Move CliScriptDefinition provider to the plugin too, fix tests
This commit is contained in:
-51
@@ -1,51 +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.common.script
|
||||
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import org.jetbrains.kotlin.script.LazyScriptDefinitionProvider
|
||||
import org.jetbrains.kotlin.script.ScriptDefinitionsSource
|
||||
import org.jetbrains.kotlin.script.StandardScriptDefinition
|
||||
import kotlin.concurrent.write
|
||||
|
||||
class CliScriptDefinitionProvider : LazyScriptDefinitionProvider() {
|
||||
private val definitionsFromSources: MutableList<Sequence<KotlinScriptDefinition>> = arrayListOf()
|
||||
private val definitions: MutableList<KotlinScriptDefinition> = arrayListOf(StandardScriptDefinition)
|
||||
|
||||
override val currentDefinitions: Sequence<KotlinScriptDefinition> =
|
||||
definitionsFromSources.asSequence().flatMap { it } + definitions.asSequence()
|
||||
|
||||
override fun getDefaultScriptDefinition(): KotlinScriptDefinition {
|
||||
return StandardScriptDefinition
|
||||
}
|
||||
|
||||
fun setScriptDefinitions(newDefinitions: List<KotlinScriptDefinition>) {
|
||||
lock.write {
|
||||
definitions.clear()
|
||||
definitions.addAll(newDefinitions)
|
||||
}
|
||||
}
|
||||
|
||||
fun setScriptDefinitionsSources(newSources: List<ScriptDefinitionsSource>) {
|
||||
lock.write {
|
||||
definitionsFromSources.clear()
|
||||
for (it in newSources) {
|
||||
definitionsFromSources.add(it.definitions.constrainOnce())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-64
@@ -1,64 +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.common.script
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.script.*
|
||||
import java.io.File
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.concurrent.read
|
||||
import kotlin.concurrent.write
|
||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||
|
||||
class CliScriptDependenciesProvider(private val project: Project) : ScriptDependenciesProvider {
|
||||
private val cacheLock = ReentrantReadWriteLock()
|
||||
private val cache = hashMapOf<String, ScriptDependencies?>()
|
||||
private val scriptContentLoader = ScriptContentLoader(project)
|
||||
|
||||
override fun getScriptDependencies(file: VirtualFile): ScriptDependencies? = cacheLock.read {
|
||||
calculateExternalDependencies(file)
|
||||
}
|
||||
|
||||
private fun calculateExternalDependencies(file: VirtualFile): ScriptDependencies? {
|
||||
val path = file.path
|
||||
val cached = cache[path]
|
||||
return if (cached != null) cached
|
||||
else {
|
||||
val scriptDef = findScriptDefinition(file, project)
|
||||
if (scriptDef != null) {
|
||||
val result = scriptContentLoader.loadContentsAndResolveDependencies(scriptDef, file)
|
||||
|
||||
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports)
|
||||
|
||||
val deps = result.dependencies?.adjustByDefinition(scriptDef)
|
||||
|
||||
if (deps != null) {
|
||||
log.info("[kts] new cached deps for $path: ${deps.classpath.joinToString(File.pathSeparator)}")
|
||||
}
|
||||
cacheLock.write {
|
||||
cache.put(path, deps)
|
||||
}
|
||||
deps
|
||||
} else null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val log = Logger.getInstance(ScriptDependenciesProvider::class.java)
|
||||
@@ -1,46 +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.common.script
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.script.ScriptReportSink
|
||||
import kotlin.script.experimental.dependencies.ScriptReport
|
||||
|
||||
class CliScriptReportSink(private val messageCollector: MessageCollector) : ScriptReportSink {
|
||||
override fun attachReports(scriptFile: VirtualFile, reports: List<ScriptReport>) {
|
||||
reports.forEach {
|
||||
messageCollector.report(it.severity.convertSeverity(), it.message, location(scriptFile, it.position))
|
||||
}
|
||||
}
|
||||
|
||||
private fun location(scriptFile: VirtualFile, position: ScriptReport.Position?): CompilerMessageLocation? {
|
||||
if (position == null) return CompilerMessageLocation.create(scriptFile.path)
|
||||
|
||||
return CompilerMessageLocation.create(scriptFile.path, position.startLine, position.startColumn, null)
|
||||
}
|
||||
|
||||
private fun ScriptReport.Severity.convertSeverity(): CompilerMessageSeverity = when (this) {
|
||||
ScriptReport.Severity.FATAL -> CompilerMessageSeverity.ERROR
|
||||
ScriptReport.Severity.ERROR -> CompilerMessageSeverity.ERROR
|
||||
ScriptReport.Severity.WARNING -> CompilerMessageSeverity.WARNING
|
||||
ScriptReport.Severity.INFO -> CompilerMessageSeverity.INFO
|
||||
ScriptReport.Severity.DEBUG -> CompilerMessageSeverity.LOGGING
|
||||
}
|
||||
}
|
||||
-7
@@ -14,7 +14,6 @@ import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.util.PathUtil
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.cli.common.script.CliScriptDefinitionProvider
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.FirSessionBase
|
||||
@@ -27,7 +26,6 @@ import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.script.ScriptDefinitionProvider
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.testFramework.KtParsingTestCase
|
||||
import java.io.File
|
||||
@@ -39,11 +37,6 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
|
||||
"kt",
|
||||
KotlinParserDefinition()
|
||||
) {
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
project.registerService(ScriptDefinitionProvider::class.java, CliScriptDefinitionProvider::class.java)
|
||||
}
|
||||
|
||||
override fun getTestDataPath() = KotlinTestUtils.getHomeDirectory()
|
||||
|
||||
private fun createFile(filePath: String, fileType: IElementType): PsiFile {
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.script
|
||||
|
||||
import com.intellij.ide.highlighter.JavaClassFileType
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
||||
import com.intellij.openapi.project.Project
|
||||
@@ -25,9 +24,6 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.concurrent.read
|
||||
import kotlin.concurrent.write
|
||||
|
||||
interface ScriptDefinitionProvider {
|
||||
fun findScriptDefinition(fileName: String): KotlinScriptDefinition?
|
||||
@@ -73,76 +69,3 @@ private fun isKotlinFileType(file: VirtualFile): Boolean {
|
||||
typeRegistry.getFileTypeByFileName(file.name) == KotlinFileType.INSTANCE
|
||||
}
|
||||
|
||||
abstract class LazyScriptDefinitionProvider : ScriptDefinitionProvider {
|
||||
|
||||
protected val lock = ReentrantReadWriteLock()
|
||||
|
||||
protected abstract val currentDefinitions: Sequence<KotlinScriptDefinition>
|
||||
|
||||
private var _cachedDefinitions: Sequence<KotlinScriptDefinition>? = null
|
||||
private val cachedDefinitions: Sequence<KotlinScriptDefinition>
|
||||
get() {
|
||||
assert(lock.readLockCount > 0) { "cachedDefinitions should only be used under the read lock" }
|
||||
if (_cachedDefinitions == null) lock.write {
|
||||
_cachedDefinitions = CachingSequence(currentDefinitions.constrainOnce())
|
||||
}
|
||||
return _cachedDefinitions!!
|
||||
}
|
||||
|
||||
protected fun clearCache() {
|
||||
lock.write {
|
||||
_cachedDefinitions = null
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun nonScriptFileName(fileName: String) = nonScriptFilenameSuffixes.any {
|
||||
fileName.endsWith(it, ignoreCase = true)
|
||||
}
|
||||
|
||||
override fun findScriptDefinition(fileName: String): KotlinScriptDefinition? =
|
||||
if (nonScriptFileName(fileName)) null
|
||||
else lock.read {
|
||||
cachedDefinitions.firstOrNull { it.isScript(fileName) }
|
||||
}
|
||||
|
||||
override fun isScript(fileName: String) = findScriptDefinition(fileName) != null
|
||||
|
||||
override fun getKnownFilenameExtensions(): Sequence<String> = lock.read {
|
||||
cachedDefinitions.map { it.fileExtension }
|
||||
}
|
||||
|
||||
companion object {
|
||||
// TODO: find a common place for storing kotlin-related extensions and reuse values from it everywhere
|
||||
protected val nonScriptFilenameSuffixes = arrayOf(".${KotlinFileType.EXTENSION}", ".${JavaFileType.DEFAULT_EXTENSION}")
|
||||
}
|
||||
}
|
||||
|
||||
private class CachingSequence<T>(from: Sequence<T>) : Sequence<T> {
|
||||
|
||||
private val lock = ReentrantReadWriteLock()
|
||||
private val sequenceIterator = from.iterator()
|
||||
private val cache = arrayListOf<T>()
|
||||
|
||||
private inner class CachingIterator : Iterator<T> {
|
||||
|
||||
private var cacheCursor = 0
|
||||
|
||||
override fun hasNext(): Boolean =
|
||||
lock.read { cacheCursor < cache.size }
|
||||
// iterator's hasNext can mutate the iterator's state, therefore write lock is needed
|
||||
|| lock.write { cacheCursor < cache.size || sequenceIterator.hasNext() }
|
||||
|
||||
override fun next(): T {
|
||||
lock.read {
|
||||
if (cacheCursor < cache.size) return cache[cacheCursor++]
|
||||
}
|
||||
// lock.write is not an upgrade but retake, therefore - one more check needed
|
||||
lock.write {
|
||||
return if (cacheCursor < cache.size) cache[cacheCursor++]
|
||||
else sequenceIterator.next().also { cache.add(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun iterator(): Iterator<T> = CachingIterator()
|
||||
}
|
||||
|
||||
@@ -26,12 +26,11 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.PathUtil;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.KtNodeTypes;
|
||||
import org.jetbrains.kotlin.TestsCompilerError;
|
||||
import org.jetbrains.kotlin.cli.common.script.CliScriptDefinitionProvider;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.script.ScriptDefinitionProvider;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.testFramework.KtParsingTestCase;
|
||||
|
||||
@@ -39,14 +38,7 @@ import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import kotlin.jvm.functions.Function1;
|
||||
|
||||
public abstract class AbstractParsingTest extends KtParsingTestCase {
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
getProject().registerService(ScriptDefinitionProvider.class, CliScriptDefinitionProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
package org.jetbrains.kotlin.parsing;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.script.ScriptDefinitionProvider;
|
||||
import org.jetbrains.kotlin.scripting.legacy.CliScriptDefinitionProvider;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TargetBackend;
|
||||
@@ -2473,6 +2475,13 @@ public class ParsingTestGenerated extends AbstractParsingTest {
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Script extends AbstractParsingTest {
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
getProject().registerService(ScriptDefinitionProvider.class, CliScriptDefinitionProvider.class);
|
||||
}
|
||||
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doParsingTest, TargetBackend.ANY, testDataFilePath);
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.scripts
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.script.CliScriptDefinitionProvider
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import org.jetbrains.kotlin.script.ScriptDefinitionsSource
|
||||
import org.jetbrains.kotlin.scripting.legacy.CliScriptDefinitionProvider
|
||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
||||
Reference in New Issue
Block a user