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
|
||||
|
||||
- Zig
|
||||
- Changing the zig standard library path in the project settings now properly updates the dependency
|
||||
- ZLS
|
||||
- All of the config options are now exposed in the GUI
|
||||
|
||||
|
|
|
@ -22,15 +22,18 @@
|
|||
|
||||
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.project.Project
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
@State(
|
||||
name = "ZigProjectSettings",
|
||||
storages = [Storage("zigbrains.xml")]
|
||||
)
|
||||
class ZigProjectSettingsService: PersistentStateComponent<ZigProjectSettings> {
|
||||
class ZigProjectSettingsService(val project: Project): PersistentStateComponent<ZigProjectSettings> {
|
||||
@Volatile
|
||||
private var state = ZigProjectSettings()
|
||||
|
||||
|
@ -40,10 +43,13 @@ class ZigProjectSettingsService: PersistentStateComponent<ZigProjectSettings> {
|
|||
|
||||
fun setState(value: ZigProjectSettings) {
|
||||
this.state = value
|
||||
zigCoroutineScope.launch {
|
||||
ZigSyntheticLibrary.reload(project, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadState(state: ZigProjectSettings) {
|
||||
this.state = state
|
||||
setState(state)
|
||||
}
|
||||
|
||||
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.intellij.navigation.ItemPresentation
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.guessProjectDir
|
||||
import com.intellij.openapi.roots.SyntheticLibrary
|
||||
import com.intellij.openapi.util.io.toNioPathOrNull
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
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 java.util.*
|
||||
import javax.swing.Icon
|
||||
|
||||
class ZigSyntheticLibrary(val project: Project) : SyntheticLibrary(), ItemPresentation {
|
||||
private var state: ZigProjectSettings = project.zigProjectSettings.state.copy()
|
||||
private val roots by lazy {
|
||||
getRoots(project.zigProjectSettings.state, project)
|
||||
runBlocking {getRoot(state, project)}?.let { setOf(it) } ?: emptySet()
|
||||
}
|
||||
|
||||
private val name by lazy {
|
||||
getName(project.zigProjectSettings.state, project)
|
||||
getName(state, project)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is ZigSyntheticLibrary)
|
||||
return false
|
||||
|
||||
return roots == other.roots
|
||||
return state == other.state
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
|
@ -67,9 +73,59 @@ class ZigSyntheticLibrary(val project: Project) : SyntheticLibrary(), ItemPresen
|
|||
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(
|
||||
state: ZigProjectSettings,
|
||||
|
@ -80,29 +136,29 @@ private fun getName(
|
|||
return "Zig $version"
|
||||
}
|
||||
|
||||
private fun getRoots(
|
||||
suspend fun getRoot(
|
||||
state: ZigProjectSettings,
|
||||
project: Project
|
||||
): Set<VirtualFile> {
|
||||
): VirtualFile? {
|
||||
val toolchain = state.toolchain
|
||||
if (state.overrideStdPath) run {
|
||||
val ePathStr = state.explicitPathToStd ?: return@run
|
||||
val ePath = ePathStr.toNioPathOrNull() ?: return@run
|
||||
if (ePath.isAbsolute) {
|
||||
val roots = ePath.refreshAndFindVirtualDirectory() ?: return@run
|
||||
return setOf(roots)
|
||||
return roots
|
||||
} else if (toolchain != null) {
|
||||
val stdPath = toolchain.location.resolve(ePath)
|
||||
if (stdPath.isAbsolute) {
|
||||
val roots = stdPath.refreshAndFindVirtualDirectory() ?: return@run
|
||||
return setOf(roots)
|
||||
return roots
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toolchain != null) {
|
||||
val stdPath = runBlocking { toolchain.zig.getEnv(project) }?.stdPath(toolchain, project) ?: return emptySet()
|
||||
val roots = stdPath.refreshAndFindVirtualDirectory() ?: return emptySet()
|
||||
return setOf(roots)
|
||||
val stdPath = toolchain.zig.getEnv(project)?.stdPath(toolchain, project) ?: return null
|
||||
val roots = stdPath.refreshAndFindVirtualDirectory() ?: return null
|
||||
return roots
|
||||
}
|
||||
return emptySet()
|
||||
return null
|
||||
}
|
Loading…
Add table
Reference in a new issue