Skip to content

Commit

Permalink
feat: Basic structure view
Browse files Browse the repository at this point in the history
  • Loading branch information
siketyan committed Aug 16, 2024
1 parent 6041721 commit 3475cf9
Show file tree
Hide file tree
Showing 18 changed files with 203 additions and 6 deletions.
4 changes: 4 additions & 0 deletions gen/jp/s6n/idea/typespec/lang/psi/TypeSpecAliasStatement.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions gen/jp/s6n/idea/typespec/lang/psi/TypeSpecEnumStatement.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions gen/jp/s6n/idea/typespec/lang/psi/TypeSpecModelStatement.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions gen/jp/s6n/idea/typespec/lang/psi/TypeSpecUnionStatement.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 25 additions & 6 deletions grammars/TypeSpec.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
psiImplClassSuffix='Impl'
psiPackage='jp.s6n.idea.typespec.lang.psi'
psiImplPackage='jp.s6n.idea.typespec.lang.psi.impl'
psiImplUtilClass='jp.s6n.idea.typespec.lang.psi.impl.TypeSpecImplUtil'

tokens=[
IMPORT = 'import'
Expand Down Expand Up @@ -73,19 +74,28 @@ UsingStatement ::= USING Path SEMICOLON {extends=Statement}

NamespaceStatement ::= Decorator* NAMESPACE Path (SEMICOLON | LBRACE Statement* RBRACE) {extends=Statement}

EnumStatement ::= Decorator* ENUM Identifier EnumVariantsBlock {extends=Statement}
EnumStatement ::= Decorator* ENUM Identifier EnumVariantsBlock {
extends=Statement
methods=[getPresentation]
}

EnumVariantsBlock ::= LBRACE [EnumVariant (COMMA EnumVariant)* COMMA?] RBRACE

EnumVariant ::= Decorator* Identifier

UnionStatement ::= Decorator* UNION Identifier UnionVariantsBlock {extends=Statement}
UnionStatement ::= Decorator* UNION Identifier UnionVariantsBlock {
extends=Statement
methods=[getPresentation]
}

UnionVariantsBlock ::= LBRACE [UnionVariant (COMMA UnionVariant)* COMMA?] RBRACE

UnionVariant ::= Decorator* Identifier COLON PathType

ModelStatement ::= Decorator* MODEL Identifier (ModelExtends | ModelIs)? ModelPropertiesBlock {extends=Statement}
ModelStatement ::= Decorator* MODEL Identifier (ModelExtends | ModelIs)? ModelPropertiesBlock {
extends=Statement
methods=[getPresentation]
}

ModelExtends ::= EXTENDS PathType

Expand All @@ -95,15 +105,24 @@ ModelPropertiesBlock ::= LBRACE ModelProperty* RBRACE

ModelProperty ::= Decorator* Identifier QUEST? COLON Type SEMICOLON

InterfaceStatement ::= Decorator* INTERFACE Identifier InterfaceOperationsBlock {extends=Statement}
InterfaceStatement ::= Decorator* INTERFACE Identifier InterfaceOperationsBlock {
extends=Statement
methods=[getPresentation]
}

InterfaceOperationsBlock ::= LBRACE InterfaceOperation* RBRACE

InterfaceOperation ::= Decorator* Operation SEMICOLON

OperationStatement ::= Decorator* OP Operation SEMICOLON {extends=Statement}
OperationStatement ::= Decorator* OP Operation SEMICOLON {
extends=Statement
methods=[getPresentation]
}

AliasStatement ::= ALIAS Identifier EQ Type SEMICOLON {extends=Statement}
AliasStatement ::= ALIAS Identifier EQ Type SEMICOLON {
extends=Statement
methods=[getPresentation]
}

Operation ::= Identifier OperationArgumentList COLON Type

Expand Down
21 changes: 21 additions & 0 deletions src/main/kotlin/jp/s6n/idea/typespec/lang/TypeSpecIconProvider.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package jp.s6n.idea.typespec.lang

import com.intellij.icons.AllIcons
import com.intellij.ide.IconProvider
import com.intellij.psi.PsiElement
import jp.s6n.idea.typespec.lang.psi.*
import javax.swing.Icon

class TypeSpecIconProvider : IconProvider() {
override fun getIcon(element: PsiElement, flags: Int): Icon? {
return when (element) {
is TypeSpecEnumStatement -> AllIcons.Nodes.Enum
is TypeSpecUnionStatement -> AllIcons.Nodes.Enum
is TypeSpecModelStatement -> AllIcons.Nodes.Class
is TypeSpecInterfaceStatement -> AllIcons.Nodes.Interface
is TypeSpecAliasStatement -> AllIcons.Nodes.Type
is TypeSpecOperationStatement -> AllIcons.Nodes.Function
else -> null
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package jp.s6n.idea.typespec.lang

import com.intellij.ide.projectView.PresentationData
import com.intellij.ide.structureView.StructureViewBuilder
import com.intellij.ide.structureView.StructureViewModelBase
import com.intellij.ide.structureView.StructureViewTreeElement
import com.intellij.ide.structureView.TreeBasedStructureViewBuilder
import com.intellij.ide.util.treeView.smartTree.TreeElement
import com.intellij.lang.PsiStructureViewFactory
import com.intellij.navigation.ItemPresentation
import com.intellij.openapi.editor.Editor
import com.intellij.psi.NavigatablePsiElement
import com.intellij.psi.PsiFile
import jp.s6n.idea.typespec.lang.psi.TypeSpecFile

class TypeSpecStructureViewFactory : PsiStructureViewFactory {
override fun getStructureViewBuilder(file: PsiFile) = object : TreeBasedStructureViewBuilder() {
override fun createStructureViewModel(editor: Editor?) = TypeSpecStructureViewModel(file, editor)
}
}

class TypeSpecStructureViewModel(file: PsiFile, editor: Editor?) : StructureViewModelBase(file, editor, TypeSpecStructureViewElement(file))

class TypeSpecStructureViewElement(private val element: NavigatablePsiElement) : StructureViewTreeElement {
override fun getValue() = element

override fun getPresentation(): ItemPresentation = element.presentation ?: PresentationData()

override fun getChildren(): Array<TreeElement> {
return when (element) {
is TypeSpecFile -> {
element.statements
.filterIsInstance<NavigatablePsiElement>()
.filter { it.presentation != null }
.map { TypeSpecStructureViewElement(it) }
.toTypedArray()
}
else -> TreeElement.EMPTY_ARRAY
}
}
}
3 changes: 3 additions & 0 deletions src/main/kotlin/jp/s6n/idea/typespec/lang/psi/TypeSpecFile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package jp.s6n.idea.typespec.lang.psi

import com.intellij.extapi.psi.PsiFileBase
import com.intellij.psi.FileViewProvider
import com.intellij.psi.util.childrenOfType
import jp.s6n.idea.typespec.lang.TypeSpecFileType
import jp.s6n.idea.typespec.lang.TypeSpecLanguage

class TypeSpecFile(viewProvider: FileViewProvider) : PsiFileBase(viewProvider, TypeSpecLanguage) {
val statements get() = childrenOfType<TypeSpecStatement>()

override fun getFileType() = TypeSpecFileType
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package jp.s6n.idea.typespec.lang.psi.impl

import com.intellij.navigation.ItemPresentation
import jp.s6n.idea.typespec.lang.psi.TypeSpecAliasStatement
import jp.s6n.idea.typespec.lang.psi.TypeSpecElement
import jp.s6n.idea.typespec.lang.psi.TypeSpecEnumStatement
import jp.s6n.idea.typespec.lang.psi.TypeSpecInterfaceStatement
import jp.s6n.idea.typespec.lang.psi.TypeSpecModelStatement
import jp.s6n.idea.typespec.lang.psi.TypeSpecOperationStatement
import jp.s6n.idea.typespec.lang.psi.TypeSpecUnionStatement

object TypeSpecImplUtil {
@JvmStatic
fun getPresentation(element: TypeSpecElement): ItemPresentation? {
return when (element) {
is TypeSpecEnumStatement -> object : ItemPresentation {
override fun getPresentableText() = element.identifier.text
override fun getIcon(unused: Boolean) = element.getIcon(0)
}
is TypeSpecUnionStatement -> object : ItemPresentation {
override fun getPresentableText() = element.identifier.text
override fun getIcon(unused: Boolean) = element.getIcon(0)
}
is TypeSpecModelStatement -> object : ItemPresentation {
override fun getPresentableText() = element.identifier.text
override fun getIcon(unused: Boolean) = element.getIcon(0)
}
is TypeSpecInterfaceStatement -> object : ItemPresentation {
override fun getPresentableText() = element.identifier.text
override fun getIcon(unused: Boolean) = element.getIcon(0)
}
is TypeSpecOperationStatement -> object : ItemPresentation {
override fun getPresentableText() = element.operation.identifier.text
override fun getIcon(unused: Boolean) = element.getIcon(0)
}
is TypeSpecAliasStatement -> object : ItemPresentation {
override fun getPresentableText() = element.identifier.text
override fun getIcon(unused: Boolean) = element.getIcon(0)
}
else -> null
}
}
}
Loading

0 comments on commit 3475cf9

Please sign in to comment.