[kotlin] K2: main.kts highlighting

^KTIJ-30172 Fixed

GitOrigin-RevId: cdf6b2e08439e91e364dd8d3fa908d99e73c081b
This commit is contained in:
Vlad Koshkin
2024-05-24 11:13:39 +02:00
committed by intellij-monorepo-bot
parent 7596f6e291
commit e15901a830
29 changed files with 549 additions and 388 deletions

View File

@@ -17,7 +17,7 @@ object MetadataStorageImpl: MetadataStorageBase() {
var typeMetadata: StorageTypeMetadata
typeMetadata = FinalClassMetadata.ObjectMetadata(fqName = "org.jetbrains.kotlin.idea.core.script.KotlinK2ScriptEntitySource", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "virtualFileUrl", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = true, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.url.VirtualFileUrl")), withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.EntitySource"))
typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "org.jetbrains.kotlin.idea.core.script.KotlinScriptEntitySourceK2", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "virtualFileUrl", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.url.VirtualFileUrl")), withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.EntitySource"))
addMetadata(typeMetadata)
@@ -71,7 +71,7 @@ OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name =
addMetadataHash(typeFqn = "org.jetbrains.kotlin.idea.core.script.ucache.KotlinScriptLibraryRoot", metadataHash = 940316485)
addMetadataHash(typeFqn = "org.jetbrains.kotlin.idea.core.script.ucache.KotlinScriptLibraryRootTypeId", metadataHash = -2068549764)
addMetadataHash(typeFqn = "com.intellij.platform.workspace.storage.EntitySource", metadataHash = 1946578919)
addMetadataHash(typeFqn = "org.jetbrains.kotlin.idea.core.script.KotlinK2ScriptEntitySource", metadataHash = 782346369)
addMetadataHash(typeFqn = "org.jetbrains.kotlin.idea.core.script.KotlinScriptEntitySourceK2", metadataHash = -860768271)
addMetadataHash(typeFqn = "org.jetbrains.kotlin.idea.core.script.ucache.KotlinScriptEntitySource", metadataHash = 236614476)
addMetadataHash(typeFqn = "org.jetbrains.kotlin.idea.core.script.ucache.KotlinScriptLibraryEntitySource", metadataHash = 1353548779)
addMetadataHash(typeFqn = "com.intellij.platform.workspace.storage.SymbolicEntityId", metadataHash = -194396395)

View File

