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