Improve type boundaries for KotlinScriptDefinition interface

This commit is contained in:
Ilya Chernikov
2016-12-02 17:02:09 +01:00
parent cfcd3b8186
commit 28b01126d9
6 changed files with 24 additions and 24 deletions
@@ -37,13 +37,13 @@ open class KotlinScriptDefinition(val template: KClass<out Any>) {
open val annotationsForSamWithReceivers: List<String>
get() = emptyList()
open fun <TF> isScript(file: TF): Boolean =
open fun <TF: Any> isScript(file: TF): Boolean =
getFileName(file).endsWith(KotlinParserDefinition.STD_SCRIPT_EXT)
open fun getScriptName(script: KtScript): Name =
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> {
@@ -81,19 +81,19 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
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)) }
// 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 <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) {
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
try {
getAnnotationEntries(file, project)
@@ -112,7 +112,7 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
})
try {
val fileDeps = resolver?.resolve(script, environment, ::logScriptDefMessage, previousDependencies)
val fileDeps = resolver?.resolve(makeScriptContents(), environment, ::logScriptDefMessage, previousDependencies)
// TODO: use it as a Future
return fileDeps?.get()
}
@@ -122,7 +122,7 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
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 VirtualFile -> getAnnotationEntriesFromVirtualFile(file, project)
is File -> {
@@ -143,7 +143,7 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
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 annotations: Iterable<Annotation> by lazy { getAnnotations() }
override val text: CharSequence? by lazy { getFileContents(myFile) }
@@ -44,11 +44,11 @@ class KotlinScriptDefinitionProvider {
return changed
}
fun<TF> findScriptDefinition(file: TF): KotlinScriptDefinition? = definitionsLock.read {
fun<TF: Any> findScriptDefinition(file: TF): KotlinScriptDefinition? = definitionsLock.read {
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) {
definitionsLock.write {
@@ -31,13 +31,13 @@ class KotlinScriptExternalImportsProvider(val project: Project, private val scri
private val cache = hashMapOf<String, KotlinScriptExternalDependencies>()
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) }
}
private fun <TF> calculateExternalDependencies(file: TF): KotlinScriptExternalDependencies? {
private fun <TF: Any> calculateExternalDependencies(file: TF): KotlinScriptExternalDependencies? {
val path = getFilePath(file)
return cache[path]
?: 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
fun <TF> cacheExternalImports(files: Iterable<TF>): Unit = cacheLock.write {
fun <TF: Any> cacheExternalImports(files: Iterable<TF>): Unit = cacheLock.write {
val uncached = hashSetOf<String>()
files.forEach { 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 {
files.forEach { file ->
val path = getFilePath(file)
@@ -150,7 +150,7 @@ class KotlinScriptExternalImportsProvider(val project: Project, private val scri
cache.values.flatMap { it.sources }
}.distinct()
fun <TF> getCombinedClasspathFor(files: Iterable<TF>): List<File> =
fun <TF: Any> getCombinedClasspathFor(files: Iterable<TF>): List<File> =
getExternalImports(files)
.flatMap { it.classpath }
.distinct()
@@ -21,42 +21,42 @@ import com.intellij.psi.PsiFile
import java.io.File
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 VirtualFile -> file.name
is File -> file.name
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 VirtualFile -> file.path
is File -> file.canonicalPath
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 VirtualFile -> file.isValid
is File -> file.exists() && file.isFile
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 VirtualFile -> File(file.path)
is File -> 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 VirtualFile -> file.inputStream.reader(charset = file.charset).readText()
is File -> file.readText()
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 VirtualFile -> file.inputStream
is File -> file.inputStream()
@@ -126,7 +126,7 @@ class KotlinConsoleRunner(
private val consoleScriptDefinition = object : KotlinScriptDefinition(Any::class) {
override val name = "Kotlin REPL"
override fun <TF> isScript(file: TF): Boolean {
override fun <TF: Any> isScript(file: TF): Boolean {
val vf = when (file) {
is PsiFile -> file.originalFile.virtualFile
is VirtualFile -> file