@@ -21,280 +21,281 @@ import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInst
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
import kotlin.jvm.JvmName
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmStatic
@GeneratedCodeApiVersion(3)
@GeneratedCodeImplVersion(5)
open class KotlinScriptEntityImpl(private val dataSource: KotlinScriptEntityData) : KotlinScriptEntity, WorkspaceEntityBase(dataSource) {
private companion object {
private companion object {
private val connections = listOf<ConnectionId>(
)
private val connections = listOf<ConnectionId>(
)
}
override val path: String
get() {
readField("path")
return dataSource.path
}
override val path: String
get() {
readField("path")
return dataSource.path
}
override val dependencies: Set<KotlinScriptLibraryId>
get() {
readField("dependencies")
return dataSource.dependencies
}
override val dependencies: Set<KotlinScriptLibraryId>
get() {
readField("dependencies")
return dataSource.dependencies
}
override val entitySource: EntitySource
get() {
readField("entitySource")
return dataSource.entitySource
}
override val entitySource: EntitySource
get() {
readField("entitySource")
return dataSource.entitySource
override fun connectionIdList(): List<ConnectionId> {
return connections
}
class Builder(result: KotlinScriptEntityData?) : ModifiableWorkspaceEntityBase<KotlinScriptEntity, KotlinScriptEntityData>(
result), KotlinScriptEntity.Builder {
constructor() : this(KotlinScriptEntityData())
override fun applyToBuilder(builder: MutableEntityStorage) {
if (this.diff != null) {
if (existsInBuilder(builder)) {
this.diff = builder
return
}
else {
error("Entity KotlinScriptEntity is already created in a different builder")
}
}
this.diff = builder
addToBuilder()
this.id = getEntityData().createEntityId()
// After adding entity data to the builder, we need to unbind it and move the control over entity data to builder
// Builder may switch to snapshot at any moment and lock entity data to modification
this.currentEntityData = null
// Process linked entities that are connected without a builder
processLinkedEntities(builder)
checkInitialization() // TODO uncomment and check failed tests
}
private fun checkInitialization() {
val _diff = diff
if (!getEntityData().isEntitySourceInitialized()) {
error("Field WorkspaceEntity#entitySource should be initialized")
}
if (!getEntityData().isPathInitialized()) {
error("Field KotlinScriptEntity#path should be initialized")
}
if (!getEntityData().isDependenciesInitialized()) {
error("Field KotlinScriptEntity#dependencies should be initialized")
}
}
override fun connectionIdList(): List<ConnectionId> {
return connections
return connections
}
override fun afterModification() {
val collection_dependencies = getEntityData().dependencies
if (collection_dependencies is MutableWorkspaceSet<*>) {
collection_dependencies.cleanModificationUpdateAction()
}
}
// Relabeling code, move information from dataSource to this builder
override fun relabel(dataSource: WorkspaceEntity, parents: Set<WorkspaceEntity>?) {
dataSource as KotlinScriptEntity
if (this.entitySource != dataSource.entitySource) this.entitySource = dataSource.entitySource
if (this.path != dataSource.path) this.path = dataSource.path
if (this.dependencies != dataSource.dependencies) this.dependencies = dataSource.dependencies.toMutableSet()
updateChildToParentReferences(parents)
}
class Builder(result: KotlinScriptEntityData?) : ModifiableWorkspaceEntityBase<KotlinScriptEntity, KotlinScriptEntityData>(result),
KotlinScriptEntity.Builder {
constructor() : this(KotlinScriptEntityData())
override var entitySource: EntitySource
get() = getEntityData().entitySource
set(value) {
checkModificationAllowed()
getEntityData(true).entitySource = value
changedProperty.add("entitySource")
override fun applyToBuilder(builder: MutableEntityStorage) {
if (this.diff != null) {
if (existsInBuilder(builder)) {
this.diff = builder
return
} else {
error("Entity KotlinScriptEntity is already created in a different builder")
}
}
}
this.diff = builder
addToBuilder()
this.id = getEntityData().createEntityId()
// After adding entity data to the builder, we need to unbind it and move the control over entity data to builder
// Builder may switch to snapshot at any moment and lock entity data to modification
this.currentEntityData = null
override var path: String
get() = getEntityData().path
set(value) {
checkModificationAllowed()
getEntityData(true).path = value
changedProperty.add("path")
}
// Process linked entities that are connected without a builder
processLinkedEntities(builder)
checkInitialization() // TODO uncomment and check failed tests
}
private val dependenciesUpdater: (value: Set<KotlinScriptLibraryId>) -> Unit = { value ->
private fun checkInitialization() {
val _diff = diff
if (!getEntityData().isEntitySourceInitialized()) {
error("Field WorkspaceEntity#entitySource should be initialized")
}
if (!getEntityData().isPathInitialized()) {
error("Field KotlinScriptEntity#path should be initialized")
}
if (!getEntityData().isDependenciesInitialized()) {
error("Field KotlinScriptEntity#dependencies should be initialized")
}
}
override fun connectionIdList(): List<ConnectionId> {
return connections
}
override fun afterModification() {
val collection_dependencies = getEntityData().dependencies
if (collection_dependencies is MutableWorkspaceSet<*>) {
collection_dependencies.cleanModificationUpdateAction()
}
}
// Relabeling code, move information from dataSource to this builder
override fun relabel(dataSource: WorkspaceEntity, parents: Set<WorkspaceEntity>?) {
dataSource as KotlinScriptEntity
if (this.entitySource != dataSource.entitySource) this.entitySource = dataSource.entitySource
if (this.path != dataSource.path) this.path = dataSource.path
if (this.dependencies != dataSource.dependencies) this.dependencies = dataSource.dependencies.toMutableSet()
updateChildToParentReferences(parents)
}
override var entitySource: EntitySource
get() = getEntityData().entitySource
set(value) {
checkModificationAllowed()
getEntityData(true).entitySource = value
changedProperty.add("entitySource")
}
override var path: String
get() = getEntityData().path
set(value) {
checkModificationAllowed()
getEntityData(true).path = value
changedProperty.add("path")
}
private val dependenciesUpdater: (value: Set<KotlinScriptLibraryId>) -> Unit = { value ->
changedProperty.add("dependencies")
}
override var dependencies: MutableSet<KotlinScriptLibraryId>
get() {
val collection_dependencies = getEntityData().dependencies
if (collection_dependencies !is MutableWorkspaceSet) return collection_dependencies
if (diff == null || modifiable.get()) {
collection_dependencies.setModificationUpdateAction(dependenciesUpdater)
} else {
collection_dependencies.cleanModificationUpdateAction()
}
return collection_dependencies
}
set(value) {
checkModificationAllowed()
getEntityData(true).dependencies = value
dependenciesUpdater.invoke(value)
}
override fun getEntityClass(): Class<KotlinScriptEntity> = KotlinScriptEntity::class.java
changedProperty.add("dependencies")
}
override var dependencies: MutableSet<KotlinScriptLibraryId>
get() {
val collection_dependencies = getEntityData().dependencies
if (collection_dependencies !is MutableWorkspaceSet) return collection_dependencies
if (diff == null || modifiable.get()) {
collection_dependencies.setModificationUpdateAction(dependenciesUpdater)
}
else {
collection_dependencies.cleanModificationUpdateAction()
}
return collection_dependencies
}
set(value) {
checkModificationAllowed()
getEntityData(true).dependencies = value
dependenciesUpdater.invoke(value)
}
override fun getEntityClass(): Class<KotlinScriptEntity> = KotlinScriptEntity::class.java
}
}
class KotlinScriptEntityData : WorkspaceEntityData<KotlinScriptEntity>(), SoftLinkable {
lateinit var path: String
lateinit var dependencies: MutableSet<KotlinScriptLibraryId>
lateinit var path: String
lateinit var dependencies: MutableSet<KotlinScriptLibraryId>
internal fun isPathInitialized(): Boolean = ::path.isInitialized
internal fun isDependenciesInitialized(): Boolean = ::dependencies.isInitialized
internal fun isPathInitialized(): Boolean = ::path.isInitialized
internal fun isDependenciesInitialized(): Boolean = ::dependencies.isInitialized
override fun getLinks(): Set<SymbolicEntityId<*>> {
val result = HashSet<SymbolicEntityId<*>>()
for (item in dependencies) {
result.add(item)
}
return result
override fun getLinks(): Set<SymbolicEntityId<*>> {
val result = HashSet<SymbolicEntityId<*>>()
for (item in dependencies) {
result.add(item)
}
return result
}
override fun index(index: WorkspaceMutableIndex<SymbolicEntityId<*>>) {
for (item in dependencies) {
index.index(this, item)
}
override fun index(index: WorkspaceMutableIndex<SymbolicEntityId<*>>) {
for (item in dependencies) {
index.index(this, item)
}
}
override fun updateLinksIndex(prev: Set<SymbolicEntityId<*>>, index: WorkspaceMutableIndex<SymbolicEntityId<*>>) {
// TODO verify logic
val mutablePreviousSet = HashSet(prev)
for (item in dependencies) {
val removedItem_item = mutablePreviousSet.remove(item)
if (!removedItem_item) {
index.index(this, item)
}
}
for (removed in mutablePreviousSet) {
index.remove(this, removed)
}
override fun updateLinksIndex(prev: Set<SymbolicEntityId<*>>, index: WorkspaceMutableIndex<SymbolicEntityId<*>>) {
// TODO verify logic
val mutablePreviousSet = HashSet(prev)
for (item in dependencies) {
val removedItem_item = mutablePreviousSet.remove(item)
if (!removedItem_item) {
index.index(this, item)
}
}
override fun updateLink(oldLink: SymbolicEntityId<*>, newLink: SymbolicEntityId<*>): Boolean {
var changed = false
val dependencies_data = dependencies.map {
val it_data = if (it == oldLink) {
changed = true
newLink as KotlinScriptLibraryId
} else {
null
}
if (it_data != null) {
it_data
} else {
it
}
}
if (dependencies_data != null) {
dependencies = dependencies_data as MutableSet<KotlinScriptLibraryId>
}
return changed
for (removed in mutablePreviousSet) {
index.remove(this, removed)
}
}
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<KotlinScriptEntity> {
val modifiable = KotlinScriptEntityImpl.Builder(null)
modifiable.diff = diff
modifiable.id = createEntityId()
return modifiable
override fun updateLink(oldLink: SymbolicEntityId<*>, newLink: SymbolicEntityId<*>): Boolean {
var changed = false
val dependencies_data = dependencies.map {
val it_data = if (it == oldLink) {
changed = true
newLink as KotlinScriptLibraryId
}
else {
null
}
if (it_data != null) {
it_data
}
else {
it
}
}
@OptIn(EntityStorageInstrumentationApi::class)
override fun createEntity(snapshot: EntityStorageInstrumentation): KotlinScriptEntity {
val entityId = createEntityId()
return snapshot.initializeEntity(entityId) {
val entity = KotlinScriptEntityImpl(this)
entity.snapshot = snapshot
entity.id = entityId
entity
}
if (dependencies_data != null) {
dependencies = dependencies_data as MutableSet<KotlinScriptLibraryId>
}
return changed
}
override fun getMetadata(): EntityMetadata {
return MetadataStorageImpl.getMetadataByTypeFqn("org.jetbrains.kotlin.idea.core.script.ucache.KotlinScriptEntity") as EntityMetadata
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<KotlinScriptEntity> {
val modifiable = KotlinScriptEntityImpl.Builder(null)
modifiable.diff = diff
modifiable.id = createEntityId()
return modifiable
}
@OptIn(EntityStorageInstrumentationApi::class)
override fun createEntity(snapshot: EntityStorageInstrumentation): KotlinScriptEntity {
val entityId = createEntityId()
return snapshot.initializeEntity(entityId) {
val entity = KotlinScriptEntityImpl(this)
entity.snapshot = snapshot
entity.id = entityId
entity
}
}
override fun clone(): KotlinScriptEntityData {
val clonedEntity = super.clone()
clonedEntity as KotlinScriptEntityData
clonedEntity.dependencies = clonedEntity.dependencies.toMutableWorkspaceSet()
return clonedEntity
override fun getMetadata(): EntityMetadata {
return MetadataStorageImpl.getMetadataByTypeFqn("org.jetbrains.kotlin.idea.core.script.ucache.KotlinScriptEntity") as EntityMetadata
}
override fun clone(): KotlinScriptEntityData {
val clonedEntity = super.clone()
clonedEntity as KotlinScriptEntityData
clonedEntity.dependencies = clonedEntity.dependencies.toMutableWorkspaceSet()
return clonedEntity
}
override fun getEntityInterface(): Class<out WorkspaceEntity> {
return KotlinScriptEntity::class.java
}
override fun createDetachedEntity(parents: List<WorkspaceEntity.Builder<*>>): WorkspaceEntity.Builder<*> {
return KotlinScriptEntity(path, dependencies, entitySource) {
}
}
override fun getEntityInterface(): Class<out WorkspaceEntity> {
return KotlinScriptEntity::class.java
}
override fun getRequiredParents(): List<Class<out WorkspaceEntity>> {
val res = mutableListOf<Class<out WorkspaceEntity>>()
return res
}
override fun createDetachedEntity(parents: List<WorkspaceEntity.Builder<*>>): WorkspaceEntity.Builder<*> {
return KotlinScriptEntity(path, dependencies, entitySource) {
}
}
override fun equals(other: Any?): Boolean {
if (other == null) return false
if (this.javaClass != other.javaClass) return false
override fun getRequiredParents(): List<Class<out WorkspaceEntity>> {
val res = mutableListOf<Class<out WorkspaceEntity>>()
return res
}
other as KotlinScriptEntityData
override fun equals(other: Any?): Boolean {
if (other == null) return false
if (this.javaClass != other.javaClass) return false
if (this.entitySource != other.entitySource) return false
if (this.path != other.path) return false
if (this.dependencies != other.dependencies) return false
return true
}
other as KotlinScriptEntityData
override fun equalsIgnoringEntitySource(other: Any?): Boolean {
if (other == null) return false
if (this.javaClass != other.javaClass) return false
if (this.entitySource != other.entitySource) return false
if (this.path != other.path) return false
if (this.dependencies != other.dependencies) return false
return true
}
other as KotlinScriptEntityData
override fun equalsIgnoringEntitySource(other: Any?): Boolean {
if (other == null) return false
if (this.javaClass != other.javaClass) return false
if (this.path != other.path) return false
if (this.dependencies != other.dependencies) return false
return true
}
other as KotlinScriptEntityData
override fun hashCode(): Int {
var result = entitySource.hashCode()
result = 31 * result + path.hashCode()
result = 31 * result + dependencies.hashCode()
return result
}
if (this.path != other.path) return false
if (this.dependencies != other.dependencies) return false
return true
}
override fun hashCode(): Int {
var result = entitySource.hashCode()
result = 31 * result + path.hashCode()
result = 31 * result + dependencies.hashCode()
return result
}
override fun hashCodeIgnoringEntitySource(): Int {
var result = javaClass.hashCode()
result = 31 * result + path.hashCode()
result = 31 * result + dependencies.hashCode()
return result
}
override fun hashCodeIgnoringEntitySource(): Int {
var result = javaClass.hashCode()
result = 31 * result + path.hashCode()
result = 31 * result + dependencies.hashCode()
return result
}
}

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.core.script.ucache
import com.intellij.platform.workspace.storage.*
import com.intellij.platform.workspace.storage.EntitySource
import com.intellij.platform.workspace.storage.EntityType
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
@@ -8,7 +9,6 @@ import com.intellij.platform.workspace.storage.GeneratedCodeImplVersion
import com.intellij.platform.workspace.storage.MutableEntityStorage
import com.intellij.platform.workspace.storage.SymbolicEntityId
import com.intellij.platform.workspace.storage.WorkspaceEntity
import com.intellij.platform.workspace.storage.WorkspaceEntityWithSymbolicId
import com.intellij.platform.workspace.storage.impl.ConnectionId
import com.intellij.platform.workspace.storage.impl.ModifiableWorkspaceEntityBase
import com.intellij.platform.workspace.storage.impl.SoftLinkable
@@ -24,9 +24,6 @@ import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInst
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
import java.io.Serializable
import kotlin.jvm.JvmName
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmStatic
@GeneratedCodeApiVersion(3)
@GeneratedCodeImplVersion(5)

View File

@@ -14,4 +14,7 @@ text.loading.kotlin.script.configuration=Loading script configuration
notification.text.there.is.a.new.script.context.available=There is a new script context available.
notification.action.text.apply.context=Apply context
notification.action.text.enable.auto.reload=Enable auto-reload
scripting.support.availability.name=Kotlin scripting
scripting.support.availability.name=Kotlin scripting
action.LoadMainKtsConfiguration.text=Refresh Script
action.LoadMainKtsConfiguration.description=Load script dependencies and re-highlight

View File

@@ -7,18 +7,13 @@ import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.scripting.definitions.LazyScriptDefinitionProvider
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
import java.util.concurrent.atomic.AtomicReference
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.SourceCode
import kotlin.script.experimental.api.filePathPattern
import kotlin.script.experimental.api.with
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
/**
* Holds uploaded cache definitions.
* Returns default definition if update did not happen.
* Force-wrap legacy definitions into `ScriptDefinition.FromConfigurations` when updating.
*/
class K2ScriptDefinitionProvider(val project: Project) : LazyScriptDefinitionProvider() {
private val _definitions: AtomicReference<List<ScriptDefinition>> = AtomicReference()
@@ -26,31 +21,8 @@ class K2ScriptDefinitionProvider(val project: Project) : LazyScriptDefinitionPro
public override val currentDefinitions: Sequence<ScriptDefinition>
get() = _definitions.get()?.takeIf { it.isNotEmpty() }?.asSequence() ?: sequenceOf(getDefaultDefinition())
fun updateDefinitions(templateDefinitions: List<ScriptDefinition>) {
val definitionsFromConfigurations = templateDefinitions.map { definition ->
val configuration = definition.compilationConfiguration.with {
definition.asLegacyOrNull<KotlinScriptDefinitionFromAnnotatedTemplate>()?.let {
// remove when fix pattern processing on compiler side
filePathPattern(it.scriptFilePattern.pattern)
}
}
object : ScriptDefinition.FromConfigurations(
definition.hostConfiguration,
configuration,
definition.evaluationConfiguration,
definition.defaultCompilerOptions
) {
// remove when fix pattern processing on compiler side
override fun isScript(script: SourceCode): Boolean {
val extension = ".$fileExtension"
val location = script.locationId ?: return false
val name = script.name ?: location
return name.endsWith(extension) && filePathPattern?.let { Regex(it).matches(name) } != false
}
}
}
_definitions.set(definitionsFromConfigurations)
fun reloadDefinitions() {
_definitions.set(SCRIPT_DEFINITIONS_SOURCES.getExtensions(project).flatMap { it.definitions })
clearCache()
}

View File

@@ -13,6 +13,7 @@ import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.NonClasspathDirectoriesScope.compose
import org.jetbrains.kotlin.idea.base.util.runReadActionInSmartMode
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager.Companion.toVfsRoots
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
@@ -102,6 +103,19 @@ class K2ScriptDependenciesProvider(project: Project) : ScriptDependenciesProvide
private val configurationsByFile = ConcurrentHashMap<VirtualFile, ResultWithDiagnostics<ScriptCompilationConfigurationWrapper>>()
fun addConfiguration(script: SourceCode): ScriptCompilationConfigurationResult {
val definition = findScriptDefinition(project, script)
val virtualFile = script.getVirtualFile(definition)
val configuration = project.runReadActionInSmartMode {
refineScriptCompilationConfiguration(script, definition, project, definition.compilationConfiguration)
}
configurationsByFile[virtualFile] = configuration
return configuration
}
fun reloadConfigurations(scripts: Set<ScriptModel>, javaHome: String?) {
val classes = mutableSetOf<VirtualFile>()
val sources = mutableSetOf<VirtualFile>()
@@ -115,15 +129,14 @@ class K2ScriptDependenciesProvider(project: Project) : ScriptDependenciesProvide
val sourceCode = VirtualFileScriptSource(script.virtualFile)
val definition = findScriptDefinition(project, sourceCode)
val configuration = configurationsByFile[script.virtualFile]?.valueOrNull()?.configuration
?: definition.compilationConfiguration.with {
javaHome?.let {
jvm.jdkHome(Path.of(javaHome).toFile())
}
defaultImports(script.imports)
dependencies(JvmDependency(script.classPath.map { File(it) }))
ide.dependenciesSources(JvmDependency(script.sourcePath.map { File(it) }))
}.adjustByDefinition(definition)
val configuration = definition.compilationConfiguration.with {
javaHome?.let {
jvm.jdkHome(Path.of(javaHome).toFile())
}
defaultImports(script.imports)
dependencies(JvmDependency(script.classPath.map { File(it) }))
ide.dependenciesSources(JvmDependency(script.sourcePath.map { File(it) }))
}.adjustByDefinition(definition)
val updatedConfiguration = refineScriptCompilationConfiguration(sourceCode, definition, project, configuration)
configurationsByFile[script.virtualFile] = updatedConfiguration

View File

@@ -62,8 +62,6 @@ internal class IdeScriptDependenciesProvider(project: Project) : ScriptDependenc
* of opened files when configuration will be loaded or updated.
*/
interface ScriptConfigurationManager : ScriptDependencyAware {
fun loadPlugins()
/**
* Get cached configuration for [file] or load it.
* May return null even configuration was loaded but was not yet applied.

View File

@@ -35,7 +35,7 @@ internal class ScriptTrafficLightRendererContributor : TrafficLightRendererContr
if (scriptingEnabled) {
if (KotlinPluginModeProvider.isK2Mode()) {
if (K2ScriptDependenciesProvider.getInstanceIfCreated(project)?.getConfiguration(file.virtualFile) == null) {
if (K2ScriptDependenciesProvider.getInstanceIfCreated(project)?.getScriptConfiguration(file) == null) {
status.reasonWhySuspended = KotlinBaseScriptingBundle.message("text.loading.kotlin.script.configuration")
status.errorAnalyzingFinished = false
}

View File

@@ -68,10 +68,6 @@ class CompositeScriptConfigurationManager(val project: Project, val scope: Corou
}
}
override fun loadPlugins() {
plugins
}
fun updateScriptDependenciesIfNeeded(file: VirtualFile) {
notifier.updateScriptDependenciesIfNeeded(file)
}

View File

@@ -161,7 +161,7 @@ class KotlinScriptResolveScopeProvider : ResolveScopeProvider() {
private fun KtFile.calculateScopeForStandaloneScript(file: VirtualFile, project: Project): KotlinScriptSearchScope {
val vFile = virtualFile ?: viewProvider.virtualFile
val dependenciesScope =
ScriptDependencyAware.getInstance(project).getScriptDependenciesClassFilesScope(vFile) ?: GlobalSearchScope.EMPTY_SCOPE
ScriptDependencyAware.getInstance(project).getScriptDependenciesClassFilesScope(vFile)
debugLog { "=> standalone" }
return KotlinScriptSearchScope(project, GlobalSearchScope.fileScope(project, file).uniteWith(dependenciesScope))
}

View File

@@ -17,11 +17,9 @@ abstract class ScriptAdditionalIdeaDependenciesProvider {
ExtensionPointName.create("org.jetbrains.kotlin.scriptAdditionalIdeaDependenciesProvider")
fun getRelatedModules(file: VirtualFile, project: Project): List<Module> = EP_NAME.getExtensionList(project)
.filterIsInstance<ScriptAdditionalIdeaDependenciesProvider>()
.flatMap { it.getRelatedModules(file, project) }
fun getRelatedLibraries(file: VirtualFile, project: Project): List<Library> = EP_NAME.getExtensionList(project)
.filterIsInstance<ScriptAdditionalIdeaDependenciesProvider>()
.flatMap { it.getRelatedLibraries(file, project) }
}
}

View File

@@ -30,7 +30,7 @@ class ScriptDependenciesResolveScopeProvider : ResolveScopeProvider() {
if (RootKindMatcher.matches(project, file, RootKindFilter.libraryFiles.copy(includeScriptDependencies = false)))
return null
if ((ScriptDependencyAware.getInstance(project).getAllScriptsDependenciesClassFiles() ?: emptyList()).isEmpty()) return null
if (ScriptDependencyAware.getInstance(project).getAllScriptsDependenciesClassFiles().isEmpty()) return null
if (file !in ScriptDependencyAware.getInstance(project).getAllScriptsDependenciesClassFilesScope()
&& file !in ScriptDependencyAware.getInstance(project).getAllScriptDependenciesSourcesScope()) {

View File

@@ -42,7 +42,7 @@ class ScriptDependencySourceNavigationPolicyForJavaClasses : ClsCustomNavigation
val packageName = file.packageName
val relativePath = if (packageName.isEmpty()) sourceFileName else packageName.replace('.', '/') + '/' + sourceFileName
for (root in (ScriptDependencyAware.getInstance(project).getAllScriptDependenciesSources() ?: emptyList()).filter { it.isValid }) {
for (root in ScriptDependencyAware.getInstance(project).getAllScriptDependenciesSources().filter { it.isValid }) {
val sourceFile = root.findFileByRelativePath(relativePath)
if (sourceFile != null && sourceFile.isValid) {
val sourcePsi = file.manager.findFile(sourceFile)

View File

@@ -10,6 +10,7 @@ import com.intellij.platform.backend.workspace.toVirtualFileUrl
import com.intellij.platform.workspace.jps.entities.*
import com.intellij.platform.workspace.storage.EntitySource
import com.intellij.platform.workspace.storage.MutableEntityStorage
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager.Companion.toVfsRoots
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
import java.nio.file.Path
@@ -18,7 +19,7 @@ import kotlin.time.measureTime
const val KOTLIN_SCRIPTS_MODULE_NAME = "Kotlin Scripts"
object KotlinK2ScriptEntitySource : EntitySource
data class KotlinScriptEntitySourceK2(override val virtualFileUrl: VirtualFileUrl) : EntitySource
suspend fun Project.createScriptModules(scripts: Set<ScriptModel>) {
val duration = measureTime { createPureScriptModules(scripts, this) }
@@ -29,6 +30,7 @@ suspend fun Project.createScriptModules(scripts: Set<ScriptModel>) {
private suspend fun createPureScriptModules(scriptPaths: Set<ScriptModel>, project: Project) {
val projectPath = project.basePath?.let { Path.of(it) } ?: return
val sourcesToUpdate = mutableSetOf<KotlinScriptEntitySourceK2>()
val updatedStorage = MutableEntityStorage.create()
for (scriptFile in scriptPaths.map { it.virtualFile }) {
@@ -40,8 +42,7 @@ private suspend fun createPureScriptModules(scriptPaths: Set<ScriptModel>, proje
val file = Path.of(scriptFile.path).toFile()
val relativeLocation = FileUtil.getRelativePath(basePath, file) ?: continue
val definition =
K2ScriptDefinitionProvider.getInstance(project).findDefinition(VirtualFileScriptSource(scriptFile))
val definition = K2ScriptDefinitionProvider.getInstance(project).findDefinition(VirtualFileScriptSource(scriptFile))
val definitionName = definition?.name ?: continue
@@ -49,13 +50,15 @@ private suspend fun createPureScriptModules(scriptPaths: Set<ScriptModel>, proje
val locationName = relativeLocation.replace(VfsUtilCore.VFS_SEPARATOR_CHAR, ':')
val moduleName = "$definitionScriptModuleName.$locationName"
val dependencies = updatedStorage.createDependencies(moduleName, scriptFile, project)
val source = KotlinScriptEntitySourceK2(scriptFile.toVirtualFileUrl(WorkspaceModel.getInstance(project).getVirtualFileUrlManager()))
sourcesToUpdate += source
val dependencies = updatedStorage.createDependencies(moduleName, scriptFile, project, source)
updatedStorage.addEntity(ModuleEntity(moduleName, dependencies, KotlinK2ScriptEntitySource))
updatedStorage.addEntity(ModuleEntity(moduleName, dependencies, source))
}
WorkspaceModel.getInstance(project).update("Updating kotlin scripts modules") {
it.replaceBySource({ entitySource -> entitySource is KotlinK2ScriptEntitySource }, updatedStorage)
it.replaceBySource({ entitySource -> entitySource in sourcesToUpdate }, updatedStorage)
}
}
@@ -84,7 +87,8 @@ private fun getDependenciesFiles(scriptFile: VirtualFile, project: Project): Dep
fun MutableEntityStorage.createDependencies(
moduleName: String,
scriptFile: VirtualFile,
project: Project
project: Project,
entitySource: EntitySource
): List<ModuleDependencyItem> {
val (dependenciesClassFiles, dependenciesSourceFiles, sdk) = getDependenciesFiles(scriptFile, project)
@@ -100,7 +104,7 @@ fun MutableEntityStorage.createDependencies(
val libraryTableId = LibraryTableId.ModuleLibraryTableId(moduleId = ModuleId(moduleName))
val dependencyLibrary =
addEntity(LibraryEntity("$moduleName dependencies", libraryTableId, classRoots + sourceRoots, KotlinK2ScriptEntitySource))
addEntity(LibraryEntity("$moduleName dependencies", libraryTableId, classRoots + sourceRoots, entitySource))
return listOfNotNull(LibraryDependency(dependencyLibrary.symbolicId, false, DependencyScope.COMPILE), sdk)
}

View File

@@ -5,6 +5,7 @@ package org.jetbrains.kotlin.idea.core.script
import com.intellij.openapi.application.Application
import com.intellij.openapi.application.writeAction
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.extensions.ProjectExtensionPointName
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.waitForSmartMode
import com.intellij.openapi.util.Key
@@ -17,8 +18,12 @@ import org.jetbrains.kotlin.idea.core.script.configuration.cache.ScriptConfigura
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsSource
import kotlin.script.experimental.api.ScriptDiagnostic
val SCRIPT_DEFINITIONS_SOURCES: ProjectExtensionPointName<ScriptDefinitionsSource> =
ProjectExtensionPointName("org.jetbrains.kotlin.scriptDefinitionsSource")
@set: org.jetbrains.annotations.TestOnly
var Application.isScriptChangesNotifierDisabled by NotNullableUserDataProperty(
Key.create("SCRIPT_CHANGES_NOTIFIER_DISABLED"),
@@ -79,9 +84,7 @@ suspend fun configureGradleScriptsK2(
javaHome: String?,
project: Project,
scripts: Set<ScriptModel>,
definitions: List<ScriptDefinition>,
) {
K2ScriptDefinitionProvider.getInstance(project).updateDefinitions(definitions)
K2ScriptDependenciesProvider.getInstance(project).reloadConfigurations(scripts, javaHome)
project.createScriptModules(scripts)
@@ -92,4 +95,4 @@ suspend fun configureGradleScriptsK2(
}
}
val scriptingEnabled = Registry.`is`("kotlin.k2.scripting.enabled", false)
val scriptingEnabled = Registry.`is`("kotlin.k2.scripting.enabled", false)

View File

@@ -2,11 +2,6 @@
package org.jetbrains.kotlin.idea.core.script.ucache
import com.intellij.platform.workspace.storage.*
import com.intellij.platform.workspace.storage.EntitySource
import com.intellij.platform.workspace.storage.EntityType
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
import com.intellij.platform.workspace.storage.MutableEntityStorage
import com.intellij.platform.workspace.storage.WorkspaceEntity
import com.intellij.platform.workspace.storage.impl.containers.toMutableWorkspaceSet
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
@@ -21,42 +16,42 @@ interface KotlinScriptEntity : WorkspaceEntityWithSymbolicId {
override val symbolicId: KotlinScriptId
get() = KotlinScriptId(path)
//region generated code
@GeneratedCodeApiVersion(3)
interface Builder : WorkspaceEntity.Builder<KotlinScriptEntity> {
override var entitySource: EntitySource
var path: String
var dependencies: MutableSet<KotlinScriptLibraryId>
}
//region generated code
@GeneratedCodeApiVersion(3)
interface Builder : WorkspaceEntity.Builder<KotlinScriptEntity> {
override var entitySource: EntitySource
var path: String
var dependencies: MutableSet<KotlinScriptLibraryId>
}
companion object : EntityType<KotlinScriptEntity, Builder>() {
@JvmOverloads
@JvmStatic
@JvmName("create")
operator fun invoke(
path: String,
dependencies: Set<KotlinScriptLibraryId>,
entitySource: EntitySource,
init: (Builder.() -> Unit)? = null,
): Builder {
val builder = builder()
builder.path = path
builder.dependencies = dependencies.toMutableWorkspaceSet()
builder.entitySource = entitySource
init?.invoke(builder)
return builder
}
companion object : EntityType<KotlinScriptEntity, Builder>() {
@JvmOverloads
@JvmStatic
@JvmName("create")
operator fun invoke(
path: String,
dependencies: Set<KotlinScriptLibraryId>,
entitySource: EntitySource,
init: (Builder.() -> Unit)? = null,
): Builder {
val builder = builder()
builder.path = path
builder.dependencies = dependencies.toMutableWorkspaceSet()
builder.entitySource = entitySource
init?.invoke(builder)
return builder
}
//endregion
}
//endregion
}
//region generated code
fun MutableEntityStorage.modifyKotlinScriptEntity(
entity: KotlinScriptEntity,
modification: KotlinScriptEntity.Builder.() -> Unit,
entity: KotlinScriptEntity,
modification: KotlinScriptEntity.Builder.() -> Unit,
): KotlinScriptEntity {
return modifyEntity(KotlinScriptEntity.Builder::class.java, entity, modification)
return modifyEntity(KotlinScriptEntity.Builder::class.java, entity, modification)
}
//endregion

View File

@@ -2,11 +2,6 @@
package org.jetbrains.kotlin.idea.core.script.ucache
import com.intellij.platform.workspace.storage.*
import com.intellij.platform.workspace.storage.EntitySource
import com.intellij.platform.workspace.storage.EntityType
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
import com.intellij.platform.workspace.storage.MutableEntityStorage
import com.intellij.platform.workspace.storage.WorkspaceEntity
import com.intellij.platform.workspace.storage.impl.containers.toMutableWorkspaceList
import com.intellij.platform.workspace.storage.impl.containers.toMutableWorkspaceSet
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
@@ -43,46 +38,46 @@ interface KotlinScriptLibraryEntity : WorkspaceEntityWithSymbolicId {
override val symbolicId: KotlinScriptLibraryId
get() = KotlinScriptLibraryId(name)
//region generated code
@GeneratedCodeApiVersion(3)
interface Builder : WorkspaceEntity.Builder<KotlinScriptLibraryEntity> {
override var entitySource: EntitySource
var name: String
var roots: MutableList<KotlinScriptLibraryRoot>
var indexSourceRoots: Boolean
var usedInScripts: MutableSet<KotlinScriptId>
}
//region generated code
@GeneratedCodeApiVersion(3)
interface Builder : WorkspaceEntity.Builder<KotlinScriptLibraryEntity> {
override var entitySource: EntitySource
var name: String
var roots: MutableList<KotlinScriptLibraryRoot>
var indexSourceRoots: Boolean
var usedInScripts: MutableSet<KotlinScriptId>
}
companion object : EntityType<KotlinScriptLibraryEntity, Builder>() {
@JvmOverloads
@JvmStatic
@JvmName("create")
operator fun invoke(
name: String,
roots: List<KotlinScriptLibraryRoot>,
indexSourceRoots: Boolean,
usedInScripts: Set<KotlinScriptId>,
entitySource: EntitySource,
init: (Builder.() -> Unit)? = null,
): Builder {
val builder = builder()
builder.name = name
builder.roots = roots.toMutableWorkspaceList()
builder.indexSourceRoots = indexSourceRoots
builder.usedInScripts = usedInScripts.toMutableWorkspaceSet()
builder.entitySource = entitySource
init?.invoke(builder)
return builder
}
companion object : EntityType<KotlinScriptLibraryEntity, Builder>() {
@JvmOverloads
@JvmStatic
@JvmName("create")
operator fun invoke(
name: String,
roots: List<KotlinScriptLibraryRoot>,
indexSourceRoots: Boolean,
usedInScripts: Set<KotlinScriptId>,
entitySource: EntitySource,
init: (Builder.() -> Unit)? = null,
): Builder {
val builder = builder()
builder.name = name
builder.roots = roots.toMutableWorkspaceList()
builder.indexSourceRoots = indexSourceRoots
builder.usedInScripts = usedInScripts.toMutableWorkspaceSet()
builder.entitySource = entitySource
init?.invoke(builder)
return builder
}
//endregion
}
//endregion
}
//region generated code
fun MutableEntityStorage.modifyKotlinScriptLibraryEntity(
entity: KotlinScriptLibraryEntity,
modification: KotlinScriptLibraryEntity.Builder.() -> Unit,
entity: KotlinScriptLibraryEntity,
modification: KotlinScriptLibraryEntity.Builder.() -> Unit,
): KotlinScriptLibraryEntity {
return modifyEntity(KotlinScriptLibraryEntity.Builder::class.java, entity, modification)
return modifyEntity(KotlinScriptLibraryEntity.Builder::class.java, entity, modification)
}
//endregion

View File

@@ -12,14 +12,14 @@ object MetadataStorageImpl: MetadataStorageBase() {
var typeMetadata: StorageTypeMetadata
typeMetadata = FinalClassMetadata.ObjectMetadata(fqName = "org.jetbrains.kotlin.idea.core.script.KotlinK2ScriptEntitySource", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "virtualFileUrl", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = true, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.url.VirtualFileUrl")), withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.EntitySource"))
typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "org.jetbrains.kotlin.idea.core.script.KotlinScriptEntitySourceK2", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "virtualFileUrl", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.url.VirtualFileUrl")), withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.EntitySource"))
addMetadata(typeMetadata)
}
override fun initializeMetadataHash() {
addMetadataHash(typeFqn = "com.intellij.platform.workspace.storage.EntitySource", metadataHash = -216432311)
addMetadataHash(typeFqn = "org.jetbrains.kotlin.idea.core.script.KotlinK2ScriptEntitySource", metadataHash = 782346369)
addMetadataHash(typeFqn = "com.intellij.platform.workspace.storage.EntitySource", metadataHash = -771969063)
addMetadataHash(typeFqn = "org.jetbrains.kotlin.idea.core.script.KotlinScriptEntitySourceK2", metadataHash = -860768271)
}
}

View File

@@ -110,6 +110,8 @@
<scriptDefinitionContributor implementation="org.jetbrains.kotlin.idea.gradleJava.scripting.GradleScriptDefinitionsContributor" order="first"/>
<scriptDefinitionsSource implementation="org.jetbrains.kotlin.idea.gradleJava.scripting.GradleScriptDefinitionsSource"/>
<scriptAdditionalIdeaDependenciesProvider implementation="org.jetbrains.kotlin.idea.gradleJava.scripting.GradleScriptAdditionalIdeaDependenciesProvider"/>
<experimentalFeature implementation="org.jetbrains.kotlin.idea.gradleJava.scripting.GradleScriptConfigurationsImportingFeature"/>

View File

@@ -0,0 +1,50 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.gradleJava.scripting
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.core.script.K2ScriptDefinitionProvider
import org.jetbrains.kotlin.idea.core.script.SCRIPT_DEFINITIONS_SOURCES
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsSource
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.util.concurrent.atomic.AtomicReference
import kotlin.script.experimental.api.fileNamePattern
import kotlin.script.experimental.api.with
class GradleScriptDefinitionsSource(val project: Project) : ScriptDefinitionsSource {
private val _definitions: AtomicReference<List<ScriptDefinition>> = AtomicReference(listOf())
override val definitions: Sequence<ScriptDefinition>
get() = _definitions.get().asSequence()
/**
* Force-wrap legacy definitions into `ScriptDefinition.FromConfigurations` when updating.
*/
fun updateDefinitions(templateDefinitions: List<ScriptDefinition>) {
val definitionsFromConfigurations = templateDefinitions.map { definition ->
val configuration = definition.compilationConfiguration.with {
definition.asLegacyOrNull<KotlinScriptDefinitionFromAnnotatedTemplate>()?.let {
@Suppress("DEPRECATION_ERROR")
fileNamePattern(it.scriptFilePattern.pattern)
}
}
ScriptDefinition.FromConfigurations(
definition.hostConfiguration,
configuration,
definition.evaluationConfiguration,
definition.defaultCompilerOptions
)
}
_definitions.set(definitionsFromConfigurations)
K2ScriptDefinitionProvider.getInstance(project).reloadDefinitions()
}
companion object {
fun getInstance(project: Project): GradleScriptDefinitionsSource? =
SCRIPT_DEFINITIONS_SOURCES.getExtensions(project)
.filterIsInstance<GradleScriptDefinitionsSource>().firstOrNull()
.safeAs<GradleScriptDefinitionsSource>()
}
}

View File

@@ -62,7 +62,6 @@ internal class GradleScriptNotificationProvider : EditorNotificationProvider {
}
return Function { fileEditor ->
//if (k2ScriptingEnabled() && K2ScriptDependenciesProvider.getInstanceIfCreated(project)?.getConfiguration(file) != null) { return@Function null }
when (scriptUnderRoot.notificationKind) {
dontCare -> null
legacy -> {

View File

@@ -37,6 +37,7 @@ class ProjectGradleSettingsListener(val project: Project, private val cs: Corout
if (newRoot is Imported && KotlinPluginModeProvider.isK2Mode()) {
val definitions = loadGradleDefinitions(it.externalProjectPath, newRoot.data.gradleHome, newRoot.data.javaHome, project)
GradleScriptDefinitionsSource.getInstance(project)?.updateDefinitions(definitions)
val scripts = newRoot.data.models.mapNotNull {
val path = Paths.get(it.file)
@@ -50,7 +51,7 @@ class ProjectGradleSettingsListener(val project: Project, private val cs: Corout
}
}.toSet()
configureGradleScriptsK2(newRoot.data.javaHome, project, scripts, definitions)
configureGradleScriptsK2(newRoot.data.javaHome, project, scripts)
}
}
}

View File

@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.idea.core.script.ScriptModel
import org.jetbrains.kotlin.idea.core.script.configureGradleScriptsK2
import org.jetbrains.kotlin.idea.gradleJava.loadGradleDefinitions
import org.jetbrains.kotlin.idea.gradleJava.scripting.GradleScriptDefinitionsContributor
import org.jetbrains.kotlin.idea.gradleJava.scripting.GradleScriptDefinitionsSource
import org.jetbrains.kotlin.idea.gradleJava.scripting.roots.GradleBuildRootsManager
import org.jetbrains.plugins.gradle.service.GradleInstallationManager
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings
@@ -80,6 +81,7 @@ class KotlinDslSyncListener(val coroutineScope: CoroutineScope) : ExternalSystem
if (KotlinPluginModeProvider.isK2Mode()) {
val definitions = loadGradleDefinitions(sync.workingDir, sync.gradleHome, sync.javaHome, project)
GradleScriptDefinitionsSource.getInstance(project)?.updateDefinitions(definitions)
val scripts = sync.models.mapNotNull {
val path = Path.of(it.file)
@@ -87,7 +89,7 @@ class KotlinDslSyncListener(val coroutineScope: CoroutineScope) : ExternalSystem
ScriptModel(virtualFile, it.classPath, it.sourcePath, it.imports)
}
}.toSet()
coroutineScope.launch { configureGradleScriptsK2(sync.javaHome, project, scripts, definitions) }
coroutineScope.launch { configureGradleScriptsK2(sync.javaHome, project, scripts) }
} else {
@Suppress("DEPRECATION")
ScriptDefinitionContributor.find<GradleScriptDefinitionsContributor>(project)?.reloadIfNeeded(

View File

@@ -127,5 +127,6 @@
<orderEntry type="module" module-name="kotlin.base.analysis-api.utils" />
<orderEntry type="module" module-name="kotlin.code-insight.inspections.shared" />
<orderEntry type="module" module-name="kotlin.ide" />
<orderEntry type="library" name="kotlinc.analysis-api-providers" level="project" />
</component>
</module>

View File

@@ -6,7 +6,7 @@ import org.jetbrains.kotlin.idea.base.plugin.artifacts.KotlinArtifacts
import java.io.File
import kotlin.script.experimental.intellij.ScriptDefinitionsProvider
class MainKtsScriptDefinitionSource : ScriptDefinitionsProvider {
class MainKtsScriptDefinitionProvider : ScriptDefinitionsProvider {
override val id: String = ".main.kts script"
override fun getDefinitionClasses(): Iterable<String> = emptyList()

View File

@@ -0,0 +1,41 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.script
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.base.plugin.artifacts.KotlinArtifacts
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsSource
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.ScriptEvaluationConfiguration
import kotlin.script.experimental.api.hostConfiguration
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
class MainKtsScriptDefinitionSourceK2(val project: Project) : ScriptDefinitionsSource {
override val definitions: Sequence<ScriptDefinition>
get() {
val baseHostConfiguration = defaultJvmScriptingHostConfiguration
val classPath = listOf(
KotlinArtifacts.kotlinMainKts,
KotlinArtifacts.kotlinScriptRuntime,
KotlinArtifacts.kotlinStdlib,
KotlinArtifacts.kotlinReflect
)
val discoveredDefinitions = ScriptDefinitionsFromClasspathDiscoverySource(
classPath,
baseHostConfiguration,
::loggingReporter
).definitions
return discoveredDefinitions.map {
ScriptDefinition.FromConfigurations(
it.compilationConfiguration[ScriptCompilationConfiguration.hostConfiguration]
?: baseHostConfiguration,
it.compilationConfiguration,
it.evaluationConfiguration ?: ScriptEvaluationConfiguration.Default
)
}
}
}

View File

@@ -0,0 +1,86 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.script
import com.intellij.diff.util.DiffUtil
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.application.writeAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.LightVirtualFileBase
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.jetbrains.kotlin.analysis.providers.analysisMessageBus
import org.jetbrains.kotlin.analysis.providers.topics.KotlinTopics
import org.jetbrains.kotlin.idea.core.script.K2ScriptDependenciesProvider
import org.jetbrains.kotlin.idea.core.script.ScriptModel
import org.jetbrains.kotlin.idea.core.script.createScriptModules
import org.jetbrains.kotlin.idea.util.isKotlinFileType
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
import java.util.concurrent.ConcurrentHashMap
import kotlin.script.experimental.api.valueOrNull
internal class RefreshMainKtsScriptAction : AnAction() {
private val lastModifiedPerScript = ConcurrentHashMap<VirtualFile, Long>()
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
val editor = e.getData(CommonDataKeys.EDITOR) ?: return
val file = getKotlinScriptFile(editor) ?: return
val configurationResult = K2ScriptDependenciesProvider.getInstance(project)
.addConfiguration(VirtualFileScriptSource(file))
val configuration = configurationResult.valueOrNull()
val model =
ScriptModel(file, configuration?.dependenciesClassPath?.map { it.absolutePath } ?: emptyList())
GlobalScope.launch {
project.createScriptModules(setOf(model))
writeAction {
project.analysisMessageBus.syncPublisher(KotlinTopics.GLOBAL_MODULE_STATE_MODIFICATION).onModification()
}
}
lastModifiedPerScript[file] = file.modificationStamp
}
override fun getActionUpdateThread() = ActionUpdateThread.BGT
override fun update(e: AnActionEvent) {
val editor = e.getData(CommonDataKeys.EDITOR) ?: return
e.presentation.isEnabledAndVisible = getNotificationVisibility(editor)
}
private fun getNotificationVisibility(editor: Editor): Boolean {
if (DiffUtil.isDiffEditor(editor)) return false
val project = editor.project ?: return false
if (ScriptDefinitionProvider.getServiceIfCreated(project) == null) return false
val file = getKotlinScriptFile(editor) ?: return false
val oldValue = lastModifiedPerScript[file]
return oldValue == null || oldValue < file.modificationStamp
}
}
private fun getKotlinScriptFile(editor: Editor): VirtualFile? = FileDocumentManager.getInstance()
.getFile(editor.document)
?.takeIf {
it !is LightVirtualFileBase
&& it.isValid
&& it.isKotlinFileType()
&& isMainKtsScript(it)
}
private fun isMainKtsScript(virtualFile: VirtualFile) = virtualFile.name.endsWith(".main.kts")

View File

@@ -1,5 +1,11 @@
<idea-plugin>
<extensionPoints>
<extensionPoint
qualifiedName="org.jetbrains.kotlin.scriptDefinitionsSource"
interface="org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsSource"
area="IDEA_PROJECT"
dynamic="true"/>
<extensionPoint
qualifiedName="org.jetbrains.kotlin.scripting.definitions.scriptDefinitionProvider"
interface="org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider"
@@ -93,5 +99,15 @@
<idea.base.projectStructure.moduleInfoProviderExtension
implementation="org.jetbrains.kotlin.idea.base.scripting.ScriptingModuleInfoProviderExtension"/>
<scriptDefinitionsSource implementation="org.jetbrains.kotlin.idea.script.MainKtsScriptDefinitionSourceK2"/>
</extensions>
<actions resource-bundle="messages.KotlinBaseScriptingBundle">
<action id="LoadMainKtsConfiguration"
class="org.jetbrains.kotlin.idea.script.RefreshMainKtsScriptAction"
icon="org.jetbrains.kotlin.idea.KotlinIcons.LOAD_SCRIPT_CONFIGURATION">
<add-to-group group-id="EditorContextBarMenu"/>
</action>
</actions>
</idea-plugin>

View File

@@ -52,20 +52,8 @@
<scriptDefinitionContributor id="ScriptDefinitionForExtensionAndIdeConsoleRootsSource"
implementation="org.jetbrains.kotlin.jsr223.ScriptDefinitionForExtensionAndIdeConsoleRootsSource"/>
<scriptDefinitionsProvider id="MainKtsScriptDefinitionSource"
implementation="org.jetbrains.kotlin.idea.script.MainKtsScriptDefinitionSource"/>
<scripting.support.checker.provider id="MainKtsScriptCheckerProvider"
implementation="org.jetbrains.kotlin.idea.script.MainKtsScriptCheckerProvider"/>
<scripting.support.checker.provider id="SpaceKtsScriptCheckerProvider"
implementation="org.jetbrains.kotlin.idea.script.SpaceKtsScriptCheckerProvider"/>
<scripting.support.checker.provider id="TeamCityKtsScriptCheckerProvider"
implementation="org.jetbrains.kotlin.idea.script.TeamCityKtsScriptCheckerProvider"/>
<scripting.support.checker.provider id="WorkspaceKtsScriptCheckerProvider"
implementation="org.jetbrains.kotlin.idea.script.WorkspaceKtsScriptCheckerProvider"/>
<scriptDefinitionsProvider id="MainKtsScriptDefinitionProvider"
implementation="org.jetbrains.kotlin.idea.script.MainKtsScriptDefinitionProvider"/>
<ideScriptConfigurationControlFacade implementation="org.jetbrains.kotlin.idea.script.DefaultIdeScriptingConfigurationFacade"/>