diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.java b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.java index e271f29efe7..509156005b0 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.java +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.java @@ -77,6 +77,9 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments { @ValueDescription("") public String declarationsOutputPath; + @Argument(value = "Xload-script-configs", description = "Load script configuration files from project directory tree") + public boolean loadScriptConfigs; + // Paths to output directories for friend modules. public String[] friendPaths; diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt index 9d21a720905..76015bd38a0 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt @@ -284,6 +284,7 @@ class K2JVMCompiler : CLICompiler() { configuration.put(JVMConfigurationKeys.INHERIT_MULTIFILE_PARTS, arguments.inheritMultifileParts) configuration.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage) configuration.put(CLIConfigurationKeys.REPORT_PERF, arguments.reportPerf) + configuration.put(JVMConfigurationKeys.LOAD_SCRIPT_CONFIGS, arguments.loadScriptConfigs) arguments.declarationsOutputPath?.let { configuration.put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) } } 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 ce08146a870..c9001648fd6 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 @@ -138,12 +138,21 @@ class KotlinCoreEnvironment private constructor( KotlinScriptDefinitionProvider.getInstance(project).let { scriptDefinitionProvider -> scriptDefinitionProvider.scriptDefinitions = configuration.getList(JVMConfigurationKeys.SCRIPT_DEFINITIONS) - .ifEmpty { listOf(StandardScriptDefinition) } + .ifEmpty { + if (configuration.get(JVMConfigurationKeys.LOAD_SCRIPT_CONFIGS) ?: false) + loadScriptConfigsFromProjectRoot(File(project.basePath ?: ".")).let { configs -> + val kotlinEnvVars = generateKotlinScriptClasspathEnvVars(project) + configs.map { KotlinConfigurableScriptDefinition(it, kotlinEnvVars) } + StandardScriptDefinition + } + else null + ?: listOf(StandardScriptDefinition) + } configuration.addJvmClasspathRoots( sourceFiles - .mapNotNull { src -> src.virtualFile?.let { scriptDefinitionProvider.findScriptDefinition(it) } } - .flatMap { it.getScriptDependenciesClasspath().map { File(it).canonicalFile } } + .mapNotNull { src -> src.virtualFile } + .flatMap { getScriptCombinedClasspath(it, project) } + .map { File(it).canonicalFile } .distinct()) } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java b/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java index 796805f9d64..952b7a681ae 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java @@ -64,6 +64,9 @@ public class JVMConfigurationKeys { public static final CompilerConfigurationKey> MODULES = CompilerConfigurationKey.create("module data"); + public static final CompilerConfigurationKey LOAD_SCRIPT_CONFIGS = + CompilerConfigurationKey.create("Load script configuration files from project directory tree"); + public static final CompilerConfigurationKey> FRIEND_PATHS = CompilerConfigurationKey.create("friend module paths"); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinConfigurableScriptDefinition.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinConfigurableScriptDefinition.kt index 517d144db16..79e1bf47232 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinConfigurableScriptDefinition.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinConfigurableScriptDefinition.kt @@ -30,7 +30,10 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.parsing.KotlinParserDefinition import org.jetbrains.kotlin.psi.KtScript import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.utils.KotlinPaths +import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir import org.jetbrains.kotlin.utils.PathUtil +import java.io.File class KotlinConfigurableScriptDefinition(val config: KotlinScriptConfig, val environmentVars: Map>?) : KotlinScriptDefinition { @@ -73,16 +76,26 @@ internal fun List.evalWithVars(varsMap: Map>?): Lis } } -fun generateKotlinScriptClasspathEnvVarsForCompiler(project: Project): Map> { - val paths = PathUtil.getKotlinPathsForCompiler() - return mapOf("kotlin-runtime" to listOf(paths.runtimePath.canonicalPath), - "project-root" to listOf(project.basePath ?: "."), - "jdk" to PathUtil.getJdkClassesRoots().map { it.canonicalPath }) -} +fun generateKotlinScriptClasspathEnvVars(project: Project, kotlinHomeDir: File? = null): Map> = + generateKotlinScriptClasspathEnvVarsFromPaths( + project, + kotlinHomeDir?.let { KotlinPathsFromHomeDir(it) } ?: tryFindKotlinPathsForScriptClasspathEnvVars(project)) + +private fun tryFindKotlinPathsForScriptClasspathEnvVars(project: Project): KotlinPaths? = + sequenceOf( { PathUtil.getKotlinPathsForIdeaPlugin() }, + { PathUtil.getKotlinPathsForJpsPlugin() }, + { PathUtil.getKotlinPathsForCompiler() }, + { KotlinPathsFromHomeDir(File(project.basePath ?: ".")) }, + // note: these are only usable when debugging kotlin project + // TODO: replace with more reliable mechanism + { KotlinPathsFromHomeDir(File(PathUtil.getPathUtilJar().parentFile.parentFile.parentFile, "dist/kotlinc")) }) + .map { it() } + .firstOrNull { it.runtimePath.exists() } + +private fun generateKotlinScriptClasspathEnvVarsFromPaths(project: Project, paths: KotlinPaths?): Map> = + mapOf("kotlin-runtime" to (paths?.run { listOf(runtimePath.canonicalPath) } ?: emptyList()), + "kotlin-reflect" to (paths?.run { listOf(reflectPath.canonicalPath) } ?: emptyList()), + "project-root" to listOf(project.basePath ?: "."), + "jdk" to PathUtil.getJdkClassesRoots().map { it.canonicalPath }) + .filterNot { it.value.isEmpty() } -fun generateKotlinScriptClasspathEnvVarsForIdea(project: Project): Map> { - val paths = PathUtil.getKotlinPathsForIdeaPlugin() - return mapOf("kotlin-runtime" to listOf(paths.runtimePath.canonicalPath), - "project-root" to listOf(project.basePath ?: "."), - "jdk" to PathUtil.getJdkClassesRoots().map { it.canonicalPath }) -} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptExtraImportsProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptExtraImportsProvider.kt index 9a079083ef4..3184c450a35 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptExtraImportsProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptExtraImportsProvider.kt @@ -26,12 +26,12 @@ import kotlin.concurrent.write class KotlinScriptExtraImportsProvider(val project: Project) { private val lock = ReentrantReadWriteLock() private val cache = hashMapOf>() - private val envVars: Map> by lazy { generateKotlinScriptClasspathEnvVarsForIdea(project) } + private val envVars: Map> by lazy { generateKotlinScriptClasspathEnvVars(project) } fun isExtraImportsConfig(file: VirtualFile): Boolean = file.name.endsWith(IMPORTSFILEEXTENSION) fun getExtraImports(file: VirtualFile): List = lock.read { - if (file.isInLocalFileSystem) + if (file.isValid) cache.getOrPut(file) { file.parent.findFileByRelativePath(file.name + IMPORTSFILEEXTENSION)?.let { loadScriptExtraImportConfigs(it.inputStream).map { KotlinScriptExtraImportFromConfig(it, envVars) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/getScriptDefinition.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/getScriptDefinition.kt index 2467a8013c5..bacd8b88268 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/getScriptDefinition.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/getScriptDefinition.kt @@ -35,9 +35,13 @@ fun getScriptExtraImports(psiFile: PsiFile): List = } ?: emptyList() fun getScriptCombinedClasspath(file: VirtualFile, project: Project): List = - (getScriptDefinition(file, project)?.getScriptDependenciesClasspath() ?: emptyList()) + - getScriptExtraImports(file, project).flatMap { it.classpath } + getScriptDefinition(file, project)?.run { + getScriptDependenciesClasspath() + + getScriptExtraImports(file, project).flatMap { it.classpath } + } ?: emptyList() fun getScriptCombinedClasspath(psiFile: PsiFile): List = - (getScriptDefinition(psiFile) ?.getScriptDependenciesClasspath() ?: emptyList()) + - getScriptExtraImports(psiFile).flatMap { it.classpath } + getScriptDefinition(psiFile)?.run { + getScriptDependenciesClasspath() + + getScriptExtraImports(psiFile).flatMap { it.classpath } + } ?: emptyList() diff --git a/compiler/testData/cli/jvm/extraHelp.out b/compiler/testData/cli/jvm/extraHelp.out index 6aa3bb1387b..18fed94cde4 100644 --- a/compiler/testData/cli/jvm/extraHelp.out +++ b/compiler/testData/cli/jvm/extraHelp.out @@ -8,6 +8,7 @@ where advanced options include: -Xallow-kotlin-package Allow compiling code in package 'kotlin' -Xskip-metadata-version-check Try loading binary incompatible classes, may cause crashes -Xdump-declarations-to Path to JSON file to dump Java to Kotlin declaration mappings + -Xload-script-configs Load script configuration files from project directory tree -Xno-inline Disable method inlining -Xrepeat Repeat compilation (for performance analysis) -Xplugin Load plugins from the given classpath diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/getModuleInfo.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/getModuleInfo.kt index 7e4f803426c..9bdcbb3d44d 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/getModuleInfo.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/getModuleInfo.kt @@ -29,7 +29,6 @@ import org.jetbrains.kotlin.asJava.KtLightElement import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider import org.jetbrains.kotlin.script.getScriptDefinition import org.jetbrains.kotlin.script.getScriptExtraImports import org.jetbrains.kotlin.utils.sure diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/script/KotlinScriptConfigurationManager.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/script/KotlinScriptConfigurationManager.kt index 17cd99649ad..0d301b556ce 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/script/KotlinScriptConfigurationManager.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/script/KotlinScriptConfigurationManager.kt @@ -41,7 +41,7 @@ class KotlinScriptConfigurationManager(private val project: Project, private val kotlinScriptDependenciesIndexableSetContributor: KotlinScriptDependenciesIndexableSetContributor? ) : AbstractProjectComponent(project) { - private val kotlinEnvVars: Map> by lazy { generateKotlinScriptClasspathEnvVarsForIdea(myProject) } + private val kotlinEnvVars: Map> by lazy { generateKotlinScriptClasspathEnvVars(myProject) } init { reloadScriptDefinitions()