Move CliScriptDefinition provider to the plugin too, fix tests
This commit is contained in:
-7
@@ -14,7 +14,6 @@ import com.intellij.psi.PsiFile
|
|||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
import com.intellij.util.PathUtil
|
import com.intellij.util.PathUtil
|
||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.cli.common.script.CliScriptDefinitionProvider
|
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.FirRenderer
|
import org.jetbrains.kotlin.fir.FirRenderer
|
||||||
import org.jetbrains.kotlin.fir.FirSessionBase
|
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.parsing.KotlinParserDefinition
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||||
import org.jetbrains.kotlin.script.ScriptDefinitionProvider
|
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.jetbrains.kotlin.test.testFramework.KtParsingTestCase
|
import org.jetbrains.kotlin.test.testFramework.KtParsingTestCase
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -39,11 +37,6 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
|
|||||||
"kt",
|
"kt",
|
||||||
KotlinParserDefinition()
|
KotlinParserDefinition()
|
||||||
) {
|
) {
|
||||||
override fun setUp() {
|
|
||||||
super.setUp()
|
|
||||||
project.registerService(ScriptDefinitionProvider::class.java, CliScriptDefinitionProvider::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getTestDataPath() = KotlinTestUtils.getHomeDirectory()
|
override fun getTestDataPath() = KotlinTestUtils.getHomeDirectory()
|
||||||
|
|
||||||
private fun createFile(filePath: String, fileType: IElementType): PsiFile {
|
private fun createFile(filePath: String, fileType: IElementType): PsiFile {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package org.jetbrains.kotlin.script
|
package org.jetbrains.kotlin.script
|
||||||
|
|
||||||
import com.intellij.ide.highlighter.JavaClassFileType
|
import com.intellij.ide.highlighter.JavaClassFileType
|
||||||
import com.intellij.ide.highlighter.JavaFileType
|
|
||||||
import com.intellij.openapi.components.ServiceManager
|
import com.intellij.openapi.components.ServiceManager
|
||||||
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
@@ -25,9 +24,6 @@ import com.intellij.openapi.vfs.VirtualFile
|
|||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
|
||||||
import kotlin.concurrent.read
|
|
||||||
import kotlin.concurrent.write
|
|
||||||
|
|
||||||
interface ScriptDefinitionProvider {
|
interface ScriptDefinitionProvider {
|
||||||
fun findScriptDefinition(fileName: String): KotlinScriptDefinition?
|
fun findScriptDefinition(fileName: String): KotlinScriptDefinition?
|
||||||
@@ -73,76 +69,3 @@ private fun isKotlinFileType(file: VirtualFile): Boolean {
|
|||||||
typeRegistry.getFileTypeByFileName(file.name) == KotlinFileType.INSTANCE
|
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.tree.IElementType;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import com.intellij.util.PathUtil;
|
import com.intellij.util.PathUtil;
|
||||||
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.KtNodeTypes;
|
import org.jetbrains.kotlin.KtNodeTypes;
|
||||||
import org.jetbrains.kotlin.TestsCompilerError;
|
import org.jetbrains.kotlin.TestsCompilerError;
|
||||||
import org.jetbrains.kotlin.cli.common.script.CliScriptDefinitionProvider;
|
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.script.ScriptDefinitionProvider;
|
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
import org.jetbrains.kotlin.test.testFramework.KtParsingTestCase;
|
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.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
import kotlin.jvm.functions.Function1;
|
|
||||||
|
|
||||||
public abstract class AbstractParsingTest extends KtParsingTestCase {
|
public abstract class AbstractParsingTest extends KtParsingTestCase {
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
getProject().registerService(ScriptDefinitionProvider.class, CliScriptDefinitionProvider.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTestDataPath() {
|
protected String getTestDataPath() {
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
package org.jetbrains.kotlin.parsing;
|
package org.jetbrains.kotlin.parsing;
|
||||||
|
|
||||||
import com.intellij.testFramework.TestDataPath;
|
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.JUnit3RunnerWithInners;
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
import org.jetbrains.kotlin.test.TargetBackend;
|
import org.jetbrains.kotlin.test.TargetBackend;
|
||||||
@@ -2473,6 +2475,13 @@ public class ParsingTestGenerated extends AbstractParsingTest {
|
|||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
public static class Script extends AbstractParsingTest {
|
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 {
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
KotlinTestUtils.runTest(this::doParsingTest, TargetBackend.ANY, testDataFilePath);
|
KotlinTestUtils.runTest(this::doParsingTest, TargetBackend.ANY, testDataFilePath);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.scripts
|
package org.jetbrains.kotlin.scripts
|
||||||
|
|
||||||
import org.jetbrains.kotlin.cli.common.script.CliScriptDefinitionProvider
|
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
import org.jetbrains.kotlin.script.ScriptDefinitionsSource
|
import org.jetbrains.kotlin.script.ScriptDefinitionsSource
|
||||||
|
import org.jetbrains.kotlin.scripting.legacy.CliScriptDefinitionProvider
|
||||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|||||||
+5
-1
@@ -38,8 +38,12 @@ import org.jetbrains.kotlin.idea.KotlinFileType
|
|||||||
import org.jetbrains.kotlin.idea.caches.project.SdkInfo
|
import org.jetbrains.kotlin.idea.caches.project.SdkInfo
|
||||||
import org.jetbrains.kotlin.idea.caches.project.getScriptRelatedModuleInfo
|
import org.jetbrains.kotlin.idea.caches.project.getScriptRelatedModuleInfo
|
||||||
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
||||||
import org.jetbrains.kotlin.script.*
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
|
import org.jetbrains.kotlin.script.ScriptDefinitionProvider
|
||||||
|
import org.jetbrains.kotlin.script.ScriptTemplatesProvider
|
||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.KotlinScriptDefinitionAdapterFromNewAPI
|
import org.jetbrains.kotlin.scripting.compiler.plugin.KotlinScriptDefinitionAdapterFromNewAPI
|
||||||
|
import org.jetbrains.kotlin.scripting.legacy.LazyScriptDefinitionProvider
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.flattenTo
|
import org.jetbrains.kotlin.utils.addToStdlib.flattenTo
|
||||||
|
|||||||
+6
-4
@@ -10,9 +10,8 @@ import com.intellij.mock.MockProject
|
|||||||
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
||||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.cli.common.script.CliScriptDefinitionProvider
|
import org.jetbrains.kotlin.scripting.legacy.CliScriptDependenciesProvider
|
||||||
import org.jetbrains.kotlin.cli.common.script.CliScriptDependenciesProvider
|
import org.jetbrains.kotlin.scripting.legacy.CliScriptReportSink
|
||||||
import org.jetbrains.kotlin.cli.common.script.CliScriptReportSink
|
|
||||||
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
||||||
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
@@ -23,6 +22,7 @@ import org.jetbrains.kotlin.script.ScriptDefinitionProvider
|
|||||||
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
||||||
import org.jetbrains.kotlin.script.ScriptReportSink
|
import org.jetbrains.kotlin.script.ScriptReportSink
|
||||||
import org.jetbrains.kotlin.script.StandardScriptDefinition
|
import org.jetbrains.kotlin.script.StandardScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.legacy.CliScriptDefinitionProvider
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class ScriptingCompilerConfigurationExtension(val project: MockProject) : CompilerConfigurationExtension {
|
class ScriptingCompilerConfigurationExtension(val project: MockProject) : CompilerConfigurationExtension {
|
||||||
@@ -108,7 +108,9 @@ class ScriptingCompilerConfigurationComponentRegistrar : ComponentRegistrar {
|
|||||||
|
|
||||||
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||||
if (messageCollector != null) {
|
if (messageCollector != null) {
|
||||||
project.registerService(ScriptReportSink::class.java, CliScriptReportSink(messageCollector))
|
project.registerService(ScriptReportSink::class.java,
|
||||||
|
CliScriptReportSink(messageCollector)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-15
@@ -1,23 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2017 JetBrains s.r.o.
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
*
|
* that can be found in the license/LICENSE.txt file.
|
||||||
* 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
|
package org.jetbrains.kotlin.scripting.legacy
|
||||||
|
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
import org.jetbrains.kotlin.script.LazyScriptDefinitionProvider
|
|
||||||
import org.jetbrains.kotlin.script.ScriptDefinitionsSource
|
import org.jetbrains.kotlin.script.ScriptDefinitionsSource
|
||||||
import org.jetbrains.kotlin.script.StandardScriptDefinition
|
import org.jetbrains.kotlin.script.StandardScriptDefinition
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.cli.common.script
|
package org.jetbrains.kotlin.scripting.legacy
|
||||||
|
|
||||||
import com.intellij.openapi.components.ServiceManager
|
import com.intellij.openapi.components.ServiceManager
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
+4
-15
@@ -1,20 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2017 JetBrains s.r.o.
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
*
|
* that can be found in the license/LICENSE.txt file.
|
||||||
* 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
|
package org.jetbrains.kotlin.scripting.legacy
|
||||||
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||||
@@ -23,7 +12,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
|||||||
import org.jetbrains.kotlin.script.ScriptReportSink
|
import org.jetbrains.kotlin.script.ScriptReportSink
|
||||||
import kotlin.script.experimental.dependencies.ScriptReport
|
import kotlin.script.experimental.dependencies.ScriptReport
|
||||||
|
|
||||||
class CliScriptReportSink(private val messageCollector: MessageCollector) : ScriptReportSink {
|
internal class CliScriptReportSink(private val messageCollector: MessageCollector) : ScriptReportSink {
|
||||||
override fun attachReports(scriptFile: VirtualFile, reports: List<ScriptReport>) {
|
override fun attachReports(scriptFile: VirtualFile, reports: List<ScriptReport>) {
|
||||||
reports.forEach {
|
reports.forEach {
|
||||||
messageCollector.report(it.severity.convertSeverity(), it.message, location(scriptFile, it.position))
|
messageCollector.report(it.severity.convertSeverity(), it.message, location(scriptFile, it.position))
|
||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. 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.legacy
|
||||||
|
|
||||||
|
import com.intellij.ide.highlighter.JavaFileType
|
||||||
|
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||||
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.script.ScriptDefinitionProvider
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
|
import kotlin.concurrent.read
|
||||||
|
import kotlin.concurrent.write
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user