<lambda>null1 package org.jetbrains.dokka
2
3 import com.google.common.collect.ImmutableMap
4 import com.intellij.core.CoreApplicationEnvironment
5 import com.intellij.core.CoreModuleManager
6 import com.intellij.mock.MockComponentManager
7 import com.intellij.openapi.Disposable
8 import com.intellij.openapi.extensions.Extensions
9 import com.intellij.openapi.module.Module
10 import com.intellij.openapi.module.ModuleManager
11 import com.intellij.openapi.project.Project
12 import com.intellij.openapi.roots.OrderEnumerationHandler
13 import com.intellij.openapi.roots.ProjectFileIndex
14 import com.intellij.openapi.roots.ProjectRootManager
15 import com.intellij.openapi.util.Disposer
16 import com.intellij.openapi.vfs.StandardFileSystems
17 import com.intellij.psi.PsiElement
18 import com.intellij.psi.impl.source.javadoc.JavadocManagerImpl
19 import com.intellij.psi.javadoc.CustomJavadocTagProvider
20 import com.intellij.psi.javadoc.JavadocManager
21 import com.intellij.psi.javadoc.JavadocTagInfo
22 import com.intellij.psi.search.GlobalSearchScope
23 import org.jetbrains.kotlin.analyzer.*
24 import org.jetbrains.kotlin.builtins.KotlinBuiltIns
25 import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns
26 import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
27 import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
28 import org.jetbrains.kotlin.cli.common.config.ContentRoot
29 import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
30 import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot
31 import org.jetbrains.kotlin.cli.common.messages.MessageCollector
32 import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
33 import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
34 import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
35 import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
36 import org.jetbrains.kotlin.cli.jvm.config.*
37 import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
38 import org.jetbrains.kotlin.config.*
39 import org.jetbrains.kotlin.container.getService
40 import org.jetbrains.kotlin.container.tryGetService
41 import org.jetbrains.kotlin.context.ProjectContext
42 import org.jetbrains.kotlin.context.withModule
43 import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
44 import org.jetbrains.kotlin.descriptors.ModuleDescriptor
45 import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
46 import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
47 import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
48 import org.jetbrains.kotlin.name.Name
49 import org.jetbrains.kotlin.platform.TargetPlatform
50 import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
51 import org.jetbrains.kotlin.platform.konan.KonanPlatforms
52 import org.jetbrains.kotlin.psi.*
53 import org.jetbrains.kotlin.resolve.BindingContext
54 import org.jetbrains.kotlin.resolve.BindingTrace
55 import org.jetbrains.kotlin.resolve.CompilerEnvironment
56 import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
57 import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
58 import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
59 import org.jetbrains.kotlin.resolve.jvm.JvmResolverForModuleFactory
60 import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
61 import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
62 import org.jetbrains.kotlin.resolve.lazy.ResolveSession
63 import org.jetbrains.kotlin.types.KotlinType
64 import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice
65 import org.jetbrains.kotlin.util.slicedMap.WritableSlice
66 import java.io.File
67
68 /**
69 * Kotlin as a service entry point
70 *
71 * Configures environment, analyses files and provides facilities to perform code processing without emitting bytecode
72 *
73 * $messageCollector: required by compiler infrastructure and will receive all compiler messages
74 * $body: optional and can be used to configure environment without creating local variable
75 */
76 class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable {
77 val configuration = CompilerConfiguration()
78
79 init {
80 configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
81 }
82
83 fun createCoreEnvironment(): KotlinCoreEnvironment {
84 System.setProperty("idea.io.use.fallback", "true")
85 val environment = KotlinCoreEnvironment.createForProduction(this, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
86 val projectComponentManager = environment.project as MockComponentManager
87
88 val projectFileIndex = CoreProjectFileIndex(environment.project,
89 environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS))
90
91 val moduleManager = object : CoreModuleManager(environment.project, this) {
92 override fun getModules(): Array<out Module> = arrayOf(projectFileIndex.module)
93 }
94
95 CoreApplicationEnvironment.registerComponentInstance(projectComponentManager.picoContainer,
96 ModuleManager::class.java, moduleManager)
97
98 Extensions.registerAreaClass("IDEA_MODULE", null)
99 CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(),
100 OrderEnumerationHandler.EP_NAME, OrderEnumerationHandler.Factory::class.java)
101
102 CoreApplicationEnvironment.registerExtensionPoint(Extensions.getArea(environment.project),
103 JavadocTagInfo.EP_NAME, JavadocTagInfo::class.java)
104 CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(),
105 CustomJavadocTagProvider.EP_NAME, CustomJavadocTagProvider::class.java)
106
107 projectComponentManager.registerService(ProjectFileIndex::class.java,
108 projectFileIndex)
109 projectComponentManager.registerService(ProjectRootManager::class.java,
110 CoreProjectRootManager(projectFileIndex))
111 projectComponentManager.registerService(JavadocManager::class.java,
112 JavadocManagerImpl(environment.project))
113 projectComponentManager.registerService(CustomJavadocTagProvider::class.java,
114 CustomJavadocTagProvider { emptyList() })
115 return environment
116 }
117
118 fun createSourceModuleSearchScope(project: Project, sourceFiles: List<KtFile>): GlobalSearchScope {
119 // TODO: Fix when going to implement dokka for JS
120 return TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles)
121 }
122
123
124 fun createResolutionFacade(environment: KotlinCoreEnvironment): Pair<DokkaResolutionFacade, DokkaResolutionFacade> {
125
126 val projectContext = ProjectContext(environment.project, "Dokka")
127 val sourceFiles = environment.getSourceFiles()
128
129
130 val library = object : ModuleInfo {
131 override val name: Name = Name.special("<library>")
132 override val platform: TargetPlatform
133 get() = JvmPlatforms.defaultJvmPlatform
134 override val analyzerServices: PlatformDependentAnalyzerServices =
135 JvmPlatformAnalyzerServices
136 override fun dependencies(): List<ModuleInfo> = listOf(this)
137 }
138 val module = object : ModuleInfo {
139 override val name: Name = Name.special("<module>")
140 override val platform: TargetPlatform
141 get() = JvmPlatforms.defaultJvmPlatform
142 override val analyzerServices: PlatformDependentAnalyzerServices =
143 JvmPlatformAnalyzerServices
144 override fun dependencies(): List<ModuleInfo> = listOf(this, library)
145 }
146
147 val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles)
148
149 val builtIns = JvmBuiltIns(
150 projectContext.storageManager,
151 JvmBuiltIns.Kind.FROM_CLASS_LOADER
152 )
153
154
155 val javaRoots = classpath
156 .mapNotNull {
157 val rootFile = when {
158 it.extension == "jar" ->
159 StandardFileSystems.jar().findFileByPath("${it.absolutePath}${"!/"}")
160 else ->
161 StandardFileSystems.local().findFileByPath(it.absolutePath)
162 }
163
164 rootFile?.let { JavaRoot(it, JavaRoot.RootType.BINARY) }
165 }
166
167 val resolverForProject = object : AbstractResolverForProject<ModuleInfo>(
168 "Dokka",
169 projectContext,
170 modules = listOf(module, library)
171 ) {
172 override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> =
173 when (module) {
174 library -> ModuleContent(module, emptyList(), GlobalSearchScope.notScope(sourcesScope))
175 module -> ModuleContent(module, emptyList(), sourcesScope)
176 else -> throw IllegalArgumentException("Unexpected module info")
177 }
178
179 override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = builtIns
180
181 override fun createResolverForModule(
182 descriptor: ModuleDescriptor,
183 moduleInfo: ModuleInfo
184 ): ResolverForModule = JvmResolverForModuleFactory(
185 JvmPlatformParameters({ content ->
186 JvmPackagePartProvider(
187 configuration.languageVersionSettings,
188 content.moduleContentScope
189 )
190 .apply {
191 addRoots(javaRoots, messageCollector)
192 }
193 }, {
194 val file = (it as JavaClassImpl).psi.containingFile.virtualFile
195 if (file in sourcesScope)
196 module
197 else
198 library
199 }),
200 CompilerEnvironment,
201 KonanPlatforms.defaultKonanPlatform
202 ).createResolverForModule(
203 descriptor as ModuleDescriptorImpl,
204 projectContext.withModule(descriptor),
205 modulesContent(moduleInfo),
206 this,
207 LanguageVersionSettingsImpl.DEFAULT
208 )
209
210 override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null
211 }
212
213 val resolverForLibrary = resolverForProject.resolverForModule(library) // Required before module to initialize library properly
214 val resolverForModule = resolverForProject.resolverForModule(module)
215 val libraryModuleDescriptor = resolverForProject.descriptorForModule(library)
216 val moduleDescriptor = resolverForProject.descriptorForModule(module)
217 builtIns.initialize(moduleDescriptor, true)
218 val libraryResolutionFacade = DokkaResolutionFacade(environment.project, libraryModuleDescriptor, resolverForLibrary)
219 val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule)
220 val projectComponentManager = environment.project as MockComponentManager
221 projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created))
222
223 return created to libraryResolutionFacade
224 }
225
226 fun loadLanguageVersionSettings(languageVersionString: String?, apiVersionString: String?) {
227 val languageVersion = LanguageVersion.fromVersionString(languageVersionString) ?: LanguageVersion.LATEST_STABLE
228 val apiVersion = apiVersionString?.let { ApiVersion.parse(it) } ?: ApiVersion.createByLanguageVersion(languageVersion)
229 configuration.languageVersionSettings = LanguageVersionSettingsImpl(languageVersion, apiVersion)
230 }
231
232 /**
233 * Classpath for this environment.
234 */
235 val classpath: List<File>
236 get() = configuration.jvmClasspathRoots
237
238 /**
239 * Adds list of paths to classpath.
240 * $paths: collection of files to add
241 */
242 fun addClasspath(paths: List<File>) {
243 configuration.addJvmClasspathRoots(paths)
244 }
245
246 /**
247 * Adds path to classpath.
248 * $path: path to add
249 */
250 fun addClasspath(path: File) {
251 configuration.addJvmClasspathRoot(path)
252 }
253
254 /**
255 * List of source roots for this environment.
256 */
257 val sources: List<String>
258 get() = configuration.get(CLIConfigurationKeys.CONTENT_ROOTS)
259 ?.filterIsInstance<KotlinSourceRoot>()
260 ?.map { it.path } ?: emptyList()
261
262 /**
263 * Adds list of paths to source roots.
264 * $list: collection of files to add
265 */
266 fun addSources(list: List<String>) {
267 list.forEach {
268 configuration.addKotlinSourceRoot(it)
269 val file = File(it)
270 if (file.isDirectory || file.extension == ".java") {
271 configuration.addJavaSourceRoot(file)
272 }
273 }
274 }
275
276 fun addRoots(list: List<ContentRoot>) {
277 configuration.addAll(CLIConfigurationKeys.CONTENT_ROOTS, list)
278 }
279
280 /**
281 * Disposes the environment and frees all associated resources.
282 */
283 override fun dispose() {
284 Disposer.dispose(this)
285 }
286 }
287
contentRootFromPathnull288 fun contentRootFromPath(path: String): ContentRoot {
289 val file = File(path)
290 return if (file.extension == "java") JavaSourceRoot(file, null) else KotlinSourceRoot(path, false)
291 }
292
293
294 class DokkaResolutionFacade(override val project: Project,
295 override val moduleDescriptor: ModuleDescriptor,
296 val resolverForModule: ResolverForModule) : ResolutionFacade {
analyzeWithAllCompilerChecksnull297 override fun analyzeWithAllCompilerChecks(elements: Collection<KtElement>): AnalysisResult {
298 throw UnsupportedOperationException()
299 }
300
tryGetFrontendServicenull301 override fun <T : Any> tryGetFrontendService(element: PsiElement, serviceClass: Class<T>): T? {
302 return resolverForModule.componentProvider.tryGetService(serviceClass)
303 }
304
resolveToDescriptornull305 override fun resolveToDescriptor(declaration: KtDeclaration, bodyResolveMode: BodyResolveMode): DeclarationDescriptor {
306 return resolveSession.resolveToDescriptor(declaration)
307 }
308
analyzenull309 override fun analyze(elements: Collection<KtElement>, bodyResolveMode: BodyResolveMode): BindingContext {
310 throw UnsupportedOperationException()
311 }
312
313 val resolveSession: ResolveSession get() = getFrontendService(ResolveSession::class.java)
314
analyzenull315 override fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode): BindingContext {
316 if (element is KtDeclaration) {
317 val descriptor = resolveToDescriptor(element)
318 return object : BindingContext {
319 override fun <K : Any?, V : Any?> getKeys(p0: WritableSlice<K, V>?): Collection<K> {
320 throw UnsupportedOperationException()
321 }
322
323 override fun getType(p0: KtExpression): KotlinType? {
324 throw UnsupportedOperationException()
325 }
326
327 override fun <K : Any?, V : Any?> get(slice: ReadOnlySlice<K, V>?, key: K): V? {
328 if (key != element) {
329 throw UnsupportedOperationException()
330 }
331 return when {
332 slice == BindingContext.DECLARATION_TO_DESCRIPTOR -> descriptor as V
333 slice == BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER && (element as KtParameter).hasValOrVar() -> descriptor as V
334 else -> null
335 }
336 }
337
338 override fun getDiagnostics(): Diagnostics {
339 throw UnsupportedOperationException()
340 }
341
342 override fun addOwnDataTo(p0: BindingTrace, p1: Boolean) {
343 throw UnsupportedOperationException()
344 }
345
346 override fun <K : Any?, V : Any?> getSliceContents(p0: ReadOnlySlice<K, V>): ImmutableMap<K, V> {
347 throw UnsupportedOperationException()
348 }
349
350 }
351 }
352 throw UnsupportedOperationException()
353 }
354
getFrontendServicenull355 override fun <T : Any> getFrontendService(element: PsiElement, serviceClass: Class<T>): T {
356 throw UnsupportedOperationException()
357 }
358
getFrontendServicenull359 override fun <T : Any> getFrontendService(serviceClass: Class<T>): T {
360 return resolverForModule.componentProvider.getService(serviceClass)
361 }
362
getFrontendServicenull363 override fun <T : Any> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T {
364 return resolverForModule.componentProvider.getService(serviceClass)
365 }
366
getIdeServicenull367 override fun <T : Any> getIdeService(serviceClass: Class<T>): T {
368 throw UnsupportedOperationException()
369 }
370
371 }
372