feat: Integrate stdlib into workspace model
This commit is contained in:
parent
88df5b1426
commit
16fb4b57b7
3 changed files with 79 additions and 15 deletions
|
@ -19,6 +19,8 @@ Changelog structure reference:
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Zig
|
||||||
|
- Changing the zig standard library path in the project settings now properly updates the dependency
|
||||||
- ZLS
|
- ZLS
|
||||||
- All of the config options are now exposed in the GUI
|
- All of the config options are now exposed in the GUI
|
||||||
|
|
||||||
|
|
|
@ -22,15 +22,18 @@
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.settings
|
package com.falsepattern.zigbrains.project.settings
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.project.toolchain.stdlib.ZigSyntheticLibrary
|
||||||
|
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
||||||
import com.intellij.openapi.components.*
|
import com.intellij.openapi.components.*
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Service(Service.Level.PROJECT)
|
@Service(Service.Level.PROJECT)
|
||||||
@State(
|
@State(
|
||||||
name = "ZigProjectSettings",
|
name = "ZigProjectSettings",
|
||||||
storages = [Storage("zigbrains.xml")]
|
storages = [Storage("zigbrains.xml")]
|
||||||
)
|
)
|
||||||
class ZigProjectSettingsService: PersistentStateComponent<ZigProjectSettings> {
|
class ZigProjectSettingsService(val project: Project): PersistentStateComponent<ZigProjectSettings> {
|
||||||
@Volatile
|
@Volatile
|
||||||
private var state = ZigProjectSettings()
|
private var state = ZigProjectSettings()
|
||||||
|
|
||||||
|
@ -40,10 +43,13 @@ class ZigProjectSettingsService: PersistentStateComponent<ZigProjectSettings> {
|
||||||
|
|
||||||
fun setState(value: ZigProjectSettings) {
|
fun setState(value: ZigProjectSettings) {
|
||||||
this.state = value
|
this.state = value
|
||||||
|
zigCoroutineScope.launch {
|
||||||
|
ZigSyntheticLibrary.reload(project, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadState(state: ZigProjectSettings) {
|
override fun loadState(state: ZigProjectSettings) {
|
||||||
this.state = state
|
setState(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isModified(otherData: ZigProjectSettings): Boolean {
|
fun isModified(otherData: ZigProjectSettings): Boolean {
|
||||||
|
|
|
@ -27,28 +27,34 @@ import com.falsepattern.zigbrains.project.settings.ZigProjectSettings
|
||||||
import com.falsepattern.zigbrains.project.settings.zigProjectSettings
|
import com.falsepattern.zigbrains.project.settings.zigProjectSettings
|
||||||
import com.intellij.navigation.ItemPresentation
|
import com.intellij.navigation.ItemPresentation
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.project.guessProjectDir
|
||||||
import com.intellij.openapi.roots.SyntheticLibrary
|
import com.intellij.openapi.roots.SyntheticLibrary
|
||||||
import com.intellij.openapi.util.io.toNioPathOrNull
|
import com.intellij.openapi.util.io.toNioPathOrNull
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.openapi.vfs.refreshAndFindVirtualDirectory
|
import com.intellij.openapi.vfs.refreshAndFindVirtualDirectory
|
||||||
|
import com.intellij.platform.backend.workspace.WorkspaceModel
|
||||||
|
import com.intellij.platform.backend.workspace.toVirtualFileUrl
|
||||||
|
import com.intellij.platform.workspace.jps.entities.*
|
||||||
|
import com.intellij.workspaceModel.ide.legacyBridge.LegacyBridgeJpsEntitySourceFactory
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.swing.Icon
|
import javax.swing.Icon
|
||||||
|
|
||||||
class ZigSyntheticLibrary(val project: Project) : SyntheticLibrary(), ItemPresentation {
|
class ZigSyntheticLibrary(val project: Project) : SyntheticLibrary(), ItemPresentation {
|
||||||
|
private var state: ZigProjectSettings = project.zigProjectSettings.state.copy()
|
||||||
private val roots by lazy {
|
private val roots by lazy {
|
||||||
getRoots(project.zigProjectSettings.state, project)
|
runBlocking {getRoot(state, project)}?.let { setOf(it) } ?: emptySet()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val name by lazy {
|
private val name by lazy {
|
||||||
getName(project.zigProjectSettings.state, project)
|
getName(state, project)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (other !is ZigSyntheticLibrary)
|
if (other !is ZigSyntheticLibrary)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
return roots == other.roots
|
return state == other.state
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
|
@ -67,9 +73,59 @@ class ZigSyntheticLibrary(val project: Project) : SyntheticLibrary(), ItemPresen
|
||||||
return roots
|
return roots
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ZIG_LIBRARY_ID = "Zig SDK"
|
||||||
|
private const val ZIG_MODULE_ID = "Zig"
|
||||||
|
suspend fun reload(project: Project, state: ZigProjectSettings) {
|
||||||
|
val moduleId = ModuleId(ZIG_MODULE_ID)
|
||||||
|
val workspaceModel = WorkspaceModel.getInstance(project)
|
||||||
|
if (moduleId !in workspaceModel.currentSnapshot) {
|
||||||
|
val baseModuleDir = project.guessProjectDir()?.toVirtualFileUrl(workspaceModel.getVirtualFileUrlManager()) ?: return
|
||||||
|
|
||||||
|
val moduleEntitySource = LegacyBridgeJpsEntitySourceFactory.getInstance(project)
|
||||||
|
.createEntitySourceForModule(baseModuleDir, null)
|
||||||
|
|
||||||
|
val moduleEntity = ModuleEntity(ZIG_MODULE_ID, emptyList(), moduleEntitySource)
|
||||||
|
workspaceModel.update("Add new module") {builder ->
|
||||||
|
builder.addEntity(moduleEntity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val moduleEntity = workspaceModel.currentSnapshot.resolve(moduleId) ?: return
|
||||||
|
val root = getRoot(state, project) ?: return
|
||||||
|
val libRoot = LibraryRoot(root.toVirtualFileUrl(workspaceModel.getVirtualFileUrlManager()), LibraryRootTypeId.SOURCES)
|
||||||
|
val libraryTableId = LibraryTableId.ProjectLibraryTableId
|
||||||
|
val libraryId = LibraryId(ZIG_LIBRARY_ID, libraryTableId)
|
||||||
|
if (libraryId in workspaceModel.currentSnapshot) {
|
||||||
|
val library = workspaceModel.currentSnapshot.resolve(libraryId) ?: return
|
||||||
|
workspaceModel.update("Update library") { builder ->
|
||||||
|
builder.modifyLibraryEntity(library) {
|
||||||
|
roots.clear()
|
||||||
|
roots.add(libRoot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val libraryEntitySource = LegacyBridgeJpsEntitySourceFactory
|
||||||
|
.getInstance(project)
|
||||||
|
.createEntitySourceForProjectLibrary(null)
|
||||||
|
val libraryEntity = LibraryEntity(
|
||||||
|
ZIG_LIBRARY_ID,
|
||||||
|
libraryTableId, emptyList(),
|
||||||
|
libraryEntitySource
|
||||||
|
) {
|
||||||
|
roots.add(libRoot)
|
||||||
|
}
|
||||||
|
workspaceModel.update("Add new library") { builder ->
|
||||||
|
builder.addEntity(libraryEntity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
workspaceModel.update("Link dep") { builder ->
|
||||||
|
builder.modifyModuleEntity(moduleEntity) {
|
||||||
|
dependencies.add(LibraryDependency(libraryId, false, DependencyScope.COMPILE))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun getName(
|
private fun getName(
|
||||||
state: ZigProjectSettings,
|
state: ZigProjectSettings,
|
||||||
|
@ -80,29 +136,29 @@ private fun getName(
|
||||||
return "Zig $version"
|
return "Zig $version"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRoots(
|
suspend fun getRoot(
|
||||||
state: ZigProjectSettings,
|
state: ZigProjectSettings,
|
||||||
project: Project
|
project: Project
|
||||||
): Set<VirtualFile> {
|
): VirtualFile? {
|
||||||
val toolchain = state.toolchain
|
val toolchain = state.toolchain
|
||||||
if (state.overrideStdPath) run {
|
if (state.overrideStdPath) run {
|
||||||
val ePathStr = state.explicitPathToStd ?: return@run
|
val ePathStr = state.explicitPathToStd ?: return@run
|
||||||
val ePath = ePathStr.toNioPathOrNull() ?: return@run
|
val ePath = ePathStr.toNioPathOrNull() ?: return@run
|
||||||
if (ePath.isAbsolute) {
|
if (ePath.isAbsolute) {
|
||||||
val roots = ePath.refreshAndFindVirtualDirectory() ?: return@run
|
val roots = ePath.refreshAndFindVirtualDirectory() ?: return@run
|
||||||
return setOf(roots)
|
return roots
|
||||||
} else if (toolchain != null) {
|
} else if (toolchain != null) {
|
||||||
val stdPath = toolchain.location.resolve(ePath)
|
val stdPath = toolchain.location.resolve(ePath)
|
||||||
if (stdPath.isAbsolute) {
|
if (stdPath.isAbsolute) {
|
||||||
val roots = stdPath.refreshAndFindVirtualDirectory() ?: return@run
|
val roots = stdPath.refreshAndFindVirtualDirectory() ?: return@run
|
||||||
return setOf(roots)
|
return roots
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (toolchain != null) {
|
if (toolchain != null) {
|
||||||
val stdPath = runBlocking { toolchain.zig.getEnv(project) }?.stdPath(toolchain, project) ?: return emptySet()
|
val stdPath = toolchain.zig.getEnv(project)?.stdPath(toolchain, project) ?: return null
|
||||||
val roots = stdPath.refreshAndFindVirtualDirectory() ?: return emptySet()
|
val roots = stdPath.refreshAndFindVirtualDirectory() ?: return null
|
||||||
return setOf(roots)
|
return roots
|
||||||
}
|
}
|
||||||
return emptySet()
|
return null
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue