From 1e80c03d4120e7a0168b414e7df5a9571a371921 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Thu, 26 Sep 2019 14:31:14 +0200 Subject: [PATCH] Fix Extensions/Components API usage in core environment for 193+ for it the com.intellij.core.JavaCoreApplicationEnvironment has to be copied to the compiler (named now KotlinCoreApplicationEnvironment) and modified accordingly --- .../KotlinCoreApplicationEnvironment.java | 64 ++ .../KotlinCoreApplicationEnvironment.java.193 | 150 ++++ .../cli/jvm/compiler/KotlinCoreEnvironment.kt | 53 +- .../jvm/compiler/KotlinCoreEnvironment.kt.193 | 748 ------------------ .../compiler/KotlinCoreProjectEnvironment.kt | 3 +- 5 files changed, 223 insertions(+), 795 deletions(-) create mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreApplicationEnvironment.java create mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreApplicationEnvironment.java.193 delete mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt.193 diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreApplicationEnvironment.java b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreApplicationEnvironment.java new file mode 100644 index 00000000000..cbb289a3139 --- /dev/null +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreApplicationEnvironment.java @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ +package org.jetbrains.kotlin.cli.jvm.compiler; + +import com.intellij.codeInsight.ContainerProvider; +import com.intellij.codeInsight.runner.JavaMainMethodProvider; +import com.intellij.core.CoreApplicationEnvironment; +import com.intellij.core.JavaCoreApplicationEnvironment; +import com.intellij.lang.MetaLanguage; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.extensions.ExtensionsArea; +import com.intellij.openapi.fileTypes.FileTypeExtensionPoint; +import com.intellij.openapi.vfs.VirtualFileSystem; +import com.intellij.psi.FileContextProvider; +import com.intellij.psi.augment.PsiAugmentProvider; +import com.intellij.psi.augment.TypeAnnotationModifier; +import com.intellij.psi.compiled.ClassFileDecompilers; +import com.intellij.psi.meta.MetaDataContributor; +import com.intellij.psi.stubs.BinaryFileStubBuilders; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem; + +// Mostly a placeholder for the functionality added to the bunch 193 +public class KotlinCoreApplicationEnvironment extends JavaCoreApplicationEnvironment { + + public static KotlinCoreApplicationEnvironment create(@NotNull Disposable parentDisposable, boolean unitTestMode) { + Extensions.cleanRootArea(parentDisposable); + registerExtensionPoints(); + return new KotlinCoreApplicationEnvironment(parentDisposable, unitTestMode); + } + + private KotlinCoreApplicationEnvironment(@NotNull Disposable parentDisposable, boolean unitTestMode) { + super(parentDisposable, unitTestMode); + } + + private static void registerExtensionPoints() { + ExtensionsArea area = Extensions.getRootArea(); + + CoreApplicationEnvironment.registerExtensionPoint(area, BinaryFileStubBuilders.EP_NAME, FileTypeExtensionPoint.class); + CoreApplicationEnvironment.registerExtensionPoint(area, FileContextProvider.EP_NAME, FileContextProvider.class); + + CoreApplicationEnvironment.registerExtensionPoint(area, MetaDataContributor.EP_NAME, MetaDataContributor.class); + CoreApplicationEnvironment.registerExtensionPoint(area, PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class); + CoreApplicationEnvironment.registerExtensionPoint(area, JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class); + + CoreApplicationEnvironment.registerExtensionPoint(area, ContainerProvider.EP_NAME, ContainerProvider.class); + CoreApplicationEnvironment.registerExtensionPoint(area, ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler.class); + + CoreApplicationEnvironment.registerExtensionPoint(area, TypeAnnotationModifier.EP_NAME, TypeAnnotationModifier.class); + CoreApplicationEnvironment.registerExtensionPoint(area, MetaLanguage.EP_NAME, MetaLanguage.class); + + IdeaExtensionPoints.INSTANCE.registerVersionSpecificAppExtensionPoints(area); + } + + @Nullable + @Override + protected VirtualFileSystem createJrtFileSystem() { + return new CoreJrtFileSystem(); + } +} \ No newline at end of file diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreApplicationEnvironment.java.193 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreApplicationEnvironment.java.193 new file mode 100644 index 00000000000..f4668aed2b9 --- /dev/null +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreApplicationEnvironment.java.193 @@ -0,0 +1,150 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ +package org.jetbrains.kotlin.cli.jvm.compiler; + +import com.intellij.codeInsight.ContainerProvider; +import com.intellij.codeInsight.JavaContainerProvider; +import com.intellij.codeInsight.folding.JavaCodeFoldingSettings; +import com.intellij.codeInsight.folding.impl.JavaCodeFoldingSettingsBase; +import com.intellij.codeInsight.folding.impl.JavaFoldingBuilderBase; +import com.intellij.codeInsight.runner.JavaMainMethodProvider; +import com.intellij.core.CoreApplicationEnvironment; +import com.intellij.core.CoreJavaDirectoryService; +import com.intellij.core.CorePsiPackageImplementationHelper; +import com.intellij.ide.highlighter.ArchiveFileType; +import com.intellij.ide.highlighter.JavaClassFileType; +import com.intellij.ide.highlighter.JavaFileType; +import com.intellij.lang.LanguageASTFactory; +import com.intellij.lang.MetaLanguage; +import com.intellij.lang.folding.LanguageFolding; +import com.intellij.lang.java.JavaLanguage; +import com.intellij.lang.java.JavaParserDefinition; +import com.intellij.navigation.ItemPresentationProviders; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.extensions.ExtensionsArea; +import com.intellij.openapi.fileTypes.FileTypeExtensionPoint; +import com.intellij.openapi.fileTypes.PlainTextFileType; +import com.intellij.openapi.fileTypes.PlainTextLanguage; +import com.intellij.openapi.fileTypes.PlainTextParserDefinition; +import com.intellij.openapi.projectRoots.JavaVersionService; +import com.intellij.openapi.vfs.VirtualFileSystem; +import com.intellij.psi.*; +import com.intellij.psi.augment.PsiAugmentProvider; +import com.intellij.psi.augment.TypeAnnotationModifier; +import com.intellij.psi.compiled.ClassFileDecompilers; +import com.intellij.psi.impl.EmptySubstitutorImpl; +import com.intellij.psi.impl.LanguageConstantExpressionEvaluator; +import com.intellij.psi.impl.PsiExpressionEvaluator; +import com.intellij.psi.impl.compiled.ClassFileStubBuilder; +import com.intellij.psi.impl.file.PsiPackageImplementationHelper; +import com.intellij.psi.impl.search.MethodSuperSearcher; +import com.intellij.psi.impl.source.tree.JavaASTFactory; +import com.intellij.psi.impl.source.tree.PlainTextASTFactory; +import com.intellij.psi.meta.MetaDataContributor; +import com.intellij.psi.presentation.java.*; +import com.intellij.psi.search.searches.SuperMethodsSearch; +import com.intellij.psi.stubs.BinaryFileStubBuilders; +import com.intellij.util.QueryExecutor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem; + +/** + * adapted from com.intellij.core.JavaCoreApplicationEnvironment + * TODO: initiate removal original from com.intellij.core since it seems that there are no usages left + */ +public class KotlinCoreApplicationEnvironment extends CoreApplicationEnvironment { + + public static KotlinCoreApplicationEnvironment create(@NotNull Disposable parentDisposable, boolean unitTestMode) { + return new KotlinCoreApplicationEnvironment(parentDisposable, unitTestMode); + } + + private KotlinCoreApplicationEnvironment(@NotNull Disposable parentDisposable, boolean unitTestMode) { + super(parentDisposable, unitTestMode); + + registerExtensionPoints(); + + registerExtensions(); + } + + private void registerExtensionPoints() { + ExtensionsArea area = Extensions.getRootArea(); + + CoreApplicationEnvironment.registerExtensionPoint(area, BinaryFileStubBuilders.EP_NAME, FileTypeExtensionPoint.class); + CoreApplicationEnvironment.registerExtensionPoint(area, FileContextProvider.EP_NAME, FileContextProvider.class); + + CoreApplicationEnvironment.registerExtensionPoint(area, MetaDataContributor.EP_NAME, MetaDataContributor.class); + CoreApplicationEnvironment.registerExtensionPoint(area, PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class); + CoreApplicationEnvironment.registerExtensionPoint(area, JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class); + + CoreApplicationEnvironment.registerExtensionPoint(area, ContainerProvider.EP_NAME, ContainerProvider.class); + CoreApplicationEnvironment.registerExtensionPoint(area, ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler.class); + + CoreApplicationEnvironment.registerExtensionPoint(area, TypeAnnotationModifier.EP_NAME, TypeAnnotationModifier.class); + CoreApplicationEnvironment.registerExtensionPoint(area, MetaLanguage.EP_NAME, MetaLanguage.class); + + IdeaExtensionPoints.INSTANCE.registerVersionSpecificAppExtensionPoints(area); + } + + private void registerExtensions() { + registerFileType(JavaClassFileType.INSTANCE, "class"); + registerFileType(JavaFileType.INSTANCE, "java"); + registerFileType(ArchiveFileType.INSTANCE, "jar;zip"); + registerFileType(PlainTextFileType.INSTANCE, "txt;sh;bat;cmd;policy;log;cgi;MF;jad;jam;htaccess"); + + addExplicitExtension(LanguageASTFactory.INSTANCE, PlainTextLanguage.INSTANCE, new PlainTextASTFactory()); + registerParserDefinition(new PlainTextParserDefinition()); + + addExplicitExtension(FileTypeFileViewProviders.INSTANCE, JavaClassFileType.INSTANCE, new ClassFileViewProviderFactory()); + addExplicitExtension(BinaryFileStubBuilders.INSTANCE, JavaClassFileType.INSTANCE, new ClassFileStubBuilder()); + + addExplicitExtension(LanguageASTFactory.INSTANCE, JavaLanguage.INSTANCE, new JavaASTFactory()); + registerParserDefinition(new JavaParserDefinition()); + addExplicitExtension(LanguageConstantExpressionEvaluator.INSTANCE, JavaLanguage.INSTANCE, new PsiExpressionEvaluator()); + + addExtension(ContainerProvider.EP_NAME, new JavaContainerProvider()); + + myApplication.registerService(PsiPackageImplementationHelper.class, new CorePsiPackageImplementationHelper()); + + myApplication.registerService(EmptySubstitutor.class, new EmptySubstitutorImpl()); + myApplication.registerService(JavaDirectoryService.class, createJavaDirectoryService()); + myApplication.registerService(JavaVersionService.class, new JavaVersionService()); + + addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiPackage.class, new PackagePresentationProvider()); + addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiClass.class, new ClassPresentationProvider()); + addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiMethod.class, new MethodPresentationProvider()); + addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiField.class, new FieldPresentationProvider()); + addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiLocalVariable.class, new VariablePresentationProvider()); + addExplicitExtension(ItemPresentationProviders.INSTANCE, PsiParameter.class, new VariablePresentationProvider()); + + registerApplicationService(JavaCodeFoldingSettings.class, new JavaCodeFoldingSettingsBase()); + addExplicitExtension(LanguageFolding.INSTANCE, JavaLanguage.INSTANCE, new JavaFoldingBuilderBase() { + @Override + protected boolean shouldShowExplicitLambdaType(@NotNull PsiAnonymousClass anonymousClass, @NotNull PsiNewExpression expression) { + return false; + } + + @Override + protected boolean isBelowRightMargin(@NotNull PsiFile file, int lineLength) { + return false; + } + }); + + registerApplicationExtensionPoint(SuperMethodsSearch.EP_NAME, QueryExecutor.class); + addExtension(SuperMethodsSearch.EP_NAME, new MethodSuperSearcher()); + } + + // overridden in upsource + protected CoreJavaDirectoryService createJavaDirectoryService() { + return new CoreJavaDirectoryService(); + } + + @Nullable + @Override + protected VirtualFileSystem createJrtFileSystem() { + return new CoreJrtFileSystem(); + } +} \ No newline at end of file diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt index 85b09e20865..17faf5b3dbd 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt @@ -16,16 +16,12 @@ package org.jetbrains.kotlin.cli.jvm.compiler -import com.intellij.codeInsight.ContainerProvider import com.intellij.codeInsight.ExternalAnnotationsManager import com.intellij.codeInsight.InferredAnnotationsManager -import com.intellij.codeInsight.runner.JavaMainMethodProvider import com.intellij.core.CoreApplicationEnvironment import com.intellij.core.CoreJavaFileManager -import com.intellij.core.JavaCoreApplicationEnvironment import com.intellij.core.JavaCoreProjectEnvironment import com.intellij.ide.highlighter.JavaFileType -import com.intellij.lang.MetaLanguage import com.intellij.lang.java.JavaParserDefinition import com.intellij.mock.MockProject import com.intellij.openapi.Disposable @@ -35,7 +31,6 @@ import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.extensions.ExtensionsArea -import com.intellij.openapi.fileTypes.FileTypeExtensionPoint import com.intellij.openapi.fileTypes.PlainTextFileType import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer @@ -46,19 +41,13 @@ import com.intellij.openapi.util.io.FileUtilRt import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.* import com.intellij.openapi.vfs.impl.ZipHandler -import com.intellij.psi.FileContextProvider import com.intellij.psi.PsiElementFinder import com.intellij.psi.PsiManager -import com.intellij.psi.augment.PsiAugmentProvider -import com.intellij.psi.augment.TypeAnnotationModifier -import com.intellij.psi.compiled.ClassFileDecompilers import com.intellij.psi.impl.JavaClassSupersImpl import com.intellij.psi.impl.PsiElementFinderImpl import com.intellij.psi.impl.PsiTreeChangePreprocessor import com.intellij.psi.impl.file.impl.JavaFileManager -import com.intellij.psi.meta.MetaDataContributor import com.intellij.psi.search.GlobalSearchScope -import com.intellij.psi.stubs.BinaryFileStubBuilders import com.intellij.psi.util.JavaClassSupers import com.intellij.util.io.URLUtil import com.intellij.util.lang.UrlClassLoader @@ -66,7 +55,6 @@ import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport import org.jetbrains.kotlin.asJava.LightClassGenerationSupport import org.jetbrains.kotlin.asJava.classes.FacadeCache -import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys @@ -129,7 +117,7 @@ class KotlinCoreEnvironment private constructor( ) { class ProjectEnvironment( - disposable: Disposable, applicationEnvironment: JavaCoreApplicationEnvironment + disposable: Disposable, applicationEnvironment: KotlinCoreApplicationEnvironment ) : KotlinCoreProjectEnvironment(disposable, applicationEnvironment) { @@ -420,7 +408,7 @@ class KotlinCoreEnvironment private constructor( private val LOG = Logger.getInstance(KotlinCoreEnvironment::class.java) private val APPLICATION_LOCK = Object() - private var ourApplicationEnvironment: JavaCoreApplicationEnvironment? = null + private var ourApplicationEnvironment: KotlinCoreApplicationEnvironment? = null private var ourProjectCount = 0 @JvmStatic @@ -465,11 +453,11 @@ class KotlinCoreEnvironment private constructor( } // used in the daemon for jar cache cleanup - val applicationEnvironment: JavaCoreApplicationEnvironment? get() = ourApplicationEnvironment + val applicationEnvironment: KotlinCoreApplicationEnvironment? get() = ourApplicationEnvironment fun getOrCreateApplicationEnvironmentForProduction( parentDisposable: Disposable, configuration: CompilerConfiguration - ): JavaCoreApplicationEnvironment { + ): KotlinCoreApplicationEnvironment { synchronized(APPLICATION_LOCK) { if (ourApplicationEnvironment == null) { val disposable = Disposer.newDisposable() @@ -510,12 +498,8 @@ class KotlinCoreEnvironment private constructor( private fun createApplicationEnvironment( parentDisposable: Disposable, configuration: CompilerConfiguration, unitTestMode: Boolean - ): JavaCoreApplicationEnvironment { - Extensions.cleanRootArea(parentDisposable) - registerAppExtensionPoints() - val applicationEnvironment = object : JavaCoreApplicationEnvironment(parentDisposable, unitTestMode) { - override fun createJrtFileSystem(): VirtualFileSystem? = CoreJrtFileSystem() - } + ): KotlinCoreApplicationEnvironment { + val applicationEnvironment = KotlinCoreApplicationEnvironment.create(parentDisposable, unitTestMode) registerApplicationExtensionPointsAndExtensionsFrom(configuration, "extensions/compiler.xml") @@ -525,27 +509,6 @@ class KotlinCoreEnvironment private constructor( return applicationEnvironment } - private fun registerAppExtensionPoints() { - val area = Extensions.getRootArea() - - CoreApplicationEnvironment.registerExtensionPoint(area, BinaryFileStubBuilders.EP_NAME, FileTypeExtensionPoint::class.java) - CoreApplicationEnvironment.registerExtensionPoint(area, FileContextProvider.EP_NAME, FileContextProvider::class.java) - - CoreApplicationEnvironment.registerExtensionPoint(area, MetaDataContributor.EP_NAME, MetaDataContributor::class.java) - CoreApplicationEnvironment.registerExtensionPoint(area, PsiAugmentProvider.EP_NAME, PsiAugmentProvider::class.java) - CoreApplicationEnvironment.registerExtensionPoint(area, JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider::class.java) - - CoreApplicationEnvironment.registerExtensionPoint(area, ContainerProvider.EP_NAME, ContainerProvider::class.java) - CoreApplicationEnvironment.registerExtensionPoint( - area, ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler::class.java - ) - - CoreApplicationEnvironment.registerExtensionPoint(area, TypeAnnotationModifier.EP_NAME, TypeAnnotationModifier::class.java) - CoreApplicationEnvironment.registerExtensionPoint(area, MetaLanguage.EP_NAME, MetaLanguage::class.java) - - IdeaExtensionPoints.registerVersionSpecificAppExtensionPoints(area) - } - private fun registerApplicationExtensionPointsAndExtensionsFrom(configuration: CompilerConfiguration, configFilePath: String) { workaroundIbmJdkStaxReportCdataEventIssue() @@ -643,7 +606,7 @@ class KotlinCoreEnvironment private constructor( } - private fun registerApplicationServicesForCLI(applicationEnvironment: JavaCoreApplicationEnvironment) { + private fun registerApplicationServicesForCLI(applicationEnvironment: KotlinCoreApplicationEnvironment) { // ability to get text from annotations xml files applicationEnvironment.registerFileType(PlainTextFileType.INSTANCE, "xml") applicationEnvironment.registerParserDefinition(JavaParserDefinition()) @@ -652,7 +615,7 @@ class KotlinCoreEnvironment private constructor( // made public for Upsource @Suppress("MemberVisibilityCanBePrivate") @JvmStatic - fun registerApplicationServices(applicationEnvironment: JavaCoreApplicationEnvironment) { + fun registerApplicationServices(applicationEnvironment: KotlinCoreApplicationEnvironment) { with(applicationEnvironment) { registerFileType(KotlinFileType.INSTANCE, "kt") registerFileType(KotlinFileType.INSTANCE, KotlinParserDefinition.STD_SCRIPT_SUFFIX) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt.193 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt.193 deleted file mode 100644 index 010f59ab76e..00000000000 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt.193 +++ /dev/null @@ -1,748 +0,0 @@ -/* - * 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.cli.jvm.compiler - -import com.intellij.codeInsight.ContainerProvider -import com.intellij.codeInsight.ExternalAnnotationsManager -import com.intellij.codeInsight.InferredAnnotationsManager -import com.intellij.codeInsight.runner.JavaMainMethodProvider -import com.intellij.core.CoreApplicationEnvironment -import com.intellij.core.CoreJavaFileManager -import com.intellij.core.JavaCoreApplicationEnvironment -import com.intellij.core.JavaCoreProjectEnvironment -import com.intellij.ide.highlighter.JavaFileType -import com.intellij.lang.MetaLanguage -import com.intellij.lang.java.JavaParserDefinition -import com.intellij.mock.MockProject -import com.intellij.openapi.Disposable -import com.intellij.openapi.application.TransactionGuard -import com.intellij.openapi.application.TransactionGuardImpl -import com.intellij.openapi.components.ServiceManager -import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.extensions.Extensions -import com.intellij.openapi.extensions.ExtensionsArea -import com.intellij.openapi.fileTypes.FileTypeExtensionPoint -import com.intellij.openapi.fileTypes.PlainTextFileType -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.Disposer -import com.intellij.openapi.util.JDOMUtil -import com.intellij.openapi.util.NotNullLazyValue -import com.intellij.openapi.util.SystemInfo -import com.intellij.openapi.util.io.FileUtilRt -import com.intellij.openapi.util.text.StringUtil -import com.intellij.openapi.vfs.* -import com.intellij.openapi.vfs.impl.ZipHandler -import com.intellij.psi.FileContextProvider -import com.intellij.psi.PsiElementFinder -import com.intellij.psi.PsiManager -import com.intellij.psi.augment.PsiAugmentProvider -import com.intellij.psi.augment.TypeAnnotationModifier -import com.intellij.psi.compiled.ClassFileDecompilers -import com.intellij.psi.impl.JavaClassSupersImpl -import com.intellij.psi.impl.PsiElementFinderImpl -import com.intellij.psi.impl.PsiTreeChangePreprocessor -import com.intellij.psi.impl.file.impl.JavaFileManager -import com.intellij.psi.meta.MetaDataContributor -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.psi.stubs.BinaryFileStubBuilders -import com.intellij.psi.util.JavaClassSupers -import com.intellij.util.io.URLUtil -import com.intellij.util.lang.UrlClassLoader -import org.jetbrains.annotations.TestOnly -import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport -import org.jetbrains.kotlin.asJava.LightClassGenerationSupport -import org.jetbrains.kotlin.asJava.classes.FacadeCache -import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade -import org.jetbrains.kotlin.asJava.finder.JavaElementFinder -import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys -import org.jetbrains.kotlin.cli.common.CliModuleVisibilityManagerImpl -import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY -import org.jetbrains.kotlin.cli.common.config.ContentRoot -import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot -import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots -import org.jetbrains.kotlin.cli.common.extensions.ScriptEvaluationExtension -import org.jetbrains.kotlin.cli.common.extensions.ShellExtension -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING -import org.jetbrains.kotlin.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.cli.common.toBooleanLenient -import org.jetbrains.kotlin.cli.jvm.JvmRuntimeVersionsConsistencyChecker -import org.jetbrains.kotlin.cli.jvm.config.* -import org.jetbrains.kotlin.cli.jvm.index.* -import org.jetbrains.kotlin.cli.jvm.javac.JavacWrapperRegistrar -import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder -import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleResolver -import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem -import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension -import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension -import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar -import org.jetbrains.kotlin.config.APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY -import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.config.JVMConfigurationKeys -import org.jetbrains.kotlin.config.languageVersionSettings -import org.jetbrains.kotlin.extensions.* -import org.jetbrains.kotlin.idea.KotlinFileType -import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension -import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache -import org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory -import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager -import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory -import org.jetbrains.kotlin.parsing.KotlinParserDefinition -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer -import org.jetbrains.kotlin.resolve.ModuleAnnotationsResolver -import org.jetbrains.kotlin.resolve.extensions.ExtraImportsProviderExtension -import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension -import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade -import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension -import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension -import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver -import org.jetbrains.kotlin.resolve.lazy.declarations.CliDeclarationProviderFactoryService -import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService -import org.jetbrains.kotlin.utils.PathUtil -import java.io.File -import java.lang.reflect.Field -import java.lang.reflect.Modifier -import java.util.zip.ZipFile -import javax.xml.stream.XMLInputFactory - -class KotlinCoreEnvironment private constructor( - val projectEnvironment: JavaCoreProjectEnvironment, - initialConfiguration: CompilerConfiguration, - configFiles: EnvironmentConfigFiles -) { - - class ProjectEnvironment( - disposable: Disposable, applicationEnvironment: JavaCoreApplicationEnvironment - ) : - KotlinCoreProjectEnvironment(disposable, applicationEnvironment) { - - private var extensionRegistered = false - - override fun preregisterServices() { - registerProjectExtensionPoints(Extensions.getArea(project)) - } - - fun registerExtensionsFromPlugins(configuration: CompilerConfiguration) { - if (!extensionRegistered) { - registerPluginExtensionPoints(project) - registerExtensionsFromPlugins(project, configuration) - extensionRegistered = true - } - } - - override fun registerJavaPsiFacade() { - with(project) { - registerService( - CoreJavaFileManager::class.java, - ServiceManager.getService(this, JavaFileManager::class.java) as CoreJavaFileManager - ) - - registerKotlinLightClassSupport(project) - - registerService(ExternalAnnotationsManager::class.java, MockExternalAnnotationsManager()) - registerService(InferredAnnotationsManager::class.java, MockInferredAnnotationsManager()) - } - - super.registerJavaPsiFacade() - } - } - - private val sourceFiles = mutableListOf() - private val rootsIndex: JvmDependenciesDynamicCompoundIndex - private val packagePartProviders = mutableListOf() - - private val classpathRootsResolver: ClasspathRootsResolver - private val initialRoots: List - - val configuration: CompilerConfiguration = initialConfiguration.apply { setupJdkClasspathRoots(configFiles) }.copy() - - init { - PersistentFSConstants::class.java.getDeclaredField("ourMaxIntellisenseFileSize") - .apply { isAccessible = true } - .setInt(null, FileUtilRt.LARGE_FOR_CONTENT_LOADING) - - val project = projectEnvironment.project - - val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) - - (projectEnvironment as? ProjectEnvironment)?.registerExtensionsFromPlugins(configuration) - // otherwise consider that project environment is properly configured before passing to the environment - // TODO: consider some asserts to check important extension points - - project.registerService(DeclarationProviderFactoryService::class.java, CliDeclarationProviderFactoryService(sourceFiles)) - - val isJvm = configFiles == EnvironmentConfigFiles.JVM_CONFIG_FILES - project.registerService(ModuleVisibilityManager::class.java, CliModuleVisibilityManagerImpl(isJvm)) - - registerProjectServicesForCLI(projectEnvironment) - - registerProjectServices(projectEnvironment.project) - - for (extension in CompilerConfigurationExtension.getInstances(project)) { - extension.updateConfiguration(configuration) - } - - sourceFiles += createKtFiles(project) - - collectAdditionalSources(project) - - sourceFiles.sortBy { it.virtualFile.path } - - val jdkHome = configuration.get(JVMConfigurationKeys.JDK_HOME) - val jrtFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL) - val javaModuleFinder = CliJavaModuleFinder(jdkHome?.path?.let { path -> - jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR) - }) - - val outputDirectory = - configuration.get(JVMConfigurationKeys.MODULES)?.singleOrNull()?.getOutputDirectory() - ?: configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)?.absolutePath - - classpathRootsResolver = ClasspathRootsResolver( - PsiManager.getInstance(project), - messageCollector, - configuration.getList(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES), - this::contentRootToVirtualFile, - javaModuleFinder, - !configuration.getBoolean(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE), - outputDirectory?.let(this::findLocalFile) - ) - - val (initialRoots, javaModules) = - classpathRootsResolver.convertClasspathRoots(configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS)) - this.initialRoots = initialRoots - - if (!configuration.getBoolean(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK) && messageCollector != null) { - JvmRuntimeVersionsConsistencyChecker.checkCompilerClasspathConsistency( - messageCollector, - configuration, - initialRoots.mapNotNull { (file, type) -> if (type == JavaRoot.RootType.BINARY) file else null } - ) - } - - val (roots, singleJavaFileRoots) = - initialRoots.partition { (file) -> file.isDirectory || file.extension != JavaFileType.DEFAULT_EXTENSION } - - // REPL and kapt2 update classpath dynamically - rootsIndex = JvmDependenciesDynamicCompoundIndex().apply { - addIndex(JvmDependenciesIndexImpl(roots)) - updateClasspathFromRootsIndex(this) - } - - (ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl).initialize( - rootsIndex, - packagePartProviders, - SingleJavaFileRootsIndex(singleJavaFileRoots), - configuration.getBoolean(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING) - ) - - project.registerService( - JavaModuleResolver::class.java, - CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList()) - ) - - val finderFactory = CliVirtualFileFinderFactory(rootsIndex) - project.registerService(MetadataFinderFactory::class.java, finderFactory) - project.registerService(VirtualFileFinderFactory::class.java, finderFactory) - - project.putUserData(APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY, fun(roots: List) { - updateClasspath(roots.map { JavaSourceRoot(it, null) }) - }) - } - - private fun collectAdditionalSources(project: MockProject) { - var unprocessedSources: Collection = sourceFiles - val processedSources = HashSet() - val processedSourcesByExtension = HashMap>() - // repeat feeding extensions with sources while new sources a being added - var sourceCollectionIterations = 0 - while (unprocessedSources.isNotEmpty()) { - if (sourceCollectionIterations++ > 10) { // TODO: consider using some appropriate global constant - throw IllegalStateException("Unable to collect additional sources in reasonable number of iterations") - } - processedSources.addAll(unprocessedSources) - val allNewSources = ArrayList() - for (extension in CollectAdditionalSourcesExtension.getInstances(project)) { - // do not feed the extension with the sources it returned on the previous iteration - val sourcesToProcess = unprocessedSources - (processedSourcesByExtension[extension] ?: emptyList()) - val newSources = extension.collectAdditionalSourcesAndUpdateConfiguration(sourcesToProcess, configuration, project) - if (newSources.isNotEmpty()) { - allNewSources.addAll(newSources) - processedSourcesByExtension[extension] = newSources - } - } - unprocessedSources = allNewSources.filterNot { processedSources.contains(it) }.distinct() - sourceFiles += unprocessedSources - } - } - - fun addKotlinSourceRoots(rootDirs: List) { - val roots = rootDirs.map { KotlinSourceRoot(it.absolutePath, isCommon = false) } - sourceFiles += createSourceFilesFromSourceRoots(configuration, project, roots) - } - - fun createPackagePartProvider(scope: GlobalSearchScope): JvmPackagePartProvider { - return JvmPackagePartProvider(configuration.languageVersionSettings, scope).apply { - addRoots(initialRoots, configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)) - packagePartProviders += this - (ModuleAnnotationsResolver.getInstance(project) as CliModuleAnnotationsResolver).addPackagePartProvider(this) - } - } - - private val VirtualFile.javaFiles: List - get() = mutableListOf().apply { - VfsUtilCore.processFilesRecursively(this@javaFiles) { file -> - if (file.fileType == JavaFileType.INSTANCE) { - add(file) - } - true - } - } - - private val allJavaFiles: List - get() = configuration.javaSourceRoots - .mapNotNull(this::findLocalFile) - .flatMap { it.javaFiles } - .map { File(it.canonicalPath) } - - fun registerJavac( - javaFiles: List = allJavaFiles, - kotlinFiles: List = sourceFiles, - arguments: Array? = null, - bootClasspath: List? = null, - sourcePath: List? = null - ): Boolean { - return JavacWrapperRegistrar.registerJavac( - projectEnvironment.project, configuration, javaFiles, kotlinFiles, arguments, bootClasspath, sourcePath, - LightClassGenerationSupport.getInstance(project) - ) - } - - private val applicationEnvironment: CoreApplicationEnvironment - get() = projectEnvironment.environment - - val project: Project - get() = projectEnvironment.project - - internal fun countLinesOfCode(sourceFiles: List): Int = - sourceFiles.sumBy { sourceFile -> - val text = sourceFile.text - StringUtil.getLineBreakCount(text) + (if (StringUtil.endsWithLineBreak(text)) 0 else 1) - } - - private fun updateClasspathFromRootsIndex(index: JvmDependenciesIndex) { - index.indexedRoots.forEach { - projectEnvironment.addSourcesToClasspath(it.file) - } - } - - fun updateClasspath(contentRoots: List): List? { - // TODO: add new Java modules to CliJavaModuleResolver - val newRoots = classpathRootsResolver.convertClasspathRoots(contentRoots).roots - - for (packagePartProvider in packagePartProviders) { - packagePartProvider.addRoots(newRoots, configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)) - } - - return rootsIndex.addNewIndexForRoots(newRoots)?.let { newIndex -> - updateClasspathFromRootsIndex(newIndex) - newIndex.indexedRoots.mapNotNull { (file) -> - VfsUtilCore.virtualToIoFile(VfsUtilCore.getVirtualFileForJar(file) ?: file) - }.toList() - }.orEmpty() - } - - private fun contentRootToVirtualFile(root: JvmContentRoot): VirtualFile? = - when (root) { - is JvmClasspathRoot -> - if (root.file.isFile) findJarRoot(root.file) else findExistingRoot(root, "Classpath entry") - is JvmModulePathRoot -> - if (root.file.isFile) findJarRoot(root.file) else findExistingRoot(root, "Java module root") - is JavaSourceRoot -> - findExistingRoot(root, "Java source root") - else -> - throw IllegalStateException("Unexpected root: $root") - } - - internal fun findLocalFile(path: String): VirtualFile? = - applicationEnvironment.localFileSystem.findFileByPath(path) - - private fun findExistingRoot(root: JvmContentRoot, rootDescription: String): VirtualFile? { - return findLocalFile(root.file.absolutePath).also { - if (it == null) { - report(STRONG_WARNING, "$rootDescription points to a non-existent location: ${root.file}") - } - } - } - - private fun findJarRoot(file: File): VirtualFile? = - applicationEnvironment.jarFileSystem.findFileByPath("$file${URLUtil.JAR_SEPARATOR}") - - private fun getSourceRootsCheckingForDuplicates(): List { - val uniqueSourceRoots = hashSetOf() - val result = mutableListOf() - - for (root in configuration.kotlinSourceRoots) { - if (!uniqueSourceRoots.add(root.path)) { - report(STRONG_WARNING, "Duplicate source root: ${root.path}") - } - result.add(root) - } - - return result - } - - fun getSourceFiles(): List = sourceFiles - - private fun createKtFiles(project: Project): List = - createSourceFilesFromSourceRoots(configuration, project, getSourceRootsCheckingForDuplicates()) - - internal fun report(severity: CompilerMessageSeverity, message: String) = configuration.report(severity, message) - - companion object { - private val LOG = Logger.getInstance(KotlinCoreEnvironment::class.java) - - private val APPLICATION_LOCK = Object() - private var ourApplicationEnvironment: JavaCoreApplicationEnvironment? = null - private var ourProjectCount = 0 - - @JvmStatic - fun createForProduction( - parentDisposable: Disposable, configuration: CompilerConfiguration, configFiles: EnvironmentConfigFiles - ): KotlinCoreEnvironment { - val appEnv = getOrCreateApplicationEnvironmentForProduction(parentDisposable, configuration) - val projectEnv = ProjectEnvironment(parentDisposable, appEnv) - val environment = KotlinCoreEnvironment(projectEnv, configuration, configFiles) - - synchronized(APPLICATION_LOCK) { - ourProjectCount++ - } - return environment - } - - @JvmStatic - fun createForProduction( - projectEnvironment: JavaCoreProjectEnvironment, configuration: CompilerConfiguration, configFiles: EnvironmentConfigFiles - ): KotlinCoreEnvironment { - val environment = KotlinCoreEnvironment(projectEnvironment, configuration, configFiles) - - if (projectEnvironment.environment == applicationEnvironment) { - // accounting for core environment disposing - synchronized(APPLICATION_LOCK) { - ourProjectCount++ - } - } - return environment - } - - @TestOnly - @JvmStatic - fun createForTests( - parentDisposable: Disposable, initialConfiguration: CompilerConfiguration, extensionConfigs: EnvironmentConfigFiles - ): KotlinCoreEnvironment { - val configuration = initialConfiguration.copy() - // Tests are supposed to create a single project and dispose it right after use - val appEnv = createApplicationEnvironment(parentDisposable, configuration, unitTestMode = true) - val projectEnv = ProjectEnvironment(parentDisposable, appEnv) - return KotlinCoreEnvironment(projectEnv, configuration, extensionConfigs) - } - - // used in the daemon for jar cache cleanup - val applicationEnvironment: JavaCoreApplicationEnvironment? get() = ourApplicationEnvironment - - fun getOrCreateApplicationEnvironmentForProduction( - parentDisposable: Disposable, configuration: CompilerConfiguration - ): JavaCoreApplicationEnvironment { - synchronized(APPLICATION_LOCK) { - if (ourApplicationEnvironment == null) { - val disposable = Disposer.newDisposable() - ourApplicationEnvironment = createApplicationEnvironment(disposable, configuration, unitTestMode = false) - ourProjectCount = 0 - Disposer.register(disposable, Disposable { - synchronized(APPLICATION_LOCK) { - ourApplicationEnvironment = null - } - }) - } - // Disposing of the environment is unsafe in production then parallel builds are enabled, but turning it off universally - // breaks a lot of tests, therefore it is disabled for production and enabled for tests - if (System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY).toBooleanLenient() != true) { - // JPS may run many instances of the compiler in parallel (there's an option for compiling independent modules in parallel in IntelliJ) - // All projects share the same ApplicationEnvironment, and when the last project is disposed, the ApplicationEnvironment is disposed as well - Disposer.register(parentDisposable, Disposable { - synchronized(APPLICATION_LOCK) { - if (--ourProjectCount <= 0) { - disposeApplicationEnvironment() - } - } - }) - } - - return ourApplicationEnvironment!! - } - } - - private fun disposeApplicationEnvironment() { - synchronized(APPLICATION_LOCK) { - val environment = ourApplicationEnvironment ?: return - ourApplicationEnvironment = null - Disposer.dispose(environment.parentDisposable) - ZipHandler.clearFileAccessorCache() - } - } - - private fun createApplicationEnvironment( - parentDisposable: Disposable, configuration: CompilerConfiguration, unitTestMode: Boolean - ): JavaCoreApplicationEnvironment { - // FIXME: no such method in 193 platform - // Extensions.cleanRootArea(parentDisposable) - registerAppExtensionPoints() - val applicationEnvironment = object : JavaCoreApplicationEnvironment(parentDisposable, unitTestMode) { - override fun createJrtFileSystem(): VirtualFileSystem? = CoreJrtFileSystem() - } - - registerApplicationExtensionPointsAndExtensionsFrom(configuration, "extensions/compiler.xml") - - registerApplicationServicesForCLI(applicationEnvironment) - registerApplicationServices(applicationEnvironment) - - return applicationEnvironment - } - - private fun registerAppExtensionPoints() { - val area = Extensions.getRootArea() - - CoreApplicationEnvironment.registerExtensionPoint(area, BinaryFileStubBuilders.EP_NAME, FileTypeExtensionPoint::class.java) - CoreApplicationEnvironment.registerExtensionPoint(area, FileContextProvider.EP_NAME, FileContextProvider::class.java) - - CoreApplicationEnvironment.registerExtensionPoint(area, MetaDataContributor.EP_NAME, MetaDataContributor::class.java) - CoreApplicationEnvironment.registerExtensionPoint(area, PsiAugmentProvider.EP_NAME, PsiAugmentProvider::class.java) - CoreApplicationEnvironment.registerExtensionPoint(area, JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider::class.java) - - CoreApplicationEnvironment.registerExtensionPoint(area, ContainerProvider.EP_NAME, ContainerProvider::class.java) - CoreApplicationEnvironment.registerExtensionPoint( - area, ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler::class.java - ) - - CoreApplicationEnvironment.registerExtensionPoint(area, TypeAnnotationModifier.EP_NAME, TypeAnnotationModifier::class.java) - CoreApplicationEnvironment.registerExtensionPoint(area, MetaLanguage.EP_NAME, MetaLanguage::class.java) - - IdeaExtensionPoints.registerVersionSpecificAppExtensionPoints(area) - } - - private fun registerApplicationExtensionPointsAndExtensionsFrom(configuration: CompilerConfiguration, configFilePath: String) { - workaroundIbmJdkStaxReportCdataEventIssue() - - fun File.hasConfigFile(configFile: String): Boolean = - if (isDirectory) File(this, "META-INF" + File.separator + configFile).exists() - else try { - ZipFile(this).use { - it.getEntry("META-INF/$configFile") != null - } - } catch (e: Throwable) { - false - } - - val pluginRoot = - configuration.get(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT)?.let(::File) - ?: PathUtil.getResourcePathForClass(this::class.java).takeIf { it.hasConfigFile(configFilePath) } - // hack for load extensions when compiler run directly from project directory (e.g. in tests) - ?: File("compiler/cli/cli-common/resources").takeIf { it.hasConfigFile(configFilePath) } - ?: throw IllegalStateException( - "Unable to find extension point configuration $configFilePath " + - "(cp:\n ${(Thread.currentThread().contextClassLoader as? UrlClassLoader)?.urls?.joinToString("\n ") { it.file }})" - ) - - CoreApplicationEnvironment.registerExtensionPointAndExtensions(pluginRoot, configFilePath, Extensions.getRootArea()) - } - - private fun workaroundIbmJdkStaxReportCdataEventIssue() { - if (!SystemInfo.isIbmJvm) return - - // On IBM JDK, XMLInputFactory does not support "report-cdata-event" property, but JDOMUtil sets it unconditionally in the - // static XML_INPUT_FACTORY field and fails with an exception (Logger.error throws exception in the compiler) if unsuccessful. - // Until this is fixed in the platform, we workaround the issue by setting that field to a value that does not attempt - // to set the unsupported property. - // See IDEA-206446 for more information - val field = JDOMUtil::class.java.getDeclaredField("XML_INPUT_FACTORY") - field.isAccessible = true - Field::class.java.getDeclaredField("modifiers") - .apply { isAccessible = true } - .setInt(field, field.modifiers and Modifier.FINAL.inv()) - field.set(null, object : NotNullLazyValue() { - override fun compute(): XMLInputFactory { - val factory: XMLInputFactory = try { - // otherwise wst can be used (in tests/dev run) - val clazz = Class.forName("com.sun.xml.internal.stream.XMLInputFactoryImpl") - clazz.newInstance() as XMLInputFactory - } catch (e: Exception) { - // ok, use random - XMLInputFactory.newFactory() - } - - factory.setProperty(XMLInputFactory.IS_COALESCING, true) - factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false) - factory.setProperty(XMLInputFactory.SUPPORT_DTD, false) - return factory - } - }) - } - - @JvmStatic - @Suppress("MemberVisibilityCanPrivate") // made public for CLI Android Lint - fun registerPluginExtensionPoints(project: MockProject) { - ExpressionCodegenExtension.registerExtensionPoint(project) - SyntheticResolveExtension.registerExtensionPoint(project) - ClassBuilderInterceptorExtension.registerExtensionPoint(project) - AnalysisHandlerExtension.registerExtensionPoint(project) - PackageFragmentProviderExtension.registerExtensionPoint(project) - StorageComponentContainerContributor.registerExtensionPoint(project) - DeclarationAttributeAltererExtension.registerExtensionPoint(project) - PreprocessedVirtualFileFactoryExtension.registerExtensionPoint(project) - JsSyntheticTranslateExtension.registerExtensionPoint(project) - CompilerConfigurationExtension.registerExtensionPoint(project) - CollectAdditionalSourcesExtension.registerExtensionPoint(project) - ExtraImportsProviderExtension.registerExtensionPoint(project) - IrGenerationExtension.registerExtensionPoint(project) - ScriptEvaluationExtension.registerExtensionPoint(project) - ShellExtension.registerExtensionPoint(project) - } - - internal fun registerExtensionsFromPlugins(project: MockProject, configuration: CompilerConfiguration) { - val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) - for (registrar in configuration.getList(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS)) { - try { - registrar.registerProjectComponents(project, configuration) - } catch (e: AbstractMethodError) { - val message = "The provided plugin ${registrar.javaClass.name} is not compatible with this version of compiler" - // Since the scripting plugin is often discovered in the compiler environment, it is often taken from the incompatible - // location, and in many cases this is not a fatal error, therefore strong warning is generated instead of exception - if (registrar.javaClass.simpleName == "ScriptingCompilerConfigurationComponentRegistrar") { - messageCollector?.report(STRONG_WARNING, "Default scripting plugin is disabled: $message") - } else { - throw IllegalStateException(message, e) - } - } - } - } - - - private fun registerApplicationServicesForCLI(applicationEnvironment: JavaCoreApplicationEnvironment) { - // ability to get text from annotations xml files - applicationEnvironment.registerFileType(PlainTextFileType.INSTANCE, "xml") - applicationEnvironment.registerParserDefinition(JavaParserDefinition()) - } - - // made public for Upsource - @Suppress("MemberVisibilityCanBePrivate") - @JvmStatic - fun registerApplicationServices(applicationEnvironment: JavaCoreApplicationEnvironment) { - with(applicationEnvironment) { - registerFileType(KotlinFileType.INSTANCE, "kt") - registerFileType(KotlinFileType.INSTANCE, KotlinParserDefinition.STD_SCRIPT_SUFFIX) - registerParserDefinition(KotlinParserDefinition()) - application.registerService(KotlinBinaryClassCache::class.java, KotlinBinaryClassCache()) - application.registerService(JavaClassSupers::class.java, JavaClassSupersImpl::class.java) - application.registerService(TransactionGuard::class.java, TransactionGuardImpl::class.java) - } - } - - @JvmStatic - fun registerProjectExtensionPoints(area: ExtensionsArea) { - CoreApplicationEnvironment.registerExtensionPoint( - area, PsiTreeChangePreprocessor.EP_NAME, PsiTreeChangePreprocessor::class.java - ) - CoreApplicationEnvironment.registerExtensionPoint(area, PsiElementFinder.EP_NAME, PsiElementFinder::class.java) - - IdeaExtensionPoints.registerVersionSpecificProjectExtensionPoints(area) - } - - // made public for Upsource - @JvmStatic - @Deprecated("Use registerProjectServices(project) instead.", ReplaceWith("registerProjectServices(projectEnvironment.project)")) - fun registerProjectServices(projectEnvironment: JavaCoreProjectEnvironment, messageCollector: MessageCollector?) { - registerProjectServices(projectEnvironment.project) - } - - // made public for Android Lint - @JvmStatic - fun registerProjectServices(project: MockProject) { - with(project) { - registerService(KotlinJavaPsiFacade::class.java, KotlinJavaPsiFacade(this)) - registerService(FacadeCache::class.java, FacadeCache(this)) - registerService(ModuleAnnotationsResolver::class.java, CliModuleAnnotationsResolver()) - } - } - - private fun registerProjectServicesForCLI(@Suppress("UNUSED_PARAMETER") projectEnvironment: JavaCoreProjectEnvironment) { - /** - * Note that Kapt may restart code analysis process, and CLI services should be aware of that. - * Use PsiManager.getModificationTracker() to ensure that all the data you cached is still valid. - */ - } - - // made public for Android Lint - @JvmStatic - fun registerKotlinLightClassSupport(project: MockProject) { - with(project) { - val traceHolder = CliTraceHolder() - val cliLightClassGenerationSupport = CliLightClassGenerationSupport(traceHolder) - val kotlinAsJavaSupport = CliKotlinAsJavaSupport(this, traceHolder) - registerService(LightClassGenerationSupport::class.java, cliLightClassGenerationSupport) - registerService(CliLightClassGenerationSupport::class.java, cliLightClassGenerationSupport) - registerService(KotlinAsJavaSupport::class.java, kotlinAsJavaSupport) - registerService(CodeAnalyzerInitializer::class.java, traceHolder) - - val area = Extensions.getArea(this) - - area.getExtensionPoint(PsiElementFinder.EP_NAME).registerExtension(JavaElementFinder(this, kotlinAsJavaSupport)) - area.getExtensionPoint(PsiElementFinder.EP_NAME).registerExtension( - PsiElementFinderImpl(this, ServiceManager.getService(this, JavaFileManager::class.java)) - ) - } - } - - private fun CompilerConfiguration.setupJdkClasspathRoots(configFiles: EnvironmentConfigFiles) { - if (getBoolean(JVMConfigurationKeys.NO_JDK)) return - - val jvmTarget = configFiles == EnvironmentConfigFiles.JVM_CONFIG_FILES - if (!jvmTarget) return - - val jdkHome = get(JVMConfigurationKeys.JDK_HOME) - val (javaRoot, classesRoots) = if (jdkHome == null) { - val javaHome = File(System.getProperty("java.home")) - put(JVMConfigurationKeys.JDK_HOME, javaHome) - - javaHome to PathUtil.getJdkClassesRootsFromCurrentJre() - } else { - jdkHome to PathUtil.getJdkClassesRoots(jdkHome) - } - - if (!CoreJrtFileSystem.isModularJdk(javaRoot)) { - if (classesRoots.isEmpty()) { - report(ERROR, "No class roots are found in the JDK path: $javaRoot") - } else { - addJvmSdkRoots(classesRoots) - } - } - } - } -} - diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreProjectEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreProjectEnvironment.kt index 1e1998dc11a..cfc8bb7da3b 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreProjectEnvironment.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreProjectEnvironment.kt @@ -16,14 +16,13 @@ package org.jetbrains.kotlin.cli.jvm.compiler -import com.intellij.core.JavaCoreApplicationEnvironment import com.intellij.core.JavaCoreProjectEnvironment import com.intellij.openapi.Disposable import com.intellij.psi.PsiManager open class KotlinCoreProjectEnvironment( disposable: Disposable, - applicationEnvironment: JavaCoreApplicationEnvironment + applicationEnvironment: KotlinCoreApplicationEnvironment ) : JavaCoreProjectEnvironment(disposable, applicationEnvironment) { override fun createCoreFileManager() = KotlinCliJavaFileManagerImpl(PsiManager.getInstance(project)) }