Skip to content

Commit f45c822

Browse files
committed
feat(snippet): enhance JSON handling for devcontainer files #308
- Add support for parsing and updating devcontainer.json files. - Introduce new methods to handle JSON properties and values. - Update file handling logic to check for devcontainer-specific images.
1 parent 8324b37 commit f45c822

File tree

1 file changed

+59
-8
lines changed

1 file changed

+59
-8
lines changed

core/src/main/kotlin/cc/unitmesh/devti/gui/snippet/AutoDevLanguageLabelAction.kt

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
11
package cc.unitmesh.devti.gui.snippet
22

33
import cc.unitmesh.devti.util.parser.CodeFence
4+
import com.intellij.ide.scratch.ScratchRootType
45
import com.intellij.json.JsonLanguage
6+
import com.intellij.json.psi.JsonFile
7+
import com.intellij.json.psi.JsonLiteral
8+
import com.intellij.json.psi.JsonObject
9+
import com.intellij.json.psi.JsonProperty
10+
import com.intellij.json.psi.JsonStringLiteral
11+
import com.intellij.json.psi.JsonValue
12+
import com.intellij.json.JsonUtil
513
import com.intellij.openapi.actionSystem.ActionUpdateThread
614
import com.intellij.openapi.actionSystem.AnActionEvent
715
import com.intellij.openapi.actionSystem.CommonDataKeys
816
import com.intellij.openapi.actionSystem.Presentation
917
import com.intellij.openapi.actionSystem.ex.CustomComponentAction
18+
import com.intellij.openapi.application.runReadAction
1019
import com.intellij.openapi.fileEditor.FileDocumentManager
1120
import com.intellij.openapi.project.DumbAwareAction
1221
import com.intellij.openapi.project.Project
1322
import com.intellij.openapi.util.Key
23+
import com.intellij.openapi.vfs.VirtualFile
24+
import com.intellij.psi.PsiFile
25+
import com.intellij.psi.PsiManager
1426
import com.intellij.testFramework.LightVirtualFile
1527
import com.intellij.ui.components.JBLabel
1628
import com.intellij.util.ui.UIUtil
@@ -43,22 +55,38 @@ class AutoDevLanguageLabelAction : DumbAwareAction(), CustomComponentAction {
4355

4456
override fun update(e: AnActionEvent) {
4557
val editor = e.dataContext.getData(CommonDataKeys.EDITOR) ?: return
46-
val lightVirtualFile = FileDocumentManager.getInstance().getFile(editor.document) as? LightVirtualFile ?: return
58+
var lightVirtualFile = FileDocumentManager.getInstance().getFile(editor.document) as? LightVirtualFile ?: return
4759

48-
// val project = e.project ?: return
49-
// if (lightVirtualFile.language == JsonLanguage.INSTANCE) {
50-
// checkDevContainer(project, lightVirtualFile)
51-
// }
60+
val project = e.project ?: return
61+
if (lightVirtualFile.language == JsonLanguage.INSTANCE) {
62+
lightVirtualFile = updateForDevContainer(project, lightVirtualFile) ?: lightVirtualFile
63+
}
5264

5365
val displayName =
54-
lightVirtualFile.language.displayName ?: CodeFence.displayNameByExt(lightVirtualFile.extension ?: "txt")
66+
lightVirtualFile.language?.displayName ?: CodeFence.displayNameByExt(lightVirtualFile.extension ?: "txt")
5567
e.presentation.putClientProperty(LANGUAGE_PRESENTATION_KEY, displayName)
5668
}
5769

58-
private fun checkDevContainer(
70+
private fun updateForDevContainer(
5971
project: Project,
6072
lightVirtualFile: LightVirtualFile
61-
) {
73+
): LightVirtualFile? {
74+
val psiFile = runReadAction { PsiManager.getInstance(project).findFile(lightVirtualFile) } ?: return null
75+
val image = getEnvObject("image", psiFile) ?: return null
76+
77+
val literal = image as? JsonStringLiteral ?: return null
78+
val imageValue = literal.value
79+
80+
if (!imageValue.contains("mcr.microsoft.com/devcontainers")) return null
81+
82+
/// create new file with name devcontainer.json
83+
val content = lightVirtualFile.inputStream.readBytes().toString(Charsets.UTF_8)
84+
val newFile = LightVirtualFile(
85+
"devcontainer.json",
86+
JsonLanguage.INSTANCE,
87+
content
88+
)
89+
6290
try {
6391
// follow: https://containers.dev/guide/dockerfile
6492
// check image, exist, {
@@ -68,9 +96,32 @@ class AutoDevLanguageLabelAction : DumbAwareAction(), CustomComponentAction {
6896
.filter { it.isAvailable(lightVirtualFile) }
6997

7098
// devcontainer.json
99+
providers.map {
100+
it.name
101+
}
71102
} catch (e: Exception) {
72103
e.printStackTrace()
73104
}
105+
106+
return newFile
107+
}
108+
109+
fun getEnvObject(propName: String, psiFile: PsiFile): JsonValue? {
110+
val rootObject = (psiFile as? JsonFile)?.topLevelValue as? JsonObject ?: return null
111+
return rootObject.propertyList.firstOrNull { it.name == propName }?.value
112+
}
113+
114+
fun JsonProperty.valueAsString(obj: JsonObject): String? {
115+
val value = JsonUtil.getPropertyValueOfType(obj, name, JsonLiteral::class.java)
116+
return when (value) {
117+
is JsonStringLiteral -> value.value
118+
else -> value?.text
119+
}
120+
}
121+
122+
fun JsonObject.findString(name: String): String? {
123+
val property = findProperty(name) ?: return null
124+
return property.valueAsString(this)
74125
}
75126

76127
companion object {

0 commit comments

Comments
 (0)