Pluggable platforms in IDE plugin
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.caches.resolve
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
|
||||
import org.jetbrains.kotlin.analyzer.AnalyzerFacade
|
||||
import org.jetbrains.kotlin.analyzer.common.DefaultAnalyzerFacade
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider
|
||||
import org.jetbrains.kotlin.config.TargetPlatformKind
|
||||
import org.jetbrains.kotlin.context.GlobalContextImpl
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.JsAnalyzerFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings
|
||||
import org.jetbrains.kotlin.idea.framework.CommonLibraryKind
|
||||
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||
import org.jetbrains.kotlin.platform.JvmBuiltIns
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
|
||||
abstract class IdePlatformSupport {
|
||||
abstract val platform: TargetPlatform
|
||||
abstract val analyzerFacade: AnalyzerFacade
|
||||
abstract val libraryKind: PersistentLibraryKind<*>?
|
||||
|
||||
abstract fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl): KotlinBuiltIns
|
||||
|
||||
abstract fun isModuleForPlatform(module: Module): Boolean
|
||||
|
||||
companion object {
|
||||
val EP_NAME = ExtensionPointName.create<IdePlatformSupport>("org.jetbrains.kotlin.idePlatformSupport")
|
||||
|
||||
val platformSupport by lazy {
|
||||
Extensions.getExtensions(EP_NAME).associateBy { it.platform }
|
||||
}
|
||||
|
||||
val facades by lazy {
|
||||
Extensions.getExtensions(EP_NAME).map { it.platform to it.analyzerFacade }.toMap()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getPlatformForModule(module: Module): TargetPlatform {
|
||||
return Extensions.getExtensions(EP_NAME).find { it.isModuleForPlatform(module) }?.platform ?: JvmPlatform
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class JvmPlatformSupport : IdePlatformSupport() {
|
||||
override val platform: TargetPlatform
|
||||
get() = JvmPlatform
|
||||
|
||||
override val analyzerFacade: AnalyzerFacade
|
||||
get() = JvmAnalyzerFacade
|
||||
|
||||
override val libraryKind: PersistentLibraryKind<*>?
|
||||
get() = null
|
||||
|
||||
override fun isModuleForPlatform(module: Module): Boolean {
|
||||
val settings = KotlinFacetSettingsProvider.getInstance(module.project).getInitializedSettings(module)
|
||||
return settings.targetPlatformKind is TargetPlatformKind.Jvm
|
||||
}
|
||||
|
||||
override fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl): KotlinBuiltIns {
|
||||
return if (settings.sdk != null) JvmBuiltIns(sdkContext.storageManager) else DefaultBuiltIns.Instance
|
||||
}
|
||||
}
|
||||
|
||||
class JsPlatformSupport : IdePlatformSupport() {
|
||||
override val platform: TargetPlatform
|
||||
get() = JsPlatform
|
||||
|
||||
override val analyzerFacade: AnalyzerFacade
|
||||
get() = JsAnalyzerFacade
|
||||
|
||||
override val libraryKind: PersistentLibraryKind<*>?
|
||||
get() = JSLibraryKind
|
||||
|
||||
override fun isModuleForPlatform(module: Module): Boolean {
|
||||
val settings = KotlinFacetSettingsProvider.getInstance(module.project).getInitializedSettings(module)
|
||||
return settings.targetPlatformKind is TargetPlatformKind.JavaScript
|
||||
}
|
||||
|
||||
override fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl): KotlinBuiltIns {
|
||||
return JsPlatform.builtIns
|
||||
}
|
||||
}
|
||||
|
||||
class CommonPlatformSupport : IdePlatformSupport() {
|
||||
override val platform: TargetPlatform
|
||||
get() = TargetPlatform.Default
|
||||
|
||||
override val analyzerFacade: AnalyzerFacade
|
||||
get() = DefaultAnalyzerFacade
|
||||
|
||||
override val libraryKind: PersistentLibraryKind<*>?
|
||||
get() = CommonLibraryKind
|
||||
|
||||
override fun isModuleForPlatform(module: Module): Boolean {
|
||||
val settings = KotlinFacetSettingsProvider.getInstance(module.project).getInitializedSettings(module)
|
||||
return settings.targetPlatformKind is TargetPlatformKind.Common
|
||||
}
|
||||
|
||||
override fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl): KotlinBuiltIns {
|
||||
return DefaultBuiltIns.Instance
|
||||
}
|
||||
}
|
||||
+8
-9
@@ -29,18 +29,16 @@ import org.jetbrains.kotlin.analyzer.ResolverForProject
|
||||
import org.jetbrains.kotlin.analyzer.ResolverForProjectImpl
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.caches.resolve.IdePlatformSupport
|
||||
import org.jetbrains.kotlin.context.GlobalContextImpl
|
||||
import org.jetbrains.kotlin.context.withProject
|
||||
import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
|
||||
import org.jetbrains.kotlin.idea.project.AnalyzerFacadeProvider
|
||||
import org.jetbrains.kotlin.idea.project.IdeaEnvironment
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
|
||||
import org.jetbrains.kotlin.platform.JvmBuiltIns
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
|
||||
fun createModuleResolverProvider(
|
||||
debugName: String,
|
||||
@@ -76,7 +74,10 @@ fun createModuleResolverProvider(
|
||||
|
||||
val resolverForProject = ResolverForProjectImpl(
|
||||
debugName, globalContext.withProject(project), modulesToCreateResolversFor,
|
||||
{ module -> AnalyzerFacadeProvider.getAnalyzerFacade(module.platform ?: analysisSettings.platform) },
|
||||
{ module ->
|
||||
val platform = module.platform ?: analysisSettings.platform
|
||||
IdePlatformSupport.facades[platform] ?: throw UnsupportedOperationException("Unsupported platform $platform")
|
||||
},
|
||||
modulesContent, jvmPlatformParameters,
|
||||
IdeaEnvironment, builtIns,
|
||||
delegateResolver, { _, c -> IDEPackagePartProvider(c.moduleContentScope) },
|
||||
@@ -123,11 +124,9 @@ fun collectAllModuleInfosFromIdeaModel(project: Project): List<IdeaModuleInfo> {
|
||||
return modulesSourcesInfos + librariesInfos + sdksInfos
|
||||
}
|
||||
|
||||
private fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl): KotlinBuiltIns = when {
|
||||
settings.platform is JsPlatform -> JsPlatform.builtIns
|
||||
settings.platform is JvmPlatform && settings.sdk != null -> JvmBuiltIns(sdkContext.storageManager)
|
||||
else -> DefaultBuiltIns.Instance
|
||||
|
||||
private fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl): KotlinBuiltIns {
|
||||
val supportInstance = IdePlatformSupport.platformSupport[settings.platform] ?: return DefaultBuiltIns.Instance
|
||||
return supportInstance.createBuiltIns(settings, sdkContext)
|
||||
}
|
||||
|
||||
fun getAllProjectSdks(): Collection<Sdk> {
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.idea.project
|
||||
|
||||
import org.jetbrains.kotlin.analyzer.AnalyzerFacade
|
||||
import org.jetbrains.kotlin.analyzer.common.DefaultAnalyzerFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.JsAnalyzerFacade
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
|
||||
object AnalyzerFacadeProvider {
|
||||
//NOTE: it's convenient that JS backend doesn't have platform parameters (for now)
|
||||
// otherwise we would be forced to add casts on the call site of setupResolverForProject
|
||||
fun getAnalyzerFacade(targetPlatform: TargetPlatform): AnalyzerFacade {
|
||||
return when (targetPlatform) {
|
||||
JvmPlatform -> JvmAnalyzerFacade
|
||||
JsPlatform -> JsAnalyzerFacade
|
||||
TargetPlatform.Default -> DefaultAnalyzerFacade
|
||||
else -> throw IllegalArgumentException("Unsupported platform: $targetPlatform")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,27 +16,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.project;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ProjectRootModificationTracker;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.config.KotlinFacetSettings;
|
||||
import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider;
|
||||
import org.jetbrains.kotlin.config.TargetPlatformKind;
|
||||
import org.jetbrains.kotlin.idea.framework.JsLibraryStdDetectionUtil;
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform;
|
||||
import org.jetbrains.kotlin.caches.resolve.IdePlatformSupport;
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform;
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform;
|
||||
|
||||
public class ProjectStructureUtil {
|
||||
private static final Key<CachedValue<TargetPlatform>> PLATFORM_FOR_MODULE = Key.create("PLATFORM_FOR_MODULE");
|
||||
@@ -51,11 +39,8 @@ public class ProjectStructureUtil {
|
||||
result = CachedValuesManager.getManager(module.getProject()).createCachedValue(new CachedValueProvider<TargetPlatform>() {
|
||||
@Override
|
||||
public Result<TargetPlatform> compute() {
|
||||
TargetPlatform configuredInFacet = getPlatformConfiguredInFacet(module);
|
||||
TargetPlatform platform =
|
||||
configuredInFacet != null ? configuredInFacet :
|
||||
hasJsStandardLibraryInDependencies(module) ? JsPlatform.INSTANCE : JvmPlatform.INSTANCE;
|
||||
return Result.create(platform, ProjectRootModificationTracker.getInstance(module.getProject()));
|
||||
return Result.create(IdePlatformSupport.getPlatformForModule(module),
|
||||
ProjectRootModificationTracker.getInstance(module.getProject()));
|
||||
}
|
||||
}, false);
|
||||
|
||||
@@ -64,43 +49,4 @@ public class ProjectStructureUtil {
|
||||
|
||||
return result.getValue();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static TargetPlatform getPlatformConfiguredInFacet(@NotNull Module module) {
|
||||
KotlinFacetSettings settings = KotlinFacetSettingsProvider.Companion.getInstance(module.getProject()).getInitializedSettings(module);
|
||||
TargetPlatformKind<?> kind = settings.getTargetPlatformKind();
|
||||
if (kind instanceof TargetPlatformKind.Jvm) {
|
||||
return JvmPlatform.INSTANCE;
|
||||
}
|
||||
if (kind instanceof TargetPlatformKind.JavaScript) {
|
||||
return JsPlatform.INSTANCE;
|
||||
}
|
||||
if (kind instanceof TargetPlatformKind.Common) {
|
||||
return TargetPlatform.Default.INSTANCE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean hasJsStandardLibraryInDependencies(@NotNull final Module module) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
final Ref<Library> jsLibrary = Ref.create();
|
||||
|
||||
ModuleRootManager.getInstance(module).orderEntries().librariesOnly().forEachLibrary(new Processor<Library>() {
|
||||
@Override
|
||||
public boolean process(Library library) {
|
||||
if (JsLibraryStdDetectionUtil.INSTANCE.hasJsStdlibJar(library, false)) {
|
||||
jsLibrary.set(library);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return jsLibrary.get() != null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
<extensionPoint name="androidDexer"
|
||||
interface="org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.AndroidDexer"
|
||||
area="IDEA_PROJECT"/>
|
||||
|
||||
<extensionPoint name="idePlatformSupport"
|
||||
interface="org.jetbrains.kotlin.caches.resolve.IdePlatformSupport"/>
|
||||
</extensionPoints>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
@@ -26,5 +29,9 @@
|
||||
<scriptTemplatesProvider id="StandardKotlinScriptTemplateProvider"
|
||||
order="last"
|
||||
implementation="org.jetbrains.kotlin.idea.script.StandardKotlinScriptTemplateProvider"/>
|
||||
|
||||
<idePlatformSupport implementation="org.jetbrains.kotlin.caches.resolve.JvmPlatformSupport"/>
|
||||
<idePlatformSupport implementation="org.jetbrains.kotlin.caches.resolve.JsPlatformSupport"/>
|
||||
<idePlatformSupport implementation="org.jetbrains.kotlin.caches.resolve.CommonPlatformSupport"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -38,11 +38,11 @@ import org.jetbrains.kotlin.idea.versions.*
|
||||
import kotlin.reflect.KProperty1
|
||||
|
||||
private fun getDefaultTargetPlatform(module: Module, rootModel: ModuleRootModel?): TargetPlatformKind<*> {
|
||||
if (getRuntimeLibraryVersions(module, rootModel, TargetPlatformKind.JavaScript).isNotEmpty()) {
|
||||
return TargetPlatformKind.JavaScript
|
||||
}
|
||||
if (getRuntimeLibraryVersions(module, rootModel, TargetPlatformKind.Common).isNotEmpty()) {
|
||||
return TargetPlatformKind.Common
|
||||
for (platform in TargetPlatformKind.ALL_PLATFORMS) {
|
||||
if (platform.version == TargetPlatformVersion.NoVersion &&
|
||||
getRuntimeLibraryVersions(module, rootModel, platform).isNotEmpty()) {
|
||||
return platform
|
||||
}
|
||||
}
|
||||
|
||||
val sdk = ((rootModel ?: ModuleRootManager.getInstance(module))).sdk
|
||||
|
||||
Reference in New Issue
Block a user