Implement resolve top-level functions and props from classloader
#KT-33892 fixed
This commit is contained in:
@@ -534,6 +534,7 @@ tasks {
|
|||||||
dependsOn(":kotlin-script-util:test")
|
dependsOn(":kotlin-script-util:test")
|
||||||
dependsOn(":kotlin-scripting-compiler:test")
|
dependsOn(":kotlin-scripting-compiler:test")
|
||||||
dependsOn(":kotlin-scripting-common:test")
|
dependsOn(":kotlin-scripting-common:test")
|
||||||
|
dependsOn(":kotlin-scripting-jvm:test")
|
||||||
dependsOn(":kotlin-scripting-jvm-host-test:test")
|
dependsOn(":kotlin-scripting-jvm-host-test:test")
|
||||||
dependsOn(":kotlin-scripting-jsr223-test:test")
|
dependsOn(":kotlin-scripting-jsr223-test:test")
|
||||||
dependsOn(":kotlin-scripting-jvm-host-test:embeddableTest")
|
dependsOn(":kotlin-scripting-jvm-host-test:embeddableTest")
|
||||||
|
|||||||
@@ -25,14 +25,11 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.LOGGING
|
|||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
|
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartProviderBase
|
||||||
import org.jetbrains.kotlin.load.kotlin.loadModuleMapping
|
import org.jetbrains.kotlin.load.kotlin.loadModuleMapping
|
||||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping
|
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping
|
||||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.PackageParts
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
|
||||||
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPartProvider
|
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.EOFException
|
import java.io.EOFException
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
@@ -40,49 +37,10 @@ import java.io.PrintStream
|
|||||||
class JvmPackagePartProvider(
|
class JvmPackagePartProvider(
|
||||||
languageVersionSettings: LanguageVersionSettings,
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
private val scope: GlobalSearchScope
|
private val scope: GlobalSearchScope
|
||||||
) : PackagePartProvider, MetadataPartProvider {
|
) : JvmPackagePartProviderBase<VirtualFile>() {
|
||||||
private data class ModuleMappingInfo(val root: VirtualFile, val mapping: ModuleMapping, val name: String)
|
|
||||||
|
|
||||||
private val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings)
|
private val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings)
|
||||||
|
|
||||||
private val loadedModules: MutableList<ModuleMappingInfo> = SmartList()
|
override val loadedModules: MutableList<ModuleMappingInfo<VirtualFile>> = SmartList()
|
||||||
|
|
||||||
override fun findPackageParts(packageFqName: String): List<String> {
|
|
||||||
val rootToPackageParts = getPackageParts(packageFqName)
|
|
||||||
if (rootToPackageParts.isEmpty()) return emptyList()
|
|
||||||
|
|
||||||
val result = linkedSetOf<String>()
|
|
||||||
val visitedMultifileFacades = linkedSetOf<String>()
|
|
||||||
for ((_, packageParts) in rootToPackageParts) {
|
|
||||||
for (name in packageParts.parts) {
|
|
||||||
val facadeName = packageParts.getMultifileFacadeName(name)
|
|
||||||
if (facadeName == null || facadeName !in visitedMultifileFacades) {
|
|
||||||
result.add(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
packageParts.parts.mapNotNullTo(visitedMultifileFacades, packageParts::getMultifileFacadeName)
|
|
||||||
}
|
|
||||||
return result.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun findMetadataPackageParts(packageFqName: String): List<String> =
|
|
||||||
getPackageParts(packageFqName).values.flatMap(PackageParts::metadataParts).distinct()
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
private fun getPackageParts(packageFqName: String): Map<VirtualFile, PackageParts> {
|
|
||||||
val result = mutableMapOf<VirtualFile, PackageParts>()
|
|
||||||
for ((root, mapping) in loadedModules) {
|
|
||||||
val newParts = mapping.findPackageParts(packageFqName) ?: continue
|
|
||||||
result[root]?.let { parts -> parts += newParts } ?: result.put(root, newParts)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getAnnotationsOnBinaryModule(moduleName: String): List<ClassId> {
|
|
||||||
return loadedModules.mapNotNull { (_, mapping, name) ->
|
|
||||||
if (name == moduleName) mapping.moduleData.annotations.map(ClassId::fromString) else null
|
|
||||||
}.flatten()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addRoots(roots: List<JavaRoot>, messageCollector: MessageCollector) {
|
fun addRoots(roots: List<JavaRoot>, messageCollector: MessageCollector) {
|
||||||
for ((root, type) in roots) {
|
for ((root, type) in roots) {
|
||||||
@@ -93,29 +51,40 @@ class JvmPackagePartProvider(
|
|||||||
for (moduleFile in metaInf.children) {
|
for (moduleFile in metaInf.children) {
|
||||||
if (!moduleFile.name.endsWith(ModuleMapping.MAPPING_FILE_EXT)) continue
|
if (!moduleFile.name.endsWith(ModuleMapping.MAPPING_FILE_EXT)) continue
|
||||||
|
|
||||||
try {
|
tryLoadModuleMapping(
|
||||||
val mapping = ModuleMapping.loadModuleMapping(
|
{ moduleFile.contentsToByteArray() }, moduleFile.toString(), moduleFile.path,
|
||||||
moduleFile.contentsToByteArray(), moduleFile.toString(), deserializationConfiguration
|
deserializationConfiguration, messageCollector
|
||||||
) { incompatibleVersion ->
|
)?.let {
|
||||||
messageCollector.report(
|
loadedModules.add(ModuleMappingInfo(root, it, moduleFile.nameWithoutExtension))
|
||||||
ERROR,
|
|
||||||
"Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is " +
|
|
||||||
"$incompatibleVersion, expected version is ${JvmMetadataVersion.INSTANCE}.",
|
|
||||||
CompilerMessageLocation.create(moduleFile.path)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
loadedModules.add(ModuleMappingInfo(root, mapping, moduleFile.nameWithoutExtension))
|
|
||||||
} catch (e: EOFException) {
|
|
||||||
messageCollector.report(
|
|
||||||
ERROR, "Error occurred when reading the module: ${e.message}", CompilerMessageLocation.create(moduleFile.path)
|
|
||||||
)
|
|
||||||
messageCollector.report(
|
|
||||||
LOGGING,
|
|
||||||
String(ByteArrayOutputStream().also { e.printStackTrace(PrintStream(it)) }.toByteArray()),
|
|
||||||
CompilerMessageLocation.create(moduleFile.path)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun tryLoadModuleMapping(
|
||||||
|
getModuleBytes: () -> ByteArray,
|
||||||
|
debugName: String,
|
||||||
|
modulePath: String,
|
||||||
|
deserializationConfiguration: CompilerDeserializationConfiguration,
|
||||||
|
messageCollector: MessageCollector
|
||||||
|
): ModuleMapping? = try {
|
||||||
|
ModuleMapping.loadModuleMapping(getModuleBytes(), debugName, deserializationConfiguration) { incompatibleVersion ->
|
||||||
|
messageCollector.report(
|
||||||
|
ERROR,
|
||||||
|
"Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is " +
|
||||||
|
"$incompatibleVersion, expected version is ${JvmMetadataVersion.INSTANCE}.",
|
||||||
|
CompilerMessageLocation.create(modulePath)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (e: EOFException) {
|
||||||
|
messageCollector.report(
|
||||||
|
ERROR, "Error occurred when reading the module: ${e.message}", CompilerMessageLocation.create(modulePath)
|
||||||
|
)
|
||||||
|
messageCollector.report(
|
||||||
|
LOGGING,
|
||||||
|
String(ByteArrayOutputStream().also { e.printStackTrace(PrintStream(it)) }.toByteArray()),
|
||||||
|
CompilerMessageLocation.create(modulePath)
|
||||||
|
)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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.load.kotlin
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping
|
||||||
|
import org.jetbrains.kotlin.metadata.jvm.deserialization.PackageParts
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.MetadataPartProvider
|
||||||
|
|
||||||
|
abstract class JvmPackagePartProviderBase<MappingsKey> : PackagePartProvider, MetadataPartProvider {
|
||||||
|
|
||||||
|
protected data class ModuleMappingInfo<MappingsKey>(val key: MappingsKey, val mapping: ModuleMapping, val name: String)
|
||||||
|
|
||||||
|
protected abstract val loadedModules: MutableList<ModuleMappingInfo<MappingsKey>>
|
||||||
|
|
||||||
|
override fun findPackageParts(packageFqName: String): List<String> {
|
||||||
|
val rootToPackageParts: Collection<PackageParts> = getPackageParts(packageFqName)
|
||||||
|
if (rootToPackageParts.isEmpty()) return emptyList()
|
||||||
|
|
||||||
|
val result = linkedSetOf<String>()
|
||||||
|
val visitedMultifileFacades = linkedSetOf<String>()
|
||||||
|
for (packageParts in rootToPackageParts) {
|
||||||
|
for (name in packageParts.parts) {
|
||||||
|
val facadeName = packageParts.getMultifileFacadeName(name)
|
||||||
|
if (facadeName == null || facadeName !in visitedMultifileFacades) {
|
||||||
|
result.add(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
packageParts.parts.mapNotNullTo(visitedMultifileFacades, packageParts::getMultifileFacadeName)
|
||||||
|
}
|
||||||
|
return result.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findMetadataPackageParts(packageFqName: String): List<String> =
|
||||||
|
getPackageParts(packageFqName).flatMap(PackageParts::metadataParts).distinct()
|
||||||
|
|
||||||
|
private fun getPackageParts(packageFqName: String): Collection<PackageParts> {
|
||||||
|
val result = mutableMapOf<MappingsKey, PackageParts>()
|
||||||
|
for ((root, mapping) in loadedModules) {
|
||||||
|
val newParts = mapping.findPackageParts(packageFqName) ?: continue
|
||||||
|
result[root]?.let { parts -> parts += newParts } ?: result.put(root, newParts)
|
||||||
|
}
|
||||||
|
return result.values
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAnnotationsOnBinaryModule(moduleName: String): List<ClassId> {
|
||||||
|
return loadedModules.mapNotNull { (_, mapping, name) ->
|
||||||
|
if (name == moduleName) mapping.moduleData.annotations.map(ClassId::fromString) else null
|
||||||
|
}.flatten()
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-2
@@ -106,14 +106,15 @@ fun makeLazyJavaPackageFragmentFromClassLoaderProvider(
|
|||||||
notFoundClasses: NotFoundClasses,
|
notFoundClasses: NotFoundClasses,
|
||||||
reflectKotlinClassFinder: KotlinClassFinder,
|
reflectKotlinClassFinder: KotlinClassFinder,
|
||||||
deserializedDescriptorResolver: DeserializedDescriptorResolver,
|
deserializedDescriptorResolver: DeserializedDescriptorResolver,
|
||||||
singleModuleClassResolver: ModuleClassResolver
|
singleModuleClassResolver: ModuleClassResolver,
|
||||||
|
packagePartProvider: PackagePartProvider = PackagePartProvider.Empty
|
||||||
): LazyJavaPackageFragmentProvider {
|
): LazyJavaPackageFragmentProvider {
|
||||||
val annotationTypeQualifierResolver = AnnotationTypeQualifierResolver(storageManager, Jsr305State.DISABLED)
|
val annotationTypeQualifierResolver = AnnotationTypeQualifierResolver(storageManager, Jsr305State.DISABLED)
|
||||||
val javaResolverComponents = JavaResolverComponents(
|
val javaResolverComponents = JavaResolverComponents(
|
||||||
storageManager, ReflectJavaClassFinder(classLoader), reflectKotlinClassFinder, deserializedDescriptorResolver,
|
storageManager, ReflectJavaClassFinder(classLoader), reflectKotlinClassFinder, deserializedDescriptorResolver,
|
||||||
SignaturePropagator.DO_NOTHING, RuntimeErrorReporter, JavaResolverCache.EMPTY,
|
SignaturePropagator.DO_NOTHING, RuntimeErrorReporter, JavaResolverCache.EMPTY,
|
||||||
JavaPropertyInitializerEvaluator.DoNothing, SamConversionResolver.Empty, RuntimeSourceElementFactory,
|
JavaPropertyInitializerEvaluator.DoNothing, SamConversionResolver.Empty, RuntimeSourceElementFactory,
|
||||||
singleModuleClassResolver, PackagePartProvider.Empty, SupertypeLoopChecker.EMPTY, LookupTracker.DO_NOTHING, module,
|
singleModuleClassResolver, packagePartProvider, SupertypeLoopChecker.EMPTY, LookupTracker.DO_NOTHING, module,
|
||||||
ReflectionTypes(module, notFoundClasses), annotationTypeQualifierResolver,
|
ReflectionTypes(module, notFoundClasses), annotationTypeQualifierResolver,
|
||||||
SignatureEnhancement(annotationTypeQualifierResolver, Jsr305State.DISABLED),
|
SignatureEnhancement(annotationTypeQualifierResolver, Jsr305State.DISABLED),
|
||||||
JavaClassesTracker.Default, JavaResolverSettings.Default, NewKotlinTypeChecker.Default
|
JavaClassesTracker.Default, JavaResolverSettings.Default, NewKotlinTypeChecker.Default
|
||||||
|
|||||||
+1
-2
@@ -52,10 +52,9 @@ class ResolveDependenciesTest : TestCase() {
|
|||||||
runScriptAndCheckResult(classImportScript, configurationWithDependenciesFromClasspath, null, 42)
|
runScriptAndCheckResult(classImportScript, configurationWithDependenciesFromClasspath, null, 42)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
@Test
|
||||||
// This doesn't work since there is no way to resolve a top-level function/property via reflection now (see #KT-33892)
|
// This doesn't work since there is no way to resolve a top-level function/property via reflection now (see #KT-33892)
|
||||||
fun ignore_testResolveFunAndValFromClassloader() {
|
fun testResolveFunAndValFromClassloader() {
|
||||||
runScriptAndCheckResult(funAndValAccessScript, configurationWithDependenciesFromClassloader, null, 42)
|
runScriptAndCheckResult(funAndValAccessScript, configurationWithDependenciesFromClassloader, null, 42)
|
||||||
runScriptAndCheckResult(funAndValImportScript, configurationWithDependenciesFromClassloader, null, 42)
|
runScriptAndCheckResult(funAndValImportScript, configurationWithDependenciesFromClassloader, null, 42)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ dependencies {
|
|||||||
compile(project(":kotlin-script-runtime"))
|
compile(project(":kotlin-script-runtime"))
|
||||||
compile(kotlinStdlib())
|
compile(kotlinStdlib())
|
||||||
compile(project(":kotlin-scripting-common"))
|
compile(project(":kotlin-scripting-common"))
|
||||||
|
testCompile(commonDep("junit"))
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
"main" { projectDefault() }
|
"main" { projectDefault() }
|
||||||
"test" {}
|
"test" { projectDefault() }
|
||||||
}
|
}
|
||||||
|
|
||||||
publish()
|
publish()
|
||||||
|
|||||||
+146
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* 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 kotlin.script.experimental.jvm.util
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.net.JarURLConnection
|
||||||
|
import java.net.URL
|
||||||
|
import java.util.jar.JarFile
|
||||||
|
import java.util.jar.JarInputStream
|
||||||
|
import kotlin.script.experimental.jvm.impl.toFileOrNull
|
||||||
|
|
||||||
|
fun ClassLoader.forAllMatchingFiles(namePattern: String, body: (String, InputStream) -> Unit) {
|
||||||
|
val processedDirs = HashSet<File>()
|
||||||
|
val processedJars = HashSet<URL>()
|
||||||
|
val nameRegex = namePatternToRegex(namePattern)
|
||||||
|
|
||||||
|
fun iterateResources(vararg keyResourcePaths: String) {
|
||||||
|
for (keyResourcePath in keyResourcePaths) {
|
||||||
|
val resourceRootCalc = ClassLoaderResourceRootFIlePathCalculator(keyResourcePath)
|
||||||
|
for (url in getResources(keyResourcePath)) {
|
||||||
|
if (url.protocol == "jar") {
|
||||||
|
val jarConnection = url.openConnection() as? JarURLConnection
|
||||||
|
val jarUrl = jarConnection?.jarFileURL
|
||||||
|
if (jarUrl != null && !processedJars.contains(jarUrl)) {
|
||||||
|
processedJars.add(jarUrl)
|
||||||
|
try {
|
||||||
|
jarConnection.jarFile
|
||||||
|
} catch (_: IOException) {
|
||||||
|
// TODO: consider error reporting
|
||||||
|
null
|
||||||
|
}?.let {
|
||||||
|
forAllMatchingFilesInJarFile(it, nameRegex, body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val rootDir = url.toFileOrNull()?.let { resourceRootCalc(it) }
|
||||||
|
if (rootDir != null && rootDir.isDirectory && !processedDirs.contains(rootDir)) {
|
||||||
|
processedDirs.add(rootDir)
|
||||||
|
forAllMatchingFilesInDirectory(rootDir, namePattern, body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iterateResources("", JAR_MANIFEST_RESOURCE_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val wildcardChars = "*?".toCharArray()
|
||||||
|
internal val patternCharsToEscape = ".*?+()[]^\${}|".toCharArray().also { assert(wildcardChars.all { wc -> it.contains(wc) }) }
|
||||||
|
|
||||||
|
private fun Char.escape(): String = (if (patternCharsToEscape.contains(this)) "\\" else "") + this
|
||||||
|
|
||||||
|
internal val pathSeparatorChars = "/".let { if (File.separatorChar == '/') it else it + File.separator }.toCharArray()
|
||||||
|
internal val pathElementPattern = if (File.separatorChar == '/') "[^/]*" else "[^/${File.separatorChar.escape()}]*"
|
||||||
|
internal val pathSeparatorPattern = if (File.separatorChar == '/') "/" else "[/${File.separatorChar.escape()}]."
|
||||||
|
internal val specialPatternChars = patternCharsToEscape + pathSeparatorChars
|
||||||
|
|
||||||
|
internal fun forAllMatchingFilesInDirectory(baseDir: File, namePattern: String, body: (String, InputStream) -> Unit) {
|
||||||
|
val patternStart = namePattern.indexOfAny(wildcardChars)
|
||||||
|
if (patternStart < 0) {
|
||||||
|
// assuming a single file
|
||||||
|
baseDir.resolve(namePattern).takeIf { it.exists() && it.isFile }?.let { file ->
|
||||||
|
body(file.relativeToOrSelf(baseDir).path, file.inputStream())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val patternDirStart = namePattern.lastIndexOfAny(pathSeparatorChars, patternStart)
|
||||||
|
val root = if (patternDirStart <= 0) baseDir else baseDir.resolve(namePattern.substring(0, patternDirStart))
|
||||||
|
if (root.exists() && root.isDirectory) {
|
||||||
|
val re = namePatternToRegex(namePattern.substring(patternDirStart + 1))
|
||||||
|
root.walkTopDown().filter {
|
||||||
|
re.matches(it.relativeToOrSelf(root).path)
|
||||||
|
}.forEach { file ->
|
||||||
|
body(file.relativeToOrSelf(baseDir).path, file.inputStream())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun forAllMatchingFilesInJarStream(jarInputStream: JarInputStream, nameRegex: Regex, body: (String, InputStream) -> Unit) {
|
||||||
|
do {
|
||||||
|
val entry = jarInputStream.nextJarEntry
|
||||||
|
if (entry != null) {
|
||||||
|
try {
|
||||||
|
if (!entry.isDirectory && nameRegex.matches(entry.name)) {
|
||||||
|
body(entry.name, jarInputStream)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
jarInputStream.closeEntry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (entry != null)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun forAllMatchingFilesInJar(jarFile: File, nameRegex: Regex, body: (String, InputStream) -> Unit) {
|
||||||
|
JarInputStream(FileInputStream(jarFile)).use {
|
||||||
|
forAllMatchingFilesInJarStream(it, nameRegex, body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun forAllMatchingFilesInJarFile(jarFile: JarFile, nameRegex: Regex, body: (String, InputStream) -> Unit) {
|
||||||
|
jarFile.entries().asSequence().forEach { entry ->
|
||||||
|
if (!entry.isDirectory && nameRegex.matches(entry.name)) {
|
||||||
|
jarFile.getInputStream(entry).use { stream ->
|
||||||
|
body(entry.name, stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun namePatternToRegex(pattern: String): Regex = Regex(
|
||||||
|
buildString {
|
||||||
|
var current = 0
|
||||||
|
loop@ while (current < pattern.length) {
|
||||||
|
val nextIndex = pattern.indexOfAny(specialPatternChars, current)
|
||||||
|
val next = if (nextIndex < 0) pattern.length else nextIndex
|
||||||
|
append(pattern.substring(current, next))
|
||||||
|
current = next + 1
|
||||||
|
when {
|
||||||
|
next >= pattern.length -> break@loop
|
||||||
|
|
||||||
|
pathSeparatorChars.contains(pattern[next]) -> append(pathSeparatorPattern)
|
||||||
|
|
||||||
|
pattern[next] == '?' -> append('.')
|
||||||
|
|
||||||
|
pattern[next] == '*' && next + 1 < pattern.length && pattern[next + 1] == '*' -> {
|
||||||
|
append(".*")
|
||||||
|
current++
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern[next] == '*' -> append(pathElementPattern)
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
append('\\')
|
||||||
|
append(pattern[next])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
+19
-11
@@ -39,7 +39,7 @@ internal const val KOTLIN_COMPILER_JAR = "$KOTLIN_COMPILER_NAME.jar"
|
|||||||
private val JAR_COLLECTIONS_CLASSES_PATHS = arrayOf("BOOT-INF/classes", "WEB-INF/classes")
|
private val JAR_COLLECTIONS_CLASSES_PATHS = arrayOf("BOOT-INF/classes", "WEB-INF/classes")
|
||||||
private val JAR_COLLECTIONS_LIB_PATHS = arrayOf("BOOT-INF/lib", "WEB-INF/lib")
|
private val JAR_COLLECTIONS_LIB_PATHS = arrayOf("BOOT-INF/lib", "WEB-INF/lib")
|
||||||
private val JAR_COLLECTIONS_KEY_PATHS = JAR_COLLECTIONS_CLASSES_PATHS + JAR_COLLECTIONS_LIB_PATHS
|
private val JAR_COLLECTIONS_KEY_PATHS = JAR_COLLECTIONS_CLASSES_PATHS + JAR_COLLECTIONS_LIB_PATHS
|
||||||
private const val JAR_MANIFEST_RESOURCE_NAME = "META-INF/MANIFEST.MF"
|
internal const val JAR_MANIFEST_RESOURCE_NAME = "META-INF/MANIFEST.MF"
|
||||||
|
|
||||||
internal const val KOTLIN_SCRIPT_CLASSPATH_PROPERTY = "kotlin.script.classpath"
|
internal const val KOTLIN_SCRIPT_CLASSPATH_PROPERTY = "kotlin.script.classpath"
|
||||||
internal const val KOTLIN_COMPILER_CLASSPATH_PROPERTY = "kotlin.compiler.classpath"
|
internal const val KOTLIN_COMPILER_CLASSPATH_PROPERTY = "kotlin.compiler.classpath"
|
||||||
@@ -108,20 +108,28 @@ private fun ClassLoader.classPathFromGetUrlsMethodOrNull(): Sequence<File>? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class ClassLoaderResourceRootFIlePathCalculator(private val keyResourcePath: String) {
|
||||||
|
private var keyResourcePathDepth = -1
|
||||||
|
|
||||||
|
operator fun invoke(resourceFile: File): File {
|
||||||
|
if (keyResourcePathDepth < 0) {
|
||||||
|
keyResourcePathDepth = if (keyResourcePath.isBlank()) 0 else (keyResourcePath.trim('/').count { it == '/' } + 1)
|
||||||
|
}
|
||||||
|
var root = resourceFile
|
||||||
|
for (i in 0 until keyResourcePathDepth) {
|
||||||
|
root = root.parentFile
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal fun ClassLoader.rawClassPathFromKeyResourcePath(keyResourcePath: String): Sequence<File> {
|
internal fun ClassLoader.rawClassPathFromKeyResourcePath(keyResourcePath: String): Sequence<File> {
|
||||||
var keyResourcePathDepth = -1
|
val resourceRootCalc = ClassLoaderResourceRootFIlePathCalculator(keyResourcePath)
|
||||||
return getResources(keyResourcePath).asSequence().mapNotNull { url ->
|
return getResources(keyResourcePath).asSequence().mapNotNull { url ->
|
||||||
if (url.protocol == "jar") {
|
if (url.protocol == "jar") {
|
||||||
(url.openConnection() as? JarURLConnection)?.jarFileURL?.toFileOrNull()
|
(url.openConnection() as? JarURLConnection)?.jarFileURL?.toFileOrNull()
|
||||||
} else url.toFileOrNull()?.let { file ->
|
} else {
|
||||||
if (keyResourcePathDepth < 0) {
|
url.toFileOrNull()?.let { resourceRootCalc(it) }
|
||||||
keyResourcePathDepth = if (keyResourcePath.isBlank()) 0 else (keyResourcePath.trim('/').count { it == '/' } + 1)
|
|
||||||
}
|
|
||||||
var root = file
|
|
||||||
for (i in 0 until keyResourcePathDepth) {
|
|
||||||
root = root.parentFile
|
|
||||||
}
|
|
||||||
root
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* 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 kotlin.script.experimental.jvm.test
|
||||||
|
|
||||||
|
import junit.framework.TestCase
|
||||||
|
import org.junit.Test
|
||||||
|
import java.io.File
|
||||||
|
import java.util.jar.JarFile
|
||||||
|
import java.util.jar.JarInputStream
|
||||||
|
import kotlin.script.experimental.jvm.util.*
|
||||||
|
|
||||||
|
class UtilsTest : TestCase() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testPatternConversionWildcards() {
|
||||||
|
assertPattern("a${pathSeparatorPattern}b\\.$pathElementPattern", "a/b.*")
|
||||||
|
assertPattern("a$pathSeparatorPattern$pathElementPattern\\.txt", "a/*.txt")
|
||||||
|
assertPattern("a$pathSeparatorPattern.*/b", "a/**/b")
|
||||||
|
assertPattern("a${pathSeparatorPattern}b.\\.txt", "a/b?.txt")
|
||||||
|
assertPattern("$pathElementPattern/b\\.txt", "*/b.txt")
|
||||||
|
assertPattern(".*${pathSeparatorPattern}b\\.txt", "**/b.txt")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testPatternConversionEscaping() {
|
||||||
|
assertPattern("aa\\+\\(\\)\\[\\]\\^\\\$\\{\\}\\|", "aa+()[]^\${}|")
|
||||||
|
assertPattern("\\+\\(\\)\\[\\]\\^\\\$\\{\\}\\|bb", "+()[]^\${}|bb")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSelectFilesInDir() {
|
||||||
|
|
||||||
|
val rootDir = File(".")
|
||||||
|
|
||||||
|
fun assertProjectFilesBy(pattern: String, vararg paths: String) {
|
||||||
|
val res = ArrayList<Pair<String, String>>()
|
||||||
|
|
||||||
|
forAllMatchingFilesInDirectory(rootDir, pattern) { path, stream ->
|
||||||
|
res.add(path to stream.reader().readText())
|
||||||
|
}
|
||||||
|
assertEquals(paths.toSet(), res.mapTo(HashSet()) { it.first })
|
||||||
|
|
||||||
|
res.forEach { (path, bytes) ->
|
||||||
|
val data = File(path).readText()
|
||||||
|
assertEquals("Mismatching data for $path", data, bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertProjectFilesBy("*.kt") // none
|
||||||
|
assertProjectFilesBy("**/sss/*.kt") // none
|
||||||
|
assertProjectFilesBy(
|
||||||
|
"src/kotlin/script/experimental/jvm/util/jvmClassLoaderUtil.kt",
|
||||||
|
"src/kotlin/script/experimental/jvm/util/jvmClassLoaderUtil.kt"
|
||||||
|
)
|
||||||
|
assertProjectFilesBy(
|
||||||
|
"src/kotlin/script/experimental/jvm/util/jvm?lassLoaderUtil.kt",
|
||||||
|
"src/kotlin/script/experimental/jvm/util/jvmClassLoaderUtil.kt"
|
||||||
|
)
|
||||||
|
assertProjectFilesBy(
|
||||||
|
"src/kotlin/script/experimental/jvm/util/jvm*LoaderUtil.kt",
|
||||||
|
"src/kotlin/script/experimental/jvm/util/jvmClassLoaderUtil.kt"
|
||||||
|
)
|
||||||
|
assertProjectFilesBy("**/jvmClassLoaderUtil.kt", "src/kotlin/script/experimental/jvm/util/jvmClassLoaderUtil.kt")
|
||||||
|
assertProjectFilesBy("**/script/**/jvmClassLoaderUtil.kt", "src/kotlin/script/experimental/jvm/util/jvmClassLoaderUtil.kt")
|
||||||
|
assertProjectFilesBy("src/**/jvmClassLoaderUtil.kt", "src/kotlin/script/experimental/jvm/util/jvmClassLoaderUtil.kt")
|
||||||
|
assertProjectFilesBy("test/**/?????Test.*", "test/kotlin/script/experimental/jvm/test/utilsTest.kt")
|
||||||
|
|
||||||
|
val allSrcKtFiles = HashSet<String>()
|
||||||
|
forAllMatchingFilesInDirectory(rootDir, "src/**/*.kt") { path, _ ->
|
||||||
|
allSrcKtFiles.add(path)
|
||||||
|
}
|
||||||
|
val allExpectedSrcKtFiles =
|
||||||
|
rootDir.walkTopDown().filter {
|
||||||
|
it.relativeToOrSelf(rootDir).path.startsWith("src") && it.extension == "kt"
|
||||||
|
}.mapTo(HashSet()) {
|
||||||
|
it.relativeToOrSelf(rootDir).path
|
||||||
|
}
|
||||||
|
assertEquals(allExpectedSrcKtFiles, allSrcKtFiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSelectFilesInJar() {
|
||||||
|
|
||||||
|
fun JarFile.filesBy(pattern: String): Map<String, String> {
|
||||||
|
val res = HashMap<String, String>()
|
||||||
|
forAllMatchingFilesInJarFile(this, namePatternToRegex(pattern)) { path, stream ->
|
||||||
|
res[path] = stream.reader().readText().trim()
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
fun JarInputStream.filesBy(pattern: String): Map<String, String> {
|
||||||
|
val res = HashMap<String, String>()
|
||||||
|
forAllMatchingFilesInJarStream(this, namePatternToRegex(pattern)) { path, stream ->
|
||||||
|
res[path] = stream.reader().readText().trim()
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assertFiles(actual: Map<String, String>, vararg expected: Pair<String, String>) {
|
||||||
|
val expectedAsMap = expected.toMap()
|
||||||
|
assertEquals(expectedAsMap, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assertMatchingFilesInJarTwoWay(jar: File, pattern: String, vararg expected: Pair<String, String>) {
|
||||||
|
assertFiles( JarFile(jar).filesBy(pattern), *expected)
|
||||||
|
assertFiles( JarInputStream(jar.inputStream()).use { it.filesBy(pattern) }, *expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
val jar = File("testData/testJar.jar")
|
||||||
|
assertTrue(jar.exists())
|
||||||
|
|
||||||
|
assertMatchingFilesInJarTwoWay(jar, "META-INF/*.kotlin_module", "META-INF/abc.kotlin_module" to "module")
|
||||||
|
assertMatchingFilesInJarTwoWay(jar, "META-INF/*.kotlin") // none
|
||||||
|
assertMatchingFilesInJarTwoWay(jar, "**/*.class", "a/b/c/d1.class" to "d1", "a/b/c/d1\$s1.class" to "d1s1")
|
||||||
|
assertMatchingFilesInJarTwoWay(jar, "**/*\$*.class", "a/b/c/d1\$s1.class" to "d1s1")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun assertPattern(expected: String, pattern: String) {
|
||||||
|
assertEquals(expected, namePatternToRegex(pattern).pattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
BIN
Binary file not shown.
+19
-3
@@ -7,23 +7,29 @@ package org.jetbrains.kotlin.scripting.compiler.plugin.impl
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||||
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.NotFoundClasses
|
import org.jetbrains.kotlin.descriptors.NotFoundClasses
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.components.*
|
import org.jetbrains.kotlin.descriptors.runtime.components.*
|
||||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
|
import org.jetbrains.kotlin.load.java.components.JavaResolverCache
|
||||||
import org.jetbrains.kotlin.load.java.lazy.SingleModuleClassResolver
|
import org.jetbrains.kotlin.load.java.lazy.SingleModuleClassResolver
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
import org.jetbrains.kotlin.load.kotlin.*
|
import org.jetbrains.kotlin.load.kotlin.*
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
|
||||||
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
||||||
import kotlin.script.experimental.jvm.ClassLoaderByConfiguration
|
import kotlin.script.experimental.jvm.ClassLoaderByConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.util.classpathFromClassloader
|
||||||
|
|
||||||
class PackageFragmentFromClassLoaderProviderExtension(
|
class PackageFragmentFromClassLoaderProviderExtension(
|
||||||
val classLoaderGetter: ClassLoaderByConfiguration,
|
val classLoaderGetter: ClassLoaderByConfiguration,
|
||||||
val scriptCompilationConfiguration: ScriptCompilationConfiguration
|
val scriptCompilationConfiguration: ScriptCompilationConfiguration,
|
||||||
|
val compilerConfiguration: CompilerConfiguration
|
||||||
) : PackageFragmentProviderExtension {
|
) : PackageFragmentProviderExtension {
|
||||||
|
|
||||||
override fun getPackageFragmentProvider(
|
override fun getPackageFragmentProvider(
|
||||||
@@ -40,11 +46,18 @@ class PackageFragmentFromClassLoaderProviderExtension(
|
|||||||
val deserializedDescriptorResolver = DeserializedDescriptorResolver()
|
val deserializedDescriptorResolver = DeserializedDescriptorResolver()
|
||||||
val singleModuleClassResolver = SingleModuleClassResolver()
|
val singleModuleClassResolver = SingleModuleClassResolver()
|
||||||
val notFoundClasses = NotFoundClasses(storageManager, module)
|
val notFoundClasses = NotFoundClasses(storageManager, module)
|
||||||
|
val packagePartProvider =
|
||||||
|
PackagePartFromClassLoaderProvider(
|
||||||
|
classLoader,
|
||||||
|
compilerConfiguration.languageVersionSettings,
|
||||||
|
compilerConfiguration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]!!
|
||||||
|
)
|
||||||
|
|
||||||
val lazyJavaPackageFragmentProvider =
|
val lazyJavaPackageFragmentProvider =
|
||||||
makeLazyJavaPackageFragmentFromClassLoaderProvider(
|
makeLazyJavaPackageFragmentFromClassLoaderProvider(
|
||||||
classLoader, module, storageManager, notFoundClasses,
|
classLoader, module, storageManager, notFoundClasses,
|
||||||
reflectKotlinClassFinder, deserializedDescriptorResolver, singleModuleClassResolver
|
reflectKotlinClassFinder, deserializedDescriptorResolver, singleModuleClassResolver,
|
||||||
|
packagePartProvider
|
||||||
)
|
)
|
||||||
|
|
||||||
val deserializationComponentsForJava =
|
val deserializationComponentsForJava =
|
||||||
@@ -55,6 +68,9 @@ class PackageFragmentFromClassLoaderProviderExtension(
|
|||||||
|
|
||||||
deserializedDescriptorResolver.setComponents(deserializationComponentsForJava)
|
deserializedDescriptorResolver.setComponents(deserializationComponentsForJava)
|
||||||
|
|
||||||
|
val javaDescriptorResolver = JavaDescriptorResolver(lazyJavaPackageFragmentProvider, JavaResolverCache.EMPTY)
|
||||||
|
singleModuleClassResolver.resolver = javaDescriptorResolver
|
||||||
|
|
||||||
return lazyJavaPackageFragmentProvider
|
return lazyJavaPackageFragmentProvider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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.scripting.compiler.plugin.impl
|
||||||
|
|
||||||
|
import com.intellij.util.SmartList
|
||||||
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.tryLoadModuleMapping
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartProviderBase
|
||||||
|
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping
|
||||||
|
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.util.forAllMatchingFiles
|
||||||
|
|
||||||
|
class PackagePartFromClassLoaderProvider(
|
||||||
|
classLoader: ClassLoader,
|
||||||
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
|
messageCollector: MessageCollector
|
||||||
|
) : JvmPackagePartProviderBase<String>() {
|
||||||
|
private val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings)
|
||||||
|
|
||||||
|
override val loadedModules: MutableList<ModuleMappingInfo<String>> = SmartList()
|
||||||
|
|
||||||
|
init {
|
||||||
|
classLoader.forAllMatchingFiles("META-INF/*.${ModuleMapping.MAPPING_FILE_EXT}") { name, stream ->
|
||||||
|
tryLoadModuleMapping(
|
||||||
|
{ stream.readBytes() }, name, name, deserializationConfiguration, messageCollector
|
||||||
|
)?.let {
|
||||||
|
val moduleName = name.removePrefix("META-INF/").removeSuffix(".${ModuleMapping.MAPPING_FILE_EXT}")
|
||||||
|
loadedModules.add(ModuleMappingInfo(name, it, moduleName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+18
-8
@@ -132,6 +132,23 @@ private fun compileImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun registerPackageFragmetProvidersIfNeeded(
|
||||||
|
scriptCompilationConfiguration: ScriptCompilationConfiguration,
|
||||||
|
environment: KotlinCoreEnvironment
|
||||||
|
) {
|
||||||
|
scriptCompilationConfiguration[ScriptCompilationConfiguration.dependencies]?.forEach { dependency ->
|
||||||
|
if (dependency is JvmDependencyFromClassLoader) {
|
||||||
|
// TODO: consider implementing deduplication
|
||||||
|
PackageFragmentProviderExtension.registerExtension(
|
||||||
|
environment.project,
|
||||||
|
PackageFragmentFromClassLoaderProviderExtension(
|
||||||
|
dependency.classLoaderGetter, scriptCompilationConfiguration, environment.configuration
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun doCompile(
|
private fun doCompile(
|
||||||
context: SharedScriptCompilationContext,
|
context: SharedScriptCompilationContext,
|
||||||
script: SourceCode,
|
script: SourceCode,
|
||||||
@@ -141,14 +158,7 @@ private fun doCompile(
|
|||||||
getScriptConfiguration: (KtFile) -> ScriptCompilationConfiguration
|
getScriptConfiguration: (KtFile) -> ScriptCompilationConfiguration
|
||||||
): ResultWithDiagnostics<KJvmCompiledScript<Any>> {
|
): ResultWithDiagnostics<KJvmCompiledScript<Any>> {
|
||||||
|
|
||||||
context.baseScriptCompilationConfiguration[ScriptCompilationConfiguration.dependencies]?.forEach { dependency ->
|
registerPackageFragmetProvidersIfNeeded(getScriptConfiguration(sourceFiles.first()), context.environment)
|
||||||
if (dependency is JvmDependencyFromClassLoader) {
|
|
||||||
PackageFragmentProviderExtension.registerExtension(
|
|
||||||
context.environment.project,
|
|
||||||
PackageFragmentFromClassLoaderProviderExtension(dependency.classLoaderGetter, context.baseScriptCompilationConfiguration)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val analysisResult = analyze(sourceFiles, context.environment)
|
val analysisResult = analyze(sourceFiles, context.environment)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user