Improve type boundaries for KotlinScriptDefinition interface
This commit is contained in:
@@ -37,13 +37,13 @@ open class KotlinScriptDefinition(val template: KClass<out Any>) {
|
|||||||
open val annotationsForSamWithReceivers: List<String>
|
open val annotationsForSamWithReceivers: List<String>
|
||||||
get() = emptyList()
|
get() = emptyList()
|
||||||
|
|
||||||
open fun <TF> isScript(file: TF): Boolean =
|
open fun <TF: Any> isScript(file: TF): Boolean =
|
||||||
getFileName(file).endsWith(KotlinParserDefinition.STD_SCRIPT_EXT)
|
getFileName(file).endsWith(KotlinParserDefinition.STD_SCRIPT_EXT)
|
||||||
|
|
||||||
open fun getScriptName(script: KtScript): Name =
|
open fun getScriptName(script: KtScript): Name =
|
||||||
ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT)
|
ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT)
|
||||||
|
|
||||||
open fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? = null
|
open fun <TF: Any> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
interface KotlinScriptExternalDependencies : Comparable<KotlinScriptExternalDependencies> {
|
interface KotlinScriptExternalDependencies : Comparable<KotlinScriptExternalDependencies> {
|
||||||
|
|||||||
+6
-6
@@ -81,19 +81,19 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
|||||||
|
|
||||||
override val name = template.simpleName!!
|
override val name = template.simpleName!!
|
||||||
|
|
||||||
override fun <TF> isScript(file: TF): Boolean =
|
override fun <TF: Any> isScript(file: TF): Boolean =
|
||||||
scriptFilePattern.let { Regex(it).matches(getFileName(file)) }
|
scriptFilePattern.let { Regex(it).matches(getFileName(file)) }
|
||||||
|
|
||||||
// TODO: implement other strategy - e.g. try to extract something from match with ScriptFilePattern
|
// TODO: implement other strategy - e.g. try to extract something from match with ScriptFilePattern
|
||||||
override fun getScriptName(script: KtScript): Name = ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT)
|
override fun getScriptName(script: KtScript): Name = ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT)
|
||||||
|
|
||||||
override fun <TF> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? {
|
override fun <TF: Any> getDependenciesFor(file: TF, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? {
|
||||||
|
|
||||||
fun logClassloadingError(ex: Throwable) {
|
fun logClassloadingError(ex: Throwable) {
|
||||||
logScriptDefMessage(ScriptDependenciesResolver.ReportSeverity.WARNING, ex.message ?: "Invalid script template: ${template.qualifiedName}", null)
|
logScriptDefMessage(ScriptDependenciesResolver.ReportSeverity.WARNING, ex.message ?: "Invalid script template: ${template.qualifiedName}", null)
|
||||||
}
|
}
|
||||||
|
|
||||||
val script = BasicScriptContents(file, getAnnotations = {
|
fun makeScriptContents() = BasicScriptContents(file, getAnnotations = {
|
||||||
val classLoader = (template as Any).javaClass.classLoader
|
val classLoader = (template as Any).javaClass.classLoader
|
||||||
try {
|
try {
|
||||||
getAnnotationEntries(file, project)
|
getAnnotationEntries(file, project)
|
||||||
@@ -112,7 +112,7 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
|||||||
})
|
})
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val fileDeps = resolver?.resolve(script, environment, ::logScriptDefMessage, previousDependencies)
|
val fileDeps = resolver?.resolve(makeScriptContents(), environment, ::logScriptDefMessage, previousDependencies)
|
||||||
// TODO: use it as a Future
|
// TODO: use it as a Future
|
||||||
return fileDeps?.get()
|
return fileDeps?.get()
|
||||||
}
|
}
|
||||||
@@ -122,7 +122,7 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <TF> getAnnotationEntries(file: TF, project: Project): Iterable<KtAnnotationEntry> = when (file) {
|
private fun <TF: Any> getAnnotationEntries(file: TF, project: Project): Iterable<KtAnnotationEntry> = when (file) {
|
||||||
is PsiFile -> getAnnotationEntriesFromPsiFile(file)
|
is PsiFile -> getAnnotationEntriesFromPsiFile(file)
|
||||||
is VirtualFile -> getAnnotationEntriesFromVirtualFile(file, project)
|
is VirtualFile -> getAnnotationEntriesFromVirtualFile(file, project)
|
||||||
is File -> {
|
is File -> {
|
||||||
@@ -143,7 +143,7 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
|||||||
return getAnnotationEntriesFromPsiFile(psiFile)
|
return getAnnotationEntriesFromPsiFile(psiFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
class BasicScriptContents<out TF>(myFile: TF, getAnnotations: () -> Iterable<Annotation>) : ScriptContents {
|
class BasicScriptContents<out TF: Any>(myFile: TF, getAnnotations: () -> Iterable<Annotation>) : ScriptContents {
|
||||||
override val file: File? by lazy { getFile(myFile) }
|
override val file: File? by lazy { getFile(myFile) }
|
||||||
override val annotations: Iterable<Annotation> by lazy { getAnnotations() }
|
override val annotations: Iterable<Annotation> by lazy { getAnnotations() }
|
||||||
override val text: CharSequence? by lazy { getFileContents(myFile) }
|
override val text: CharSequence? by lazy { getFileContents(myFile) }
|
||||||
|
|||||||
@@ -44,11 +44,11 @@ class KotlinScriptDefinitionProvider {
|
|||||||
return changed
|
return changed
|
||||||
}
|
}
|
||||||
|
|
||||||
fun<TF> findScriptDefinition(file: TF): KotlinScriptDefinition? = definitionsLock.read {
|
fun<TF: Any> findScriptDefinition(file: TF): KotlinScriptDefinition? = definitionsLock.read {
|
||||||
definitions.firstOrNull { it.isScript(file) }
|
definitions.firstOrNull { it.isScript(file) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun<TF> isScript(file: TF): Boolean = findScriptDefinition(file) != null
|
fun<TF: Any> isScript(file: TF): Boolean = findScriptDefinition(file) != null
|
||||||
|
|
||||||
fun addScriptDefinition(scriptDefinition: KotlinScriptDefinition) {
|
fun addScriptDefinition(scriptDefinition: KotlinScriptDefinition) {
|
||||||
definitionsLock.write {
|
definitionsLock.write {
|
||||||
|
|||||||
+7
-7
@@ -31,13 +31,13 @@ class KotlinScriptExternalImportsProvider(val project: Project, private val scri
|
|||||||
private val cache = hashMapOf<String, KotlinScriptExternalDependencies>()
|
private val cache = hashMapOf<String, KotlinScriptExternalDependencies>()
|
||||||
private val cacheOfNulls = hashSetOf<String>()
|
private val cacheOfNulls = hashSetOf<String>()
|
||||||
|
|
||||||
fun <TF> getExternalImports(file: TF): KotlinScriptExternalDependencies? = cacheLock.read { calculateExternalDependencies(file) }
|
fun <TF: Any> getExternalImports(file: TF): KotlinScriptExternalDependencies? = cacheLock.read { calculateExternalDependencies(file) }
|
||||||
|
|
||||||
fun <TF> getExternalImports(files: Iterable<TF>): List<KotlinScriptExternalDependencies> = cacheLock.read {
|
fun <TF: Any> getExternalImports(files: Iterable<TF>): List<KotlinScriptExternalDependencies> = cacheLock.read {
|
||||||
files.mapNotNull { calculateExternalDependencies(it) }
|
files.mapNotNull { calculateExternalDependencies(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <TF> calculateExternalDependencies(file: TF): KotlinScriptExternalDependencies? {
|
private fun <TF: Any> calculateExternalDependencies(file: TF): KotlinScriptExternalDependencies? {
|
||||||
val path = getFilePath(file)
|
val path = getFilePath(file)
|
||||||
return cache[path]
|
return cache[path]
|
||||||
?: if (cacheOfNulls.contains(path)) null
|
?: if (cacheOfNulls.contains(path)) null
|
||||||
@@ -56,7 +56,7 @@ class KotlinScriptExternalImportsProvider(val project: Project, private val scri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// optimized for initial caching, additional handling of possible duplicates to save a call to distinct
|
// optimized for initial caching, additional handling of possible duplicates to save a call to distinct
|
||||||
fun <TF> cacheExternalImports(files: Iterable<TF>): Unit = cacheLock.write {
|
fun <TF: Any> cacheExternalImports(files: Iterable<TF>): Unit = cacheLock.write {
|
||||||
val uncached = hashSetOf<String>()
|
val uncached = hashSetOf<String>()
|
||||||
files.forEach { file ->
|
files.forEach { file ->
|
||||||
val path = getFilePath(file)
|
val path = getFilePath(file)
|
||||||
@@ -130,9 +130,9 @@ class KotlinScriptExternalImportsProvider(val project: Project, private val scri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <TF> invalidateCachesFor(vararg files: TF) { invalidateCachesFor(files.asIterable()) }
|
fun <TF: Any> invalidateCachesFor(vararg files: TF) { invalidateCachesFor(files.asIterable()) }
|
||||||
|
|
||||||
fun <TF> invalidateCachesFor(files: Iterable<TF>) {
|
fun <TF: Any> invalidateCachesFor(files: Iterable<TF>) {
|
||||||
cacheLock.write {
|
cacheLock.write {
|
||||||
files.forEach { file ->
|
files.forEach { file ->
|
||||||
val path = getFilePath(file)
|
val path = getFilePath(file)
|
||||||
@@ -150,7 +150,7 @@ class KotlinScriptExternalImportsProvider(val project: Project, private val scri
|
|||||||
cache.values.flatMap { it.sources }
|
cache.values.flatMap { it.sources }
|
||||||
}.distinct()
|
}.distinct()
|
||||||
|
|
||||||
fun <TF> getCombinedClasspathFor(files: Iterable<TF>): List<File> =
|
fun <TF: Any> getCombinedClasspathFor(files: Iterable<TF>): List<File> =
|
||||||
getExternalImports(files)
|
getExternalImports(files)
|
||||||
.flatMap { it.classpath }
|
.flatMap { it.classpath }
|
||||||
.distinct()
|
.distinct()
|
||||||
|
|||||||
@@ -21,42 +21,42 @@ import com.intellij.psi.PsiFile
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
fun <TF> getFileName(file: TF): String = when (file) {
|
fun <TF: Any> getFileName(file: TF): String = when (file) {
|
||||||
is PsiFile -> file.originalFile.name
|
is PsiFile -> file.originalFile.name
|
||||||
is VirtualFile -> file.name
|
is VirtualFile -> file.name
|
||||||
is File -> file.name
|
is File -> file.name
|
||||||
else -> throw IllegalArgumentException("Unsupported file type $file")
|
else -> throw IllegalArgumentException("Unsupported file type $file")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <TF> getFilePath(file: TF): String = when (file) {
|
fun <TF: Any> getFilePath(file: TF): String = when (file) {
|
||||||
is PsiFile -> file.originalFile.run { virtualFile?.path ?: name } // TODO: replace name with path of PSI elements
|
is PsiFile -> file.originalFile.run { virtualFile?.path ?: name } // TODO: replace name with path of PSI elements
|
||||||
is VirtualFile -> file.path
|
is VirtualFile -> file.path
|
||||||
is File -> file.canonicalPath
|
is File -> file.canonicalPath
|
||||||
else -> throw IllegalArgumentException("Unsupported file type $file")
|
else -> throw IllegalArgumentException("Unsupported file type $file")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <TF> isValidFile(file: TF): Boolean = when (file) {
|
fun <TF: Any> isValidFile(file: TF): Boolean = when (file) {
|
||||||
is PsiFile -> file.isValid
|
is PsiFile -> file.isValid
|
||||||
is VirtualFile -> file.isValid
|
is VirtualFile -> file.isValid
|
||||||
is File -> file.exists() && file.isFile
|
is File -> file.exists() && file.isFile
|
||||||
else -> throw IllegalArgumentException("Unsupported file type $file")
|
else -> throw IllegalArgumentException("Unsupported file type $file")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <TF> getFile(file: TF): File? = when (file) {
|
fun <TF: Any> getFile(file: TF): File? = when (file) {
|
||||||
is PsiFile -> file.originalFile.run { File(virtualFile?.path) }
|
is PsiFile -> file.originalFile.run { File(virtualFile?.path) }
|
||||||
is VirtualFile -> File(file.path)
|
is VirtualFile -> File(file.path)
|
||||||
is File -> file
|
is File -> file
|
||||||
else -> throw IllegalArgumentException("Unsupported file type $file")
|
else -> throw IllegalArgumentException("Unsupported file type $file")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <TF> getFileContents(file: TF): CharSequence = when (file) {
|
fun <TF: Any> getFileContents(file: TF): CharSequence = when (file) {
|
||||||
is PsiFile -> file.viewProvider.contents
|
is PsiFile -> file.viewProvider.contents
|
||||||
is VirtualFile -> file.inputStream.reader(charset = file.charset).readText()
|
is VirtualFile -> file.inputStream.reader(charset = file.charset).readText()
|
||||||
is File -> file.readText()
|
is File -> file.readText()
|
||||||
else -> throw IllegalArgumentException("Unsupported file type $file")
|
else -> throw IllegalArgumentException("Unsupported file type $file")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <TF> getFileContentsStream(file: TF): InputStream = when (file) {
|
fun <TF: Any> getFileContentsStream(file: TF): InputStream = when (file) {
|
||||||
is PsiFile -> file.viewProvider.contents.toString().byteInputStream()
|
is PsiFile -> file.viewProvider.contents.toString().byteInputStream()
|
||||||
is VirtualFile -> file.inputStream
|
is VirtualFile -> file.inputStream
|
||||||
is File -> file.inputStream()
|
is File -> file.inputStream()
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ class KotlinConsoleRunner(
|
|||||||
|
|
||||||
private val consoleScriptDefinition = object : KotlinScriptDefinition(Any::class) {
|
private val consoleScriptDefinition = object : KotlinScriptDefinition(Any::class) {
|
||||||
override val name = "Kotlin REPL"
|
override val name = "Kotlin REPL"
|
||||||
override fun <TF> isScript(file: TF): Boolean {
|
override fun <TF: Any> isScript(file: TF): Boolean {
|
||||||
val vf = when (file) {
|
val vf = when (file) {
|
||||||
is PsiFile -> file.originalFile.virtualFile
|
is PsiFile -> file.originalFile.virtualFile
|
||||||
is VirtualFile -> file
|
is VirtualFile -> file
|
||||||
|
|||||||
Reference in New Issue
Block a user