Skip to content

Commit

Permalink
GML: "Component" -> "Widget"
Browse files Browse the repository at this point in the history
  • Loading branch information
mattco98 committed Jan 27, 2024
1 parent 224fd2f commit 3db561f
Show file tree
Hide file tree
Showing 19 changed files with 107 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import com.intellij.psi.util.PsiTreeUtil
import com.intellij.refactoring.suggested.endOffset
import com.intellij.refactoring.suggested.startOffset
import me.mattco.serenityos.gml.psi.GMLPsiElement
import me.mattco.serenityos.gml.psi.api.GMLComponent
import me.mattco.serenityos.gml.psi.api.GMLWidget
import me.mattco.serenityos.gml.psi.api.GMLVisitor

class GMLBlockFoldingBuilder : CustomFoldingBuilder() {
Expand All @@ -35,8 +35,8 @@ class GMLBlockFoldingBuilder : CustomFoldingBuilder() {
override fun visitPsiElement(o: GMLPsiElement) {
}

override fun visitComponent(o: GMLComponent) {
super.visitComponent(o)
override fun visitWidget(o: GMLWidget) {
super.visitWidget(o)
val start = o.openCurly?.startOffset ?: return
val end = o.closeCurly?.endOffset ?: return
descriptors += FoldingDescriptor(o, TextRange(start, end))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class GMLColorSettingsPage : DSLColorSettingsPage(GMLLanguage) {

override fun getAdditionalHighlightingTagToDescriptorMap() = mapOf(
"NS_NAME" to Highlights.NAMESPACE_NAME,
"CLASS_NAME" to Highlights.COMPONENT_NAME,
"CLASS_NAME" to Highlights.WIDGET_NAME,
"PROPERTY" to Highlights.PROPERTY_NAME,
"BOOLEAN" to Highlights.BOOLEAN
)
Expand All @@ -105,7 +105,7 @@ class GMLColorSettingsPage : DSLColorSettingsPage(GMLLanguage) {
"Comments" to Highlights.COMMENT,

"Identifiers//Namespaces" to Highlights.NAMESPACE_NAME,
"Identifiers//Classes" to Highlights.COMPONENT_NAME,
"Identifiers//Classes" to Highlights.WIDGET_NAME,
"Identifiers//Properties" to Highlights.PROPERTY_NAME,

"Literals//Numbers" to Highlights.NUMBER,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import com.intellij.lang.documentation.DocumentationSettings
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.colors.TextAttributesKey
import com.intellij.openapi.editor.richcopy.HtmlSyntaxInfoUtil
import com.intellij.openapi.util.text.HtmlChunk
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
Expand All @@ -19,8 +18,8 @@ import com.intellij.psi.util.elementType
import com.jetbrains.cidr.lang.psi.OCFile
import com.jetbrains.cidr.lang.psi.OCStructLike
import me.mattco.serenityos.common.ancestorOfType
import me.mattco.serenityos.gml.psi.api.GMLComponent
import me.mattco.serenityos.gml.psi.api.GMLComponentName
import me.mattco.serenityos.gml.psi.api.GMLWidget
import me.mattco.serenityos.gml.psi.api.GMLWidgetName
import me.mattco.serenityos.gml.psi.api.GMLProperty
import me.mattco.serenityos.gml.psi.api.GMLPropertyIdentifier

Expand Down Expand Up @@ -51,36 +50,36 @@ class GMLDocumentationProvider : AbstractDocumentationProvider() {
if (propIdent != null)
return propIdent.ancestorOfType<GMLProperty>()

val compIdent = contextElement?.ancestorOfType<GMLComponentName>()
val compIdent = contextElement?.ancestorOfType<GMLWidgetName>()
if (compIdent != null)
return compIdent.ancestorOfType<GMLComponent>()
return compIdent.ancestorOfType<GMLWidget>()

return null
}

// Also include the '@' for component names
// Also include the '@' for widget names
if (contextElement?.elementType == GMLTypes.AT)
return contextElement?.ancestorOfType<GMLComponent>()
return contextElement?.ancestorOfType<GMLWidget>()

return super.getCustomDocumentationElement(editor, file, contextElement, targetOffset)
}

override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? {
return when (element) {
is GMLComponent -> {
val component = element.gmlComponent ?: return null
is GMLWidget -> {
val widget = element.gmlWidget ?: return null
buildString {
append(DocumentationMarkup.DEFINITION_START)
appendStyled(component.name, Highlights.COMPONENT_NAME)
if (component.inherits != null) {
appendStyled(widget.name, Highlights.WIDGET_NAME)
if (widget.inherits != null) {
append(" : ")
appendStyled(component.inherits, Highlights.COMPONENT_NAME)
appendStyled(widget.inherits, Highlights.WIDGET_NAME)
}
append(DocumentationMarkup.DEFINITION_END)

if (component.description != null) {
if (widget.description != null) {
append(DocumentationMarkup.CONTENT_START)
append("<p>${component.description}</p>")
append("<p>${widget.description}</p>")
append(DocumentationMarkup.CONTENT_END)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ import com.intellij.icons.AllIcons
import com.intellij.psi.PsiElement
import com.jetbrains.cidr.lang.psi.OCStructLike
import me.mattco.serenityos.common.findChildrenOfType
import me.mattco.serenityos.gml.psi.api.GMLComponent
import me.mattco.serenityos.gml.psi.api.GMLWidget

class GMLLineMarkerProvider : LineMarkerProvider {
override fun collectSlowLineMarkers(
elements: MutableList<out PsiElement>,
result: MutableCollection<in LineMarkerInfo<*>>
) {
elements.filterIsInstance<GMLComponent>().forEach {
elements.filterIsInstance<GMLWidget>().forEach {
NavigationGutterIconBuilder.create(AllIcons.Nodes.ModelClass)
.setTarget((it.reference?.resolve() as? OCStructLike)?.nameIdentifier ?: return@forEach)
.setTooltipText("Jump to C++ Widget")
.createLineMarkerInfo(it.componentName.findChildrenOfType(GMLTypes.IDENTIFIER).first())
.createLineMarkerInfo(it.widgetName.findChildrenOfType(GMLTypes.IDENTIFIER).first())
.let(result::add)
}
}
Expand Down
42 changes: 21 additions & 21 deletions src/main/kotlin/me/mattco/serenityos/gml/GMLService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ import me.mattco.serenityos.common.userlandDirectory
import kotlin.collections.set

interface GMLService {
val components: Map<String, Component>
val widgets: Map<String, Widget>

fun lookupComponent(name: String) = components[name]
fun lookupWidget(name: String) = widgets[name]

fun load()
}

class GMLServiceImpl(
private val project: Project,
) : GMLService {
override val components = mutableMapOf<String, Component>()
override val widgets = mutableMapOf<String, Widget>()

override fun load() {
if (!project.isSerenity)
Expand All @@ -43,14 +43,14 @@ class GMLServiceImpl(

for (file in propertyFiles) {
try {
Json.Default.decodeFromString<List<Component>>(file.readText()).forEach {
components[it.name] = it
Json.Default.decodeFromString<List<Widget>>(file.readText()).forEach {
widgets[it.name] = it
}
} catch (_: SerializationException) {
}
}

postComponentLoad()
postWidgetsLoad()
}
}

Expand All @@ -64,33 +64,33 @@ class GMLServiceImpl(
return

try {
val components = Json.Default.decodeFromString<List<Component>>(event.file!!.text)
val widgets = Json.Default.decodeFromString<List<Widget>>(event.file!!.text)
ApplicationManager.getApplication().runReadAction {
components.forEach {
service.components[it.name] = it
widgets.forEach {
service.widgets[it.name] = it
}
}

service.postComponentLoad()
service.postWidgetsLoad()
} catch (_: SerializationException) {
// If we fail to serialize the file, it is likely being edited
}
}
}

private fun postComponentLoad() {
private fun postWidgetsLoad() {
// Widget::layout is special-cased in the compiler and won't appear in the json files
val widgetComponent = components["GUI::Widget"] ?: return
if (widgetComponent.properties.none { it.name == "layout" }) {
components["GUI::Widget"] = Component(
widgetComponent.name,
widgetComponent.header,
widgetComponent.inherits,
widgetComponent.description,
widgetComponent.properties + Property(
val widget = widgets["GUI::Widget"] ?: return
if (widget.properties.none { it.name == "layout" }) {
widgets["GUI::Widget"] = Widget(
widget.name,
widget.header,
widget.inherits,
widget.description,
widget.properties + Property(
"layout",
"The layout of the component",
"GUI::Component",
"The layout of the widget",
"GUI::Widget",
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ object Highlights {
val COLON = OPERATOR.extend("COLON")

val NAMESPACE_NAME = Default.CLASS_NAME.extend("NAMESPACE_NAME")
val COMPONENT_NAME = NAMESPACE_NAME.extend("CLASS_NAME")
val WIDGET_NAME = NAMESPACE_NAME.extend("WIDGET_NAME")
val PROPERTY_NAME = Default.INSTANCE_FIELD.extend("PROPERTY_NAME")

private fun TextAttributesKey.extend(name: String) = TextAttributesKey.createTextAttributesKey("GML_$name", this)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package me.mattco.serenityos.gml.annotators

import ai.grazie.utils.dropPrefix
import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.openapi.components.service
import com.intellij.psi.PsiElement
import me.mattco.serenityos.common.DSLAnnotator
Expand All @@ -13,16 +12,16 @@ import me.mattco.serenityos.gml.psi.api.*
class GMLErrorAnnotator : DSLAnnotator() {
override fun annotate(element: PsiElement) {
when (element) {
is GMLComponentName -> {
is GMLWidgetName -> {
val name = element.text.dropPrefix("@")
if (element.project.service<GMLService>().lookupComponent(name) == null)
element.highlightError("Unknown component")
if (element.project.service<GMLService>().lookupWidget(name) == null)
element.highlightError("Unknown widget")
}
is GMLPropertyIdentifier -> {
val parentWidget = element.ancestorOfType<GMLComponent>() ?: return
val parentWidget = element.ancestorOfType<GMLWidget>() ?: return
val gmlService = element.project.service<GMLService>()
val component = gmlService.lookupComponent(parentWidget.identWithoutAt) ?: return
if (component.getProperty(element.identifier.text, gmlService) == null)
val widget = gmlService.lookupWidget(parentWidget.identWithoutAt) ?: return
if (widget.getProperty(element.identifier.text, gmlService) == null)
element.highlightError("Unknown property")
}
is GMLProperty -> {
Expand Down Expand Up @@ -56,7 +55,7 @@ class GMLErrorAnnotator : DSLAnnotator() {
Type.Bitmap -> if (value.string == null) return Lint(value, "Expected String")
Type.Bool -> if (value.boolean == null) return Lint(value, "Expected bool")
Type.Color -> if (value.string == null) return Lint(value, "Expected String")
Type.Component -> if (value.component == null) return Lint(value, "Expected Component")
Type.Widget -> if (value.widget == null) return Lint(value, "Expected Widget")
Type.Double -> if (value.number == null) return Lint(value, "Expected double")
is Type.EnumType -> if (value.string == null) return Lint(value, "Expected String")
is Type.ErrorType -> return Lint(value, type.message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import me.mattco.serenityos.common.DSLAnnotator
import me.mattco.serenityos.common.findChildrenOfType
import me.mattco.serenityos.gml.GMLTypes
import me.mattco.serenityos.gml.Highlights
import me.mattco.serenityos.gml.psi.api.GMLComponent
import me.mattco.serenityos.gml.psi.api.GMLWidget
import me.mattco.serenityos.gml.psi.api.GMLProperty
import me.mattco.serenityos.gml.psi.api.GMLValue

Expand All @@ -20,11 +20,11 @@ class GMLSyntaxAnnotator : DSLAnnotator(), DumbAware {
element.highlightError("Unexpected EOL in string literal")
}
}
is GMLComponent -> {
val parts = element.componentName.findChildrenOfType(GMLTypes.IDENTIFIER)
is GMLWidget -> {
val parts = element.widgetName.findChildrenOfType(GMLTypes.IDENTIFIER)
parts.dropLast(1).forEach { it.highlight(Highlights.NAMESPACE_NAME) }
if (parts.isNotEmpty())
parts.last().highlight(Highlights.COMPONENT_NAME)
parts.last().highlight(Highlights.WIDGET_NAME)
}
is GMLProperty -> element.propertyIdentifier.identifier.highlight(Highlights.PROPERTY_NAME)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.intellij.codeInsight.completion.CompletionType

class GMLCompletionContributor : CompletionContributor() {
init {
extend(GMLComponentCompletion)
extend(GMLWidgetCompletion)
extend(GMLPropertyCompletion)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package me.mattco.serenityos.gml.completions

import ai.grazie.utils.dropPrefix
import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.openapi.components.service
import com.intellij.patterns.ElementPattern
import com.intellij.psi.PsiElement
import com.intellij.util.ProcessingContext
import me.mattco.serenityos.common.PsiPattern
import me.mattco.serenityos.common.ancestorOfType
import me.mattco.serenityos.common.psiElement
import me.mattco.serenityos.gml.GMLService
import me.mattco.serenityos.gml.GMLTypes
import me.mattco.serenityos.gml.Type
import me.mattco.serenityos.gml.psi.api.GMLComponent
import me.mattco.serenityos.gml.psi.api.GMLWidget
import me.mattco.serenityos.gml.psi.api.GMLPropertyIdentifier

object GMLPropertyCompletion : GMLCompletion() {
Expand All @@ -27,10 +24,10 @@ object GMLPropertyCompletion : GMLCompletion() {
result: CompletionResultSet,
) {
val gmlService = parameters.editor.project!!.service<GMLService>()
val parentComponentName =
parameters.position.ancestorOfType<GMLComponent>()?.identWithoutAt ?: return
val parentComponent = gmlService.lookupComponent(parentComponentName) ?: return
val elements = parentComponent.getAllProperties(gmlService).map { property ->
val parentWidgetName =
parameters.position.ancestorOfType<GMLWidget>()?.identWithoutAt ?: return
val parentWidget = gmlService.lookupWidget(parentWidgetName) ?: return
val elements = parentWidget.getAllProperties(gmlService).map { property ->
LookupElementBuilder.create(property.name)
.withTypeText(property.type.presentation())
.withInsertHandler { context, _ ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,16 @@ import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.openapi.components.service
import com.intellij.openapi.progress.ProgressManager
import com.intellij.patterns.ElementPattern
import com.intellij.psi.PsiElement
import com.intellij.util.ProcessingContext
import me.mattco.serenityos.common.PsiPattern
import me.mattco.serenityos.common.psiElement
import me.mattco.serenityos.gml.GMLService
import me.mattco.serenityos.gml.GMLTypes
import me.mattco.serenityos.gml.psi.api.GMLComponentName
import me.mattco.serenityos.gml.psi.api.GMLWidgetName

object GMLComponentCompletion : GMLCompletion() {
object GMLWidgetCompletion : GMLCompletion() {
override val pattern: PsiPattern
get() = psiElement(GMLTypes.IDENTIFIER).withParent(psiElement<GMLComponentName>())
get() = psiElement(GMLTypes.IDENTIFIER).withParent(psiElement<GMLWidgetName>())

override fun addCompletions(
parameters: CompletionParameters,
Expand All @@ -25,7 +23,7 @@ object GMLComponentCompletion : GMLCompletion() {
) {
ProgressManager.checkCanceled()
try {
val elements = parameters.editor.project!!.service<GMLService>().components.values.map {
val elements = parameters.editor.project!!.service<GMLService>().widgets.values.map {
LookupElementBuilder.create("@${it.name}")
}
result.addAllElements(elements)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class GMLFormattingBlock(
override fun buildChildren() = children

override fun getChildAttributes(newChildIndex: Int): ChildAttributes {
if (node.elementType == GMLTypes.COMPONENT_BODY || node.elementType == GMLTypes.ARRAY)
if (node.elementType == GMLTypes.WIDGET_BODY || node.elementType == GMLTypes.ARRAY)
return ChildAttributes(Indent.getNormalIndent(), null)
return ChildAttributes(Indent.getNoneIndent(), null)
}
Expand Down
Loading

0 comments on commit 3db561f

Please sign in to comment.