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.analyzer.ResolverForProjectImpl
|
||||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.caches.resolve.IdePlatformSupport
|
||||||
import org.jetbrains.kotlin.context.GlobalContextImpl
|
import org.jetbrains.kotlin.context.GlobalContextImpl
|
||||||
import org.jetbrains.kotlin.context.withProject
|
import org.jetbrains.kotlin.context.withProject
|
||||||
import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
|
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.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.JavaClass
|
||||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
|
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
|
||||||
import org.jetbrains.kotlin.platform.JvmBuiltIns
|
import org.jetbrains.kotlin.platform.JvmBuiltIns
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
|
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
|
||||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
|
||||||
|
|
||||||
fun createModuleResolverProvider(
|
fun createModuleResolverProvider(
|
||||||
debugName: String,
|
debugName: String,
|
||||||
@@ -76,7 +74,10 @@ fun createModuleResolverProvider(
|
|||||||
|
|
||||||
val resolverForProject = ResolverForProjectImpl(
|
val resolverForProject = ResolverForProjectImpl(
|
||||||
debugName, globalContext.withProject(project), modulesToCreateResolversFor,
|
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,
|
modulesContent, jvmPlatformParameters,
|
||||||
IdeaEnvironment, builtIns,
|
IdeaEnvironment, builtIns,
|
||||||
delegateResolver, { _, c -> IDEPackagePartProvider(c.moduleContentScope) },
|
delegateResolver, { _, c -> IDEPackagePartProvider(c.moduleContentScope) },
|
||||||
@@ -123,11 +124,9 @@ fun collectAllModuleInfosFromIdeaModel(project: Project): List<IdeaModuleInfo> {
|
|||||||
return modulesSourcesInfos + librariesInfos + sdksInfos
|
return modulesSourcesInfos + librariesInfos + sdksInfos
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl): KotlinBuiltIns = when {
|
private fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl): KotlinBuiltIns {
|
||||||
settings.platform is JsPlatform -> JsPlatform.builtIns
|
val supportInstance = IdePlatformSupport.platformSupport[settings.platform] ?: return DefaultBuiltIns.Instance
|
||||||
settings.platform is JvmPlatform && settings.sdk != null -> JvmBuiltIns(sdkContext.storageManager)
|
return supportInstance.createBuiltIns(settings, sdkContext)
|
||||||
else -> DefaultBuiltIns.Instance
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllProjectSdks(): Collection<Sdk> {
|
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;
|
package org.jetbrains.kotlin.idea.project;
|
||||||
|
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
|
||||||
import com.intellij.openapi.module.Module;
|
import com.intellij.openapi.module.Module;
|
||||||
import com.intellij.openapi.roots.ModuleRootManager;
|
|
||||||
import com.intellij.openapi.roots.ProjectRootModificationTracker;
|
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.Key;
|
||||||
import com.intellij.openapi.util.Ref;
|
|
||||||
import com.intellij.psi.util.CachedValue;
|
import com.intellij.psi.util.CachedValue;
|
||||||
import com.intellij.psi.util.CachedValueProvider;
|
import com.intellij.psi.util.CachedValueProvider;
|
||||||
import com.intellij.psi.util.CachedValuesManager;
|
import com.intellij.psi.util.CachedValuesManager;
|
||||||
import com.intellij.util.Processor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.kotlin.caches.resolve.IdePlatformSupport;
|
||||||
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.resolve.TargetPlatform;
|
import org.jetbrains.kotlin.resolve.TargetPlatform;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform;
|
|
||||||
|
|
||||||
public class ProjectStructureUtil {
|
public class ProjectStructureUtil {
|
||||||
private static final Key<CachedValue<TargetPlatform>> PLATFORM_FOR_MODULE = Key.create("PLATFORM_FOR_MODULE");
|
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>() {
|
result = CachedValuesManager.getManager(module.getProject()).createCachedValue(new CachedValueProvider<TargetPlatform>() {
|
||||||
@Override
|
@Override
|
||||||
public Result<TargetPlatform> compute() {
|
public Result<TargetPlatform> compute() {
|
||||||
TargetPlatform configuredInFacet = getPlatformConfiguredInFacet(module);
|
return Result.create(IdePlatformSupport.getPlatformForModule(module),
|
||||||
TargetPlatform platform =
|
ProjectRootModificationTracker.getInstance(module.getProject()));
|
||||||
configuredInFacet != null ? configuredInFacet :
|
|
||||||
hasJsStandardLibraryInDependencies(module) ? JsPlatform.INSTANCE : JvmPlatform.INSTANCE;
|
|
||||||
return Result.create(platform, ProjectRootModificationTracker.getInstance(module.getProject()));
|
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
@@ -64,43 +49,4 @@ public class ProjectStructureUtil {
|
|||||||
|
|
||||||
return result.getValue();
|
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"
|
<extensionPoint name="androidDexer"
|
||||||
interface="org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.AndroidDexer"
|
interface="org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.AndroidDexer"
|
||||||
area="IDEA_PROJECT"/>
|
area="IDEA_PROJECT"/>
|
||||||
|
|
||||||
|
<extensionPoint name="idePlatformSupport"
|
||||||
|
interface="org.jetbrains.kotlin.caches.resolve.IdePlatformSupport"/>
|
||||||
</extensionPoints>
|
</extensionPoints>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||||
@@ -26,5 +29,9 @@
|
|||||||
<scriptTemplatesProvider id="StandardKotlinScriptTemplateProvider"
|
<scriptTemplatesProvider id="StandardKotlinScriptTemplateProvider"
|
||||||
order="last"
|
order="last"
|
||||||
implementation="org.jetbrains.kotlin.idea.script.StandardKotlinScriptTemplateProvider"/>
|
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>
|
</extensions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
|
|||||||
@@ -38,11 +38,11 @@ import org.jetbrains.kotlin.idea.versions.*
|
|||||||
import kotlin.reflect.KProperty1
|
import kotlin.reflect.KProperty1
|
||||||
|
|
||||||
private fun getDefaultTargetPlatform(module: Module, rootModel: ModuleRootModel?): TargetPlatformKind<*> {
|
private fun getDefaultTargetPlatform(module: Module, rootModel: ModuleRootModel?): TargetPlatformKind<*> {
|
||||||
if (getRuntimeLibraryVersions(module, rootModel, TargetPlatformKind.JavaScript).isNotEmpty()) {
|
for (platform in TargetPlatformKind.ALL_PLATFORMS) {
|
||||||
return TargetPlatformKind.JavaScript
|
if (platform.version == TargetPlatformVersion.NoVersion &&
|
||||||
}
|
getRuntimeLibraryVersions(module, rootModel, platform).isNotEmpty()) {
|
||||||
if (getRuntimeLibraryVersions(module, rootModel, TargetPlatformKind.Common).isNotEmpty()) {
|
return platform
|
||||||
return TargetPlatformKind.Common
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val sdk = ((rootModel ?: ModuleRootManager.getInstance(module))).sdk
|
val sdk = ((rootModel ?: ModuleRootManager.getInstance(module))).sdk
|
||||||
|
|||||||
Reference in New Issue
Block a user