mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-02 12:50:55 +00:00
global: idea generation support
This commit is contained in:
parent
821aa3563a
commit
3b101bd48a
@ -1,8 +1,10 @@
|
||||
import gay.pizza.pork.buildext.AstCodegenType
|
||||
|
||||
plugins {
|
||||
id("gay.pizza.pork.module")
|
||||
id("gay.pizza.pork.ast")
|
||||
}
|
||||
|
||||
tasks.compileKotlin {
|
||||
dependsOn(tasks.generateAstCode)
|
||||
porkAst {
|
||||
astCodegenType.set(AstCodegenType.Standard)
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ types:
|
||||
type: List<Definition>
|
||||
LetAssignment:
|
||||
parent: Expression
|
||||
namedElementValue: symbol
|
||||
values:
|
||||
- name: symbol
|
||||
type: Symbol
|
||||
@ -43,6 +44,7 @@ types:
|
||||
type: Expression
|
||||
VarAssignment:
|
||||
parent: Expression
|
||||
namedElementValue: symbol
|
||||
values:
|
||||
- name: symbol
|
||||
type: Symbol
|
||||
@ -50,6 +52,7 @@ types:
|
||||
type: Expression
|
||||
SetAssignment:
|
||||
parent: Expression
|
||||
namedElementValue: symbol
|
||||
values:
|
||||
- name: symbol
|
||||
type: Symbol
|
||||
@ -141,6 +144,7 @@ types:
|
||||
defaultValue: "false"
|
||||
FunctionDefinition:
|
||||
parent: Definition
|
||||
namedElementValue: symbol
|
||||
values:
|
||||
- name: modifiers
|
||||
type: DefinitionModifiers
|
||||
@ -154,6 +158,7 @@ types:
|
||||
type: Native?
|
||||
LetDefinition:
|
||||
parent: Definition
|
||||
namedElementValue: symbol
|
||||
values:
|
||||
- name: modifiers
|
||||
type: DefinitionModifiers
|
||||
@ -251,6 +256,7 @@ types:
|
||||
type: String
|
||||
SymbolReference:
|
||||
parent: Expression
|
||||
namedElementValue: symbol
|
||||
values:
|
||||
- name: symbol
|
||||
type: Symbol
|
||||
|
@ -0,0 +1,6 @@
|
||||
package gay.pizza.pork.buildext
|
||||
|
||||
enum class AstCodegenType {
|
||||
Standard,
|
||||
PorkIdea
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package gay.pizza.pork.buildext
|
||||
|
||||
import gay.pizza.pork.buildext.ast.AstPorkIdeaCodegen
|
||||
import gay.pizza.pork.buildext.ast.AstWorld
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import java.io.File
|
||||
|
||||
open class GeneratePorkIdeaAstCode : DefaultTask() {
|
||||
@get:InputFile
|
||||
var astDescriptionFile: File = project.project(":ast").file("src/main/ast/pork.yml")
|
||||
|
||||
@get:Input
|
||||
var codePackage: String = "gay.pizza.pork.idea.psi.gen"
|
||||
|
||||
@get:OutputDirectory
|
||||
var outputDirectory: File = project.file("src/main/kotlin/gay/pizza/pork/idea/psi/gen")
|
||||
|
||||
@TaskAction
|
||||
fun generate() {
|
||||
val world = AstWorld.read(astDescriptionFile.toPath())
|
||||
AstPorkIdeaCodegen.run(codePackage, world, outputDirectory.toPath())
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package gay.pizza.pork.buildext
|
||||
|
||||
import gay.pizza.pork.buildext.ast.AstCodegen
|
||||
import gay.pizza.pork.buildext.ast.AstStandardCodegen
|
||||
import gay.pizza.pork.buildext.ast.AstGraph
|
||||
import gay.pizza.pork.buildext.ast.AstWorld
|
||||
import org.gradle.api.DefaultTask
|
||||
@ -14,7 +14,7 @@ import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.deleteIfExists
|
||||
import kotlin.io.path.writeText
|
||||
|
||||
open class GenerateAstCode : DefaultTask() {
|
||||
open class GenerateStandardAstCode : DefaultTask() {
|
||||
@get:InputFile
|
||||
var astDescriptionFile: File = project.file("src/main/ast/pork.yml")
|
||||
|
||||
@ -30,7 +30,7 @@ open class GenerateAstCode : DefaultTask() {
|
||||
@TaskAction
|
||||
fun generate() {
|
||||
val world = AstWorld.read(astDescriptionFile.toPath())
|
||||
AstCodegen.run(codePackage, world, outputDirectory.toPath())
|
||||
AstStandardCodegen.run(codePackage, world, outputDirectory.toPath())
|
||||
|
||||
val typeGraphPath = typeGraphFile.toPath()
|
||||
typeGraphPath.deleteIfExists()
|
@ -0,0 +1,7 @@
|
||||
package gay.pizza.pork.buildext
|
||||
|
||||
import org.gradle.api.provider.Property
|
||||
|
||||
interface PorkAstExtension {
|
||||
val astCodegenType: Property<AstCodegenType>
|
||||
}
|
@ -2,15 +2,32 @@ package gay.pizza.pork.buildext
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.kotlin.dsl.create
|
||||
import org.gradle.kotlin.dsl.getByType
|
||||
|
||||
class PorkAstPlugin : Plugin<Project> {
|
||||
override fun apply(target: Project) {
|
||||
val generateAstCode = createGenerateAstCode(target)
|
||||
val processResources = target.tasks.getByName("processResources")
|
||||
processResources.dependsOn(generateAstCode)
|
||||
target.extensions.create("porkAst", PorkAstExtension::class)
|
||||
|
||||
target.afterEvaluate {
|
||||
val generateAstCode = createGenerateAstCode(target)
|
||||
val processResources = target.tasks.getByName("processResources")
|
||||
processResources.dependsOn(generateAstCode)
|
||||
val compileKotlin = target.tasks.getByName("compileKotlin")
|
||||
compileKotlin.dependsOn(generateAstCode)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createGenerateAstCode(project: Project): GenerateAstCode =
|
||||
project.tasks.create("generateAstCode", GenerateAstCode::class)
|
||||
private fun getAstExtension(project: Project): PorkAstExtension =
|
||||
project.extensions.getByType<PorkAstExtension>()
|
||||
|
||||
private fun createGenerateAstCode(project: Project): Task {
|
||||
val extension = getAstExtension(project)
|
||||
val codegenType = extension.astCodegenType.get()
|
||||
if (codegenType == AstCodegenType.Standard) {
|
||||
return project.tasks.create("generateAstCode", GenerateStandardAstCode::class)
|
||||
}
|
||||
return project.tasks.create("generateAstCode", GeneratePorkIdeaAstCode::class)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
package gay.pizza.pork.buildext.ast
|
||||
|
||||
import gay.pizza.pork.buildext.codegen.KotlinWriter
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.deleteExisting
|
||||
import kotlin.io.path.deleteIfExists
|
||||
import kotlin.io.path.listDirectoryEntries
|
||||
import kotlin.io.path.writeText
|
||||
|
||||
open class AstCodegenShared(val pkg: String, val outputDirectory: Path, val world: AstWorld) {
|
||||
protected fun deleteAllContents() {
|
||||
for (child in outputDirectory.listDirectoryEntries("*.kt")) {
|
||||
child.deleteExisting()
|
||||
}
|
||||
}
|
||||
|
||||
protected fun write(fileName: String, writer: KotlinWriter) {
|
||||
val content = "// GENERATED CODE FROM PORK AST CODEGEN\n$writer"
|
||||
val path = outputDirectory.resolve(fileName)
|
||||
path.deleteIfExists()
|
||||
path.writeText(content, StandardCharsets.UTF_8)
|
||||
}
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
package gay.pizza.pork.buildext.ast
|
||||
|
||||
import gay.pizza.pork.buildext.codegen.KotlinClass
|
||||
import gay.pizza.pork.buildext.codegen.KotlinFunction
|
||||
import gay.pizza.pork.buildext.codegen.KotlinParameter
|
||||
import gay.pizza.pork.buildext.codegen.KotlinWriter
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.exists
|
||||
|
||||
class AstPorkIdeaCodegen(pkg: String, outputDirectory: Path, world: AstWorld) :
|
||||
AstCodegenShared(pkg, outputDirectory, world) {
|
||||
companion object {
|
||||
fun run(pkg: String, world: AstWorld, outputDirectory: Path) {
|
||||
if (!outputDirectory.exists()) {
|
||||
outputDirectory.createDirectories()
|
||||
}
|
||||
val codegen = AstPorkIdeaCodegen(pkg, outputDirectory, world)
|
||||
codegen.generate()
|
||||
}
|
||||
}
|
||||
|
||||
fun generate() {
|
||||
deleteAllContents()
|
||||
writePorkElement()
|
||||
writeNamedElement()
|
||||
for (type in world.typeRegistry.types) {
|
||||
writePsiElement(type)
|
||||
}
|
||||
writeElementFactory()
|
||||
}
|
||||
|
||||
fun writePorkElement() {
|
||||
val baseClass = KotlinClass(
|
||||
pkg,
|
||||
"PorkElement",
|
||||
isAbstract = true,
|
||||
constructorParameters = mutableMapOf(
|
||||
"node" to "ASTNode"
|
||||
),
|
||||
inherits = mutableListOf(
|
||||
"ASTWrapperPsiElement(node)"
|
||||
),
|
||||
imports = mutableListOf(
|
||||
"com.intellij.extapi.psi.ASTWrapperPsiElement",
|
||||
"com.intellij.lang.ASTNode"
|
||||
)
|
||||
)
|
||||
|
||||
write("PorkElement.kt", KotlinWriter(baseClass))
|
||||
}
|
||||
|
||||
fun writePsiElement(type: AstType) {
|
||||
val role = world.typeRegistry.roleOfType(type)
|
||||
|
||||
if (role != AstTypeRole.AstNode) {
|
||||
return
|
||||
}
|
||||
|
||||
val baseType =
|
||||
if (type.namedElementValue != null) "PorkNamedElement" else "PorkElement"
|
||||
|
||||
val kotlinClass = KotlinClass(
|
||||
pkg,
|
||||
"${type.name}Element",
|
||||
constructorParameters = mutableMapOf(
|
||||
"node" to "ASTNode"
|
||||
),
|
||||
inherits = mutableListOf("${baseType}(node)"),
|
||||
imports = mutableListOf(
|
||||
"com.intellij.lang.ASTNode"
|
||||
)
|
||||
)
|
||||
|
||||
if (baseType == "PorkNamedElement") {
|
||||
kotlinClass.imports.add(0, "com.intellij.psi.PsiElement")
|
||||
kotlinClass.imports.add("gay.pizza.pork.ast.NodeType")
|
||||
kotlinClass.imports.add("gay.pizza.pork.idea.PorkElementTypes")
|
||||
val getNameFunction = KotlinFunction(
|
||||
"getName",
|
||||
overridden = true,
|
||||
returnType = "String?",
|
||||
isImmediateExpression = true
|
||||
)
|
||||
getNameFunction.body.add("node.findChildByType(PorkElementTypes.elementTypeFor(NodeType.${type.name}))?.text")
|
||||
kotlinClass.functions.add(getNameFunction)
|
||||
|
||||
val setNameFunction = KotlinFunction(
|
||||
"setName",
|
||||
overridden = true,
|
||||
returnType = "PsiElement",
|
||||
isImmediateExpression = true,
|
||||
parameters = mutableListOf(
|
||||
KotlinParameter("name", "String")
|
||||
)
|
||||
)
|
||||
setNameFunction.body.add("this")
|
||||
kotlinClass.functions.add(setNameFunction)
|
||||
}
|
||||
|
||||
write("${type.name}Element.kt", KotlinWriter(kotlinClass))
|
||||
}
|
||||
|
||||
fun writeElementFactory() {
|
||||
val kotlinClass = KotlinClass(
|
||||
pkg,
|
||||
"PorkElementFactory",
|
||||
isObject = true,
|
||||
imports = mutableListOf(
|
||||
"com.intellij.extapi.psi.ASTWrapperPsiElement",
|
||||
"com.intellij.lang.ASTNode",
|
||||
"com.intellij.psi.PsiElement",
|
||||
"gay.pizza.pork.ast.NodeType",
|
||||
"gay.pizza.pork.idea.PorkElementTypes"
|
||||
)
|
||||
)
|
||||
|
||||
val createFunction = KotlinFunction(
|
||||
"create",
|
||||
returnType = "PsiElement",
|
||||
parameters = mutableListOf(
|
||||
KotlinParameter("node", "ASTNode")
|
||||
),
|
||||
isImmediateExpression = true
|
||||
)
|
||||
|
||||
createFunction.body.add("when (PorkElementTypes.nodeTypeFor(node.elementType)) {")
|
||||
for (type in world.typeRegistry.types) {
|
||||
val role = world.typeRegistry.roleOfType(type)
|
||||
|
||||
if (role != AstTypeRole.AstNode) {
|
||||
continue
|
||||
}
|
||||
|
||||
createFunction.body.add(" NodeType.${type.name} -> ${type.name}Element(node)")
|
||||
}
|
||||
createFunction.body.add(" else -> ASTWrapperPsiElement(node)")
|
||||
createFunction.body.add("}")
|
||||
kotlinClass.functions.add(createFunction)
|
||||
|
||||
write("PorkElementFactory.kt", KotlinWriter(kotlinClass))
|
||||
}
|
||||
|
||||
fun writeNamedElement() {
|
||||
val kotlinClass = KotlinClass(
|
||||
pkg,
|
||||
"PorkNamedElement",
|
||||
isAbstract = true,
|
||||
constructorParameters = mutableMapOf(
|
||||
"node" to "ASTNode"
|
||||
),
|
||||
inherits = mutableListOf(
|
||||
"PorkElement(node)",
|
||||
"PsiNamedElement"
|
||||
),
|
||||
imports = mutableListOf(
|
||||
"com.intellij.lang.ASTNode",
|
||||
"com.intellij.psi.PsiNamedElement"
|
||||
)
|
||||
)
|
||||
|
||||
write("PorkNamedElement.kt", KotlinWriter(kotlinClass))
|
||||
}
|
||||
}
|
@ -2,17 +2,12 @@
|
||||
package gay.pizza.pork.buildext.ast
|
||||
|
||||
import gay.pizza.pork.buildext.codegen.*
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.*
|
||||
|
||||
class AstCodegen(val pkg: String, val outputDirectory: Path, val world: AstWorld) {
|
||||
private fun deleteAllContents() {
|
||||
for (child in outputDirectory.listDirectoryEntries("*.kt")) {
|
||||
child.deleteExisting()
|
||||
}
|
||||
}
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.exists
|
||||
|
||||
class AstStandardCodegen(pkg: String, outputDirectory: Path, world: AstWorld) :
|
||||
AstCodegenShared(pkg, outputDirectory, world) {
|
||||
fun generate() {
|
||||
deleteAllContents()
|
||||
for (type in world.typeRegistry.types) {
|
||||
@ -247,7 +242,7 @@ class AstCodegen(val pkg: String, val outputDirectory: Path, val world: AstWorld
|
||||
val kotlinClass = KotlinClass(pkg, type.name)
|
||||
kotlinClassLike = kotlinClass
|
||||
if (role == AstTypeRole.RootNode || role == AstTypeRole.HierarchyNode) {
|
||||
kotlinClass.sealed = true
|
||||
kotlinClass.isSealed = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -494,13 +489,6 @@ class AstCodegen(val pkg: String, val outputDirectory: Path, val world: AstWorld
|
||||
}
|
||||
}
|
||||
|
||||
private fun write(fileName: String, writer: KotlinWriter) {
|
||||
val content = "// GENERATED CODE FROM PORK AST CODEGEN\n$writer"
|
||||
val path = outputDirectory.resolve(fileName)
|
||||
path.deleteIfExists()
|
||||
path.writeText(content, StandardCharsets.UTF_8)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val enableVisitAnyInline = false
|
||||
|
||||
@ -508,7 +496,7 @@ class AstCodegen(val pkg: String, val outputDirectory: Path, val world: AstWorld
|
||||
if (!outputDirectory.exists()) {
|
||||
outputDirectory.createDirectories()
|
||||
}
|
||||
val codegen = AstCodegen(pkg, outputDirectory, world)
|
||||
val codegen = AstStandardCodegen(pkg, outputDirectory, world)
|
||||
codegen.generate()
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package gay.pizza.pork.buildext.ast
|
||||
|
||||
class AstType(val name: String, var parent: AstType? = null) {
|
||||
class AstType(val name: String, var parent: AstType? = null, var namedElementValue: String? = null) {
|
||||
private var internalValues: MutableList<AstValue>? = null
|
||||
private val internalEnums = mutableListOf<AstEnum>()
|
||||
|
||||
|
@ -3,5 +3,6 @@ package gay.pizza.pork.buildext.ast
|
||||
data class AstTypeDescription(
|
||||
val parent: String? = null,
|
||||
val values: List<AstValueDescription>? = null,
|
||||
val enums: List<AstEnumDescription> = emptyList()
|
||||
val enums: List<AstEnumDescription> = emptyList(),
|
||||
val namedElementValue: String? = null
|
||||
)
|
||||
|
@ -55,6 +55,10 @@ class AstWorld {
|
||||
type.parent = world.typeRegistry.lookup(typeDescription.parent)
|
||||
}
|
||||
|
||||
if (typeDescription.namedElementValue != null) {
|
||||
type.namedElementValue = typeDescription.namedElementValue
|
||||
}
|
||||
|
||||
if (typeDescription.values != null) {
|
||||
type.markHasValues()
|
||||
for (value in typeDescription.values) {
|
||||
|
@ -6,7 +6,7 @@ object RunCodegenIde {
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
val world = AstWorld.read(Path("src/main/ast/pork.yml"))
|
||||
AstCodegen.run(
|
||||
AstStandardCodegen.run(
|
||||
pkg = "gay.pizza.pork.ast",
|
||||
world = world,
|
||||
outputDirectory = Path("src/main/kotlin/gay/pizza/pork/ast")
|
||||
|
@ -3,12 +3,16 @@ package gay.pizza.pork.buildext.codegen
|
||||
class KotlinClass(
|
||||
override val pkg: String,
|
||||
override var name: String,
|
||||
var sealed: Boolean = false,
|
||||
var isSealed: Boolean = false,
|
||||
var isInterface: Boolean = false,
|
||||
var isOpen: Boolean = false,
|
||||
var isAbstract: Boolean = false,
|
||||
var isObject: Boolean = false,
|
||||
override var imports: MutableList<String> = mutableListOf(),
|
||||
override var annotations: MutableList<String> = mutableListOf(),
|
||||
override var typeParameters: MutableList<String> = mutableListOf(),
|
||||
override var inherits: MutableList<String> = mutableListOf(),
|
||||
override var members: MutableList<KotlinMember> = mutableListOf(),
|
||||
override var functions: MutableList<KotlinFunction> = mutableListOf()
|
||||
override var functions: MutableList<KotlinFunction> = mutableListOf(),
|
||||
override var constructorParameters: MutableMap<String, String> = mutableMapOf()
|
||||
) : KotlinClassLike()
|
||||
|
@ -9,4 +9,5 @@ abstract class KotlinClassLike {
|
||||
abstract var inherits: MutableList<String>
|
||||
abstract var members: MutableList<KotlinMember>
|
||||
abstract var functions: MutableList<KotlinFunction>
|
||||
abstract var constructorParameters: MutableMap<String, String>
|
||||
}
|
||||
|
@ -9,5 +9,6 @@ class KotlinEnum(
|
||||
override var inherits: MutableList<String> = mutableListOf(),
|
||||
override var members: MutableList<KotlinMember> = mutableListOf(),
|
||||
override var functions: MutableList<KotlinFunction> = mutableListOf(),
|
||||
var entries: MutableList<KotlinEnumEntry> = mutableListOf()
|
||||
override var constructorParameters: MutableMap<String, String> = mutableMapOf(),
|
||||
var entries: MutableList<KotlinEnumEntry> = mutableListOf(),
|
||||
) : KotlinClassLike()
|
||||
|
@ -8,11 +8,26 @@ class KotlinWriter() {
|
||||
}
|
||||
|
||||
fun writeClass(kotlinClass: KotlinClass): Unit = buffer.run {
|
||||
val classType = when {
|
||||
kotlinClass.sealed -> "sealed class"
|
||||
kotlinClass.isInterface -> "interface"
|
||||
else -> "class"
|
||||
val classType = buildString {
|
||||
if (kotlinClass.isOpen) {
|
||||
append("open ")
|
||||
}
|
||||
|
||||
if (kotlinClass.isAbstract) {
|
||||
append("abstract ")
|
||||
}
|
||||
|
||||
if (kotlinClass.isSealed) {
|
||||
append("sealed ")
|
||||
}
|
||||
|
||||
append(when {
|
||||
kotlinClass.isInterface -> "interface"
|
||||
kotlinClass.isObject -> "object"
|
||||
else -> "class"
|
||||
})
|
||||
}
|
||||
|
||||
writeClassLike(classType, kotlinClass)
|
||||
val members = kotlinClass.members.filter {
|
||||
it.abstract || (it.overridden && it.value != null) || it.notInsideConstructor
|
||||
@ -136,6 +151,11 @@ class KotlinWriter() {
|
||||
} else start
|
||||
}
|
||||
append("(${constructor})")
|
||||
} else if (kotlinClass.constructorParameters.isNotEmpty()) {
|
||||
val constructor = kotlinClass.constructorParameters.entries.joinToString(", ") {
|
||||
"${it.key}: ${it.value}"
|
||||
}
|
||||
append("(${constructor})")
|
||||
}
|
||||
|
||||
if (kotlinClass.inherits.isNotEmpty()) {
|
||||
|
@ -1,12 +1,19 @@
|
||||
import gay.pizza.pork.buildext.AstCodegenType
|
||||
|
||||
plugins {
|
||||
id("org.jetbrains.intellij") version "1.15.0"
|
||||
id("gay.pizza.pork.module")
|
||||
id("gay.pizza.pork.ast")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":parser"))
|
||||
}
|
||||
|
||||
porkAst {
|
||||
astCodegenType.set(AstCodegenType.PorkIdea)
|
||||
}
|
||||
|
||||
intellij {
|
||||
pluginName.set(properties["pluginName"].toString())
|
||||
version.set(properties["platformVersion"].toString())
|
||||
|
@ -1,10 +1,7 @@
|
||||
package gay.pizza.pork.idea
|
||||
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import gay.pizza.pork.ast.Node
|
||||
import gay.pizza.pork.ast.NodeType
|
||||
import gay.pizza.pork.parser.TokenType
|
||||
|
||||
|
@ -9,5 +9,5 @@ class PorkFile(viewProvider: FileViewProvider) : PsiFileBase(viewProvider, PorkL
|
||||
return PorkFileType
|
||||
}
|
||||
|
||||
override fun toString(): String = "Pork File"
|
||||
override fun toString(): String = "Pork"
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import javax.swing.Icon
|
||||
@Suppress("UnstableApiUsage")
|
||||
object PorkFileType : LanguageFileType(PorkLanguage) {
|
||||
override fun getName(): @NonNls String {
|
||||
return "Pork File"
|
||||
return "Pork"
|
||||
}
|
||||
|
||||
override fun getDescription(): @NlsContexts.Label String {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package gay.pizza.pork.idea
|
||||
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.lang.ParserDefinition
|
||||
import com.intellij.lang.PsiParser
|
||||
@ -11,6 +10,8 @@ import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.tree.IFileElementType
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import gay.pizza.pork.idea.psi.gen.PorkElementFactory
|
||||
import gay.pizza.pork.parser.TokenType
|
||||
|
||||
class PorkParserDefinition : ParserDefinition {
|
||||
val fileElementType = IFileElementType(PorkLanguage)
|
||||
@ -35,8 +36,12 @@ class PorkParserDefinition : ParserDefinition {
|
||||
return PorkElementTypes.StringSet
|
||||
}
|
||||
|
||||
override fun getWhitespaceTokens(): TokenSet {
|
||||
return TokenSet.create(PorkElementTypes.elementTypeFor(TokenType.Whitespace))
|
||||
}
|
||||
|
||||
override fun createElement(node: ASTNode): PsiElement {
|
||||
return ASTWrapperPsiElement(node)
|
||||
return PorkElementFactory.create(node)
|
||||
}
|
||||
|
||||
override fun createFile(viewProvider: FileViewProvider): PsiFile {
|
||||
|
@ -28,5 +28,5 @@ class PsiBuilderTokenSource(val builder: PsiBuilder) : TokenSource {
|
||||
return Token(tokenType, builder.currentOffset, builder.tokenText!!)
|
||||
}
|
||||
|
||||
class BadCharacterError(val error: String) : RuntimeException(error)
|
||||
class BadCharacterError(error: String) : RuntimeException(error)
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
package gay.pizza.pork.idea.psi
|
||||
|
||||
import gay.pizza.pork.ast.Node
|
||||
import gay.pizza.pork.idea.PorkNodeKey
|
||||
import gay.pizza.pork.idea.psi.gen.PorkElement
|
||||
|
||||
val PorkElement.porkNode: Node?
|
||||
get() = node.getUserData(PorkNodeKey)
|
||||
|
||||
val PorkElement.porkNodeChecked: Node
|
||||
get() = porkNode!!
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class BlockElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class BooleanLiteralElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class BreakElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class CompilationUnitElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class ContinueElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class DoubleLiteralElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class ForInElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class FunctionCallElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,15 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.lang.ASTNode
|
||||
import gay.pizza.pork.ast.NodeType
|
||||
import gay.pizza.pork.idea.PorkElementTypes
|
||||
|
||||
class FunctionDefinitionElement(node: ASTNode) : PorkNamedElement(node) {
|
||||
override fun getName(): String? =
|
||||
node.findChildByType(PorkElementTypes.elementTypeFor(NodeType.FunctionDefinition))?.text
|
||||
|
||||
override fun setName(name: String): PsiElement =
|
||||
this
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class IfElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class ImportDeclarationElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class InfixOperationElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class IntegerLiteralElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,15 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.lang.ASTNode
|
||||
import gay.pizza.pork.ast.NodeType
|
||||
import gay.pizza.pork.idea.PorkElementTypes
|
||||
|
||||
class LetAssignmentElement(node: ASTNode) : PorkNamedElement(node) {
|
||||
override fun getName(): String? =
|
||||
node.findChildByType(PorkElementTypes.elementTypeFor(NodeType.LetAssignment))?.text
|
||||
|
||||
override fun setName(name: String): PsiElement =
|
||||
this
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.lang.ASTNode
|
||||
import gay.pizza.pork.ast.NodeType
|
||||
import gay.pizza.pork.idea.PorkElementTypes
|
||||
|
||||
class LetDefinitionElement(node: ASTNode) : PorkNamedElement(node) {
|
||||
override fun getName(): String? =
|
||||
node.findChildByType(PorkElementTypes.elementTypeFor(NodeType.LetDefinition))?.text
|
||||
|
||||
override fun setName(name: String): PsiElement =
|
||||
this
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class ListLiteralElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class LongLiteralElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class NativeElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class NoneLiteralElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class ParenthesesElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,7 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
abstract class PorkElement(node: ASTNode) : ASTWrapperPsiElement(node)
|
@ -0,0 +1,43 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.psi.PsiElement
|
||||
import gay.pizza.pork.ast.NodeType
|
||||
import gay.pizza.pork.idea.PorkElementTypes
|
||||
|
||||
object PorkElementFactory {
|
||||
fun create(node: ASTNode): PsiElement =
|
||||
when (PorkElementTypes.nodeTypeFor(node.elementType)) {
|
||||
NodeType.Symbol -> SymbolElement(node)
|
||||
NodeType.Block -> BlockElement(node)
|
||||
NodeType.CompilationUnit -> CompilationUnitElement(node)
|
||||
NodeType.LetAssignment -> LetAssignmentElement(node)
|
||||
NodeType.VarAssignment -> VarAssignmentElement(node)
|
||||
NodeType.SetAssignment -> SetAssignmentElement(node)
|
||||
NodeType.InfixOperation -> InfixOperationElement(node)
|
||||
NodeType.BooleanLiteral -> BooleanLiteralElement(node)
|
||||
NodeType.FunctionCall -> FunctionCallElement(node)
|
||||
NodeType.FunctionDefinition -> FunctionDefinitionElement(node)
|
||||
NodeType.LetDefinition -> LetDefinitionElement(node)
|
||||
NodeType.If -> IfElement(node)
|
||||
NodeType.ImportDeclaration -> ImportDeclarationElement(node)
|
||||
NodeType.IntegerLiteral -> IntegerLiteralElement(node)
|
||||
NodeType.LongLiteral -> LongLiteralElement(node)
|
||||
NodeType.DoubleLiteral -> DoubleLiteralElement(node)
|
||||
NodeType.ListLiteral -> ListLiteralElement(node)
|
||||
NodeType.Parentheses -> ParenthesesElement(node)
|
||||
NodeType.PrefixOperation -> PrefixOperationElement(node)
|
||||
NodeType.SuffixOperation -> SuffixOperationElement(node)
|
||||
NodeType.StringLiteral -> StringLiteralElement(node)
|
||||
NodeType.SymbolReference -> SymbolReferenceElement(node)
|
||||
NodeType.While -> WhileElement(node)
|
||||
NodeType.ForIn -> ForInElement(node)
|
||||
NodeType.Break -> BreakElement(node)
|
||||
NodeType.Continue -> ContinueElement(node)
|
||||
NodeType.NoneLiteral -> NoneLiteralElement(node)
|
||||
NodeType.Native -> NativeElement(node)
|
||||
else -> ASTWrapperPsiElement(node)
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.psi.PsiNamedElement
|
||||
|
||||
abstract class PorkNamedElement(node: ASTNode) : PorkElement(node), PsiNamedElement
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class PrefixOperationElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,15 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.lang.ASTNode
|
||||
import gay.pizza.pork.ast.NodeType
|
||||
import gay.pizza.pork.idea.PorkElementTypes
|
||||
|
||||
class SetAssignmentElement(node: ASTNode) : PorkNamedElement(node) {
|
||||
override fun getName(): String? =
|
||||
node.findChildByType(PorkElementTypes.elementTypeFor(NodeType.SetAssignment))?.text
|
||||
|
||||
override fun setName(name: String): PsiElement =
|
||||
this
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class StringLiteralElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class SuffixOperationElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class SymbolElement(node: ASTNode) : PorkElement(node)
|
@ -0,0 +1,15 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.lang.ASTNode
|
||||
import gay.pizza.pork.ast.NodeType
|
||||
import gay.pizza.pork.idea.PorkElementTypes
|
||||
|
||||
class SymbolReferenceElement(node: ASTNode) : PorkNamedElement(node) {
|
||||
override fun getName(): String? =
|
||||
node.findChildByType(PorkElementTypes.elementTypeFor(NodeType.SymbolReference))?.text
|
||||
|
||||
override fun setName(name: String): PsiElement =
|
||||
this
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.lang.ASTNode
|
||||
import gay.pizza.pork.ast.NodeType
|
||||
import gay.pizza.pork.idea.PorkElementTypes
|
||||
|
||||
class VarAssignmentElement(node: ASTNode) : PorkNamedElement(node) {
|
||||
override fun getName(): String? =
|
||||
node.findChildByType(PorkElementTypes.elementTypeFor(NodeType.VarAssignment))?.text
|
||||
|
||||
override fun setName(name: String): PsiElement =
|
||||
this
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
// GENERATED CODE FROM PORK AST CODEGEN
|
||||
package gay.pizza.pork.idea.psi.gen
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class WhileElement(node: ASTNode) : PorkElement(node)
|
@ -6,7 +6,7 @@
|
||||
<vendor>Gay Pizza Specifications</vendor>
|
||||
<depends>com.intellij.modules.platform</depends>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<fileType name="Pork File" language="Pork" extensions="pork" fieldName="INSTANCE"
|
||||
<fileType name="Pork" language="Pork" extensions="pork" fieldName="INSTANCE"
|
||||
implementationClass="gay.pizza.pork.idea.PorkFileType"/>
|
||||
<lang.syntaxHighlighterFactory
|
||||
language="Pork"
|
||||
|
Loading…
Reference in New Issue
Block a user