diff --git a/idea/src/META-INF/jvm.xml b/idea/src/META-INF/jvm.xml index 3bbfa65e53b..6faebe159d7 100644 --- a/idea/src/META-INF/jvm.xml +++ b/idea/src/META-INF/jvm.xml @@ -129,8 +129,8 @@ displayName="Incompatible API usage" implementationClass="org.jetbrains.kotlin.idea.inspections.api.IncompatibleAPIInspection"/> - + diff --git a/plugins/uast-kotlin-idea/build.gradle.kts b/plugins/uast-kotlin-idea/build.gradle.kts index 308a3a3e73a..dc1538f8dd5 100644 --- a/plugins/uast-kotlin-idea/build.gradle.kts +++ b/plugins/uast-kotlin-idea/build.gradle.kts @@ -10,6 +10,7 @@ dependencies { compile(project(":compiler:backend")) compile(project(":compiler:frontend.java")) compile(project(":idea:ide-common")) + compile(project(":idea:idea-core")) compile(project(":plugins:uast-kotlin")) compileOnly(intellijDep()) } diff --git a/plugins/uast-kotlin-idea/src/IdeaKotlinUastBindingContextProviderService.kt b/plugins/uast-kotlin-idea/src/IdeaKotlinUastResolveProviderService.kt similarity index 63% rename from plugins/uast-kotlin-idea/src/IdeaKotlinUastBindingContextProviderService.kt rename to plugins/uast-kotlin-idea/src/IdeaKotlinUastResolveProviderService.kt index 27e3c48d1ec..8b385d17cab 100644 --- a/plugins/uast-kotlin-idea/src/IdeaKotlinUastBindingContextProviderService.kt +++ b/plugins/uast-kotlin-idea/src/IdeaKotlinUastResolveProviderService.kt @@ -16,16 +16,22 @@ package org.jetbrains.uast.kotlin.internal +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.codegen.ClassBuilderMode import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.uast.kotlin.KotlinUastBindingContextProviderService +import org.jetbrains.uast.kotlin.KotlinUastResolveProviderService +import org.jetbrains.kotlin.idea.project.TargetPlatformDetector +import org.jetbrains.kotlin.idea.project.languageVersionSettings +import org.jetbrains.kotlin.idea.util.module -class IdeaKotlinUastBindingContextProviderService : KotlinUastBindingContextProviderService { +class IdeaKotlinUastResolveProviderService : KotlinUastResolveProviderService { override fun getBindingContext(element: KtElement) = element.analyze(BodyResolveMode.PARTIAL) override fun getTypeMapper(element: KtElement): KotlinTypeMapper? { @@ -34,4 +40,13 @@ class IdeaKotlinUastBindingContextProviderService : KotlinUastBindingContextProv IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false, KotlinTypeMapper.RELEASE_COROUTINES_DEFAULT ) } + + override fun isJvmElement(psiElement: PsiElement): Boolean { + val module = psiElement.module + return module == null || TargetPlatformDetector.getPlatform(module) is JvmPlatform + } + + override fun getLanguageVersionSettings(element: KtElement): LanguageVersionSettings { + return element.languageVersionSettings + } } diff --git a/plugins/uast-kotlin/build.gradle.kts b/plugins/uast-kotlin/build.gradle.kts index 1083fbe446f..b6e6bbf0f97 100644 --- a/plugins/uast-kotlin/build.gradle.kts +++ b/plugins/uast-kotlin/build.gradle.kts @@ -11,8 +11,10 @@ dependencies { compile(project(":compiler:frontend")) compile(project(":compiler:frontend.java")) compile(project(":compiler:light-classes")) - compile(project(":idea:idea-core")) - compileOnly(intellijDep()) { includeJars("openapi", "idea", "java-api", "java-impl", "platform-api", "platform-impl", "util", "extensions", "asm-all") } + + // BEWARE: Uast should not depend on IDEA. + compileOnly(intellijCoreDep()) { includeJars("intellij-core") } + compileOnly(intellijDep()) { includeJars("java-api", "java-impl", "asm-all") } testCompile(projectDist(":kotlin-test:kotlin-test-jvm")) testCompile(projectTests(":compiler:tests-common")) @@ -20,7 +22,7 @@ dependencies { testCompile(project(":compiler:util")) testCompile(project(":compiler:cli")) testCompile(projectTests(":idea:idea-test-framework")) - testCompileOnly(intellijDep()) { includeJars("java-api", "java-impl", "idea_rt") } + testCompileOnly(intellijDep()) { includeJars("java-api", "java-impl") } testRuntime(projectDist(":kotlin-reflect")) testRuntime(project(":idea:idea-android")) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt index 05b4723c75e..fe742e1db26 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt @@ -17,6 +17,7 @@ package org.jetbrains.uast.kotlin import com.intellij.lang.Language +import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.util.Key import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile @@ -27,19 +28,17 @@ import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.elements.* import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.idea.project.TargetPlatformDetector -import org.jetbrains.kotlin.idea.util.module import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.uast.* import org.jetbrains.uast.kotlin.declarations.KotlinUIdentifier import org.jetbrains.uast.kotlin.declarations.KotlinUMethod @@ -47,9 +46,11 @@ import org.jetbrains.uast.kotlin.expressions.* import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable -interface KotlinUastBindingContextProviderService { +interface KotlinUastResolveProviderService { fun getBindingContext(element: KtElement): BindingContext fun getTypeMapper(element: KtElement): KotlinTypeMapper? + fun getLanguageVersionSettings(element: KtElement): LanguageVersionSettings + fun isJvmElement(psiElement: PsiElement): Boolean } var PsiElement.destructuringDeclarationInitializer: Boolean? by UserDataProperty(Key.create("kotlin.uast.destructuringDeclarationInitializer")) @@ -64,14 +65,10 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin { return fileName.endsWith(".kt", false) || fileName.endsWith(".kts", false) } - private val PsiElement.isJvmElement - get() = try { - // Workaround for UAST used without full-fledged IDEA when ProjectFileIndex is not available - // If we can't get the module (or don't have one), act as if the current platform is JVM - val module = module - module == null || TargetPlatformDetector.getPlatform(module) is JvmPlatform - } catch (e: Exception) { - true + private val PsiElement.isJvmElement: Boolean + get() { + val resolveProvider = ServiceManager.getService(project, KotlinUastResolveProviderService::class.java) + return resolveProvider.isJvmElement(this) } override fun convertElement(element: PsiElement, parent: UElement?, requiredType: Class?): UElement? { diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.172 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.172 index 778ec161668..0591cee977c 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.172 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.172 @@ -17,6 +17,7 @@ package org.jetbrains.uast.kotlin import com.intellij.lang.Language +import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.util.Key import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile @@ -27,11 +28,10 @@ import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.elements.* import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.idea.project.TargetPlatformDetector -import org.jetbrains.kotlin.idea.util.module import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType @@ -45,9 +45,11 @@ import org.jetbrains.uast.kotlin.expressions.* import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable -interface KotlinUastBindingContextProviderService { +interface KotlinUastResolveProviderService { fun getBindingContext(element: KtElement): BindingContext fun getTypeMapper(element: KtElement): KotlinTypeMapper? + fun getLanguageVersionSettings(element: KtElement): LanguageVersionSettings + fun isJvmElement(psiElement: PsiElement): Boolean } var PsiElement.destructuringDeclarationInitializer: Boolean? by UserDataProperty(Key.create("kotlin.uast.destructuringDeclarationInitializer")) @@ -64,14 +66,10 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin { return fileName.endsWith(".kt", false) || fileName.endsWith(".kts", false) } - private val PsiElement.isJvmElement - get() = try { - // Workaround for UAST used without full-fledged IDEA when ProjectFileIndex is not available - // If we can't get the module (or don't have one), act as if the current platform is JVM - val module = module - module == null || TargetPlatformDetector.getPlatform(module) is JvmPlatform - } catch (e: Exception) { - true + private val PsiElement.isJvmElement: Boolean + get() { + val resolveProvider = ServiceManager.getService(project, KotlinUastResolveProviderService::class.java) + return resolveProvider.isJvmElement(this) } override fun convertElement(element: PsiElement, parent: UElement?, requiredType: Class?): UElement? { diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.173 index 7095d4394f5..50398d478f2 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.173 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.173 @@ -17,6 +17,7 @@ package org.jetbrains.uast.kotlin import com.intellij.lang.Language +import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.util.Key import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile @@ -27,13 +28,12 @@ import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.elements.* import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.idea.project.TargetPlatformDetector -import org.jetbrains.kotlin.idea.util.module import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType @@ -46,9 +46,11 @@ import org.jetbrains.uast.kotlin.expressions.* import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable -interface KotlinUastBindingContextProviderService { +interface KotlinUastResolveProviderService { fun getBindingContext(element: KtElement): BindingContext fun getTypeMapper(element: KtElement): KotlinTypeMapper? + fun getLanguageVersionSettings(element: KtElement): LanguageVersionSettings + fun isJvmElement(psiElement: PsiElement): Boolean } var PsiElement.destructuringDeclarationInitializer: Boolean? by UserDataProperty(Key.create("kotlin.uast.destructuringDeclarationInitializer")) @@ -63,14 +65,10 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin { return fileName.endsWith(".kt", false) || fileName.endsWith(".kts", false) } - private val PsiElement.isJvmElement - get() = try { - // Workaround for UAST used without full-fledged IDEA when ProjectFileIndex is not available - // If we can't get the module (or don't have one), act as if the current platform is JVM - val module = module - module == null || TargetPlatformDetector.getPlatform(module) is JvmPlatform - } catch (e: Exception) { - true + private val PsiElement.isJvmElement: Boolean + get() { + val resolveProvider = ServiceManager.getService(project, KotlinUastResolveProviderService::class.java) + return resolveProvider.isJvmElement(this) } override fun convertElement(element: PsiElement, parent: UElement?, requiredType: Class?): UElement? { diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/CliKotlinUastBindingContextProviderService.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/CliKotlinUastResolveProviderService.kt similarity index 62% rename from plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/CliKotlinUastBindingContextProviderService.kt rename to plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/CliKotlinUastResolveProviderService.kt index 0f55a153d4a..c317e9c5b9b 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/CliKotlinUastBindingContextProviderService.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/CliKotlinUastResolveProviderService.kt @@ -1,10 +1,16 @@ package org.jetbrains.uast.kotlin.internal import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.codegen.ClassBuilderMode import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl +import org.jetbrains.kotlin.container.ComponentProvider +import org.jetbrains.kotlin.container.get +import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.psi.KtElement @@ -12,9 +18,9 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension -import org.jetbrains.uast.kotlin.KotlinUastBindingContextProviderService +import org.jetbrains.uast.kotlin.KotlinUastResolveProviderService -class CliKotlinUastBindingContextProviderService : KotlinUastBindingContextProviderService { +class CliKotlinUastResolveProviderService : KotlinUastResolveProviderService { val Project.analysisCompletedHandler: UastAnalysisHandlerExtension? get() = getExtensions(AnalysisHandlerExtension.extensionPointName) .filterIsInstance() @@ -27,14 +33,23 @@ class CliKotlinUastBindingContextProviderService : KotlinUastBindingContextProvi override fun getTypeMapper(element: KtElement): KotlinTypeMapper? { return element.project.analysisCompletedHandler?.getTypeMapper() } + + override fun isJvmElement(psiElement: PsiElement) = true + + override fun getLanguageVersionSettings(element: KtElement): LanguageVersionSettings { + return element.project.analysisCompletedHandler?.getLanguageVersionSettings() ?: LanguageVersionSettingsImpl.DEFAULT + } } class UastAnalysisHandlerExtension : AnalysisHandlerExtension { private var context: BindingContext? = null private var typeMapper: KotlinTypeMapper? = null + private var languageVersionSettings: LanguageVersionSettings? = null fun getBindingContext() = context + fun getLanguageVersionSettings() = languageVersionSettings + fun getTypeMapper(): KotlinTypeMapper? { if (typeMapper != null) return typeMapper val bindingContext = context ?: return null @@ -47,6 +62,18 @@ class UastAnalysisHandlerExtension : AnalysisHandlerExtension { return typeMapper } + override fun doAnalysis( + project: Project, + module: ModuleDescriptor, + projectContext: ProjectContext, + files: Collection, + bindingTrace: BindingTrace, + componentProvider: ComponentProvider + ): AnalysisResult? { + languageVersionSettings = componentProvider.get() + return super.doAnalysis(project, module, projectContext, files, bindingTrace, componentProvider) + } + override fun analysisCompleted( project: Project, module: ModuleDescriptor, diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt index fedfe12e5d4..c56114458b3 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt @@ -33,7 +33,6 @@ import org.jetbrains.kotlin.asJava.toLightElements import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryPackageSourceElement @@ -202,12 +201,16 @@ internal fun KotlinType.toPsiType(lightDeclaration: PsiModifierListOwner?, conte if (this.containsLocalTypes()) return UastErrorType val project = context.project - val typeMapper = ServiceManager.getService(project, KotlinUastBindingContextProviderService::class.java) + + val typeMapper = ServiceManager.getService(project, KotlinUastResolveProviderService::class.java) .getTypeMapper(context) ?: return UastErrorType + val languageVersionSettings = ServiceManager.getService(project, KotlinUastResolveProviderService::class.java) + .getLanguageVersionSettings(context) + val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.TYPE) val typeMappingMode = if (boxed) TypeMappingMode.GENERIC_ARGUMENT else TypeMappingMode.DEFAULT - val approximatedType = TypeApproximator().approximateDeclarationType(this, true, context.languageVersionSettings) + val approximatedType = TypeApproximator().approximateDeclarationType(this, true, languageVersionSettings) typeMapper.mapType(approximatedType, signatureWriter, typeMappingMode) val signature = StringCharacterIterator(signatureWriter.toString()) @@ -281,7 +284,7 @@ internal fun KtExpression.unwrapBlockOrParenthesis(): KtExpression { internal fun KtElement.analyze(): BindingContext { if (containingFile !is KtFile) return BindingContext.EMPTY // EA-114080, EA-113475 - return ServiceManager.getService(project, KotlinUastBindingContextProviderService::class.java) + return ServiceManager.getService(project, KotlinUastResolveProviderService::class.java) ?.getBindingContext(this) ?: BindingContext.EMPTY } diff --git a/plugins/uast-kotlin/tests/AbstractKotlinUastTest.kt b/plugins/uast-kotlin/tests/AbstractKotlinUastTest.kt index ad281f07c74..ab8b7b5cb9b 100644 --- a/plugins/uast-kotlin/tests/AbstractKotlinUastTest.kt +++ b/plugins/uast-kotlin/tests/AbstractKotlinUastTest.kt @@ -25,10 +25,10 @@ import org.jetbrains.kotlin.test.TestJdkKind import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase import org.jetbrains.uast.UastLanguagePlugin import org.jetbrains.uast.evaluation.UEvaluatorExtension -import org.jetbrains.uast.kotlin.KotlinUastBindingContextProviderService +import org.jetbrains.uast.kotlin.KotlinUastResolveProviderService import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin import org.jetbrains.uast.kotlin.evaluation.KotlinEvaluatorExtension -import org.jetbrains.uast.kotlin.internal.CliKotlinUastBindingContextProviderService +import org.jetbrains.uast.kotlin.internal.CliKotlinUastResolveProviderService import org.jetbrains.uast.kotlin.internal.UastAnalysisHandlerExtension import org.jetbrains.uast.test.env.AbstractCoreEnvironment import org.jetbrains.uast.test.env.AbstractUastTest @@ -72,8 +72,8 @@ abstract class AbstractKotlinUastTest : AbstractUastTest() { .registerExtension(KotlinEvaluatorExtension()) project.registerService( - KotlinUastBindingContextProviderService::class.java, - CliKotlinUastBindingContextProviderService::class.java) + KotlinUastResolveProviderService::class.java, + CliKotlinUastResolveProviderService::class.java) } override fun createEnvironment(source: File): AbstractCoreEnvironment {