support: basic idea plugin

This commit is contained in:
Alex Zenla 2023-09-10 01:27:53 -04:00
parent 0024a8b141
commit 0bc3128b9d
Signed by: alex
GPG Key ID: C0780728420EBFE5
17 changed files with 298 additions and 9 deletions

View File

@ -25,3 +25,8 @@ jobs:
with:
name: pork-jar
path: tool/build/libs/pork-all.jar
- name: Archive Idea Plugin
uses: actions/upload-artifact@v3
with:
name: pork-idea
path: support/pork-idea/build/distributions/Pork.zip

View File

@ -107,8 +107,8 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
subtract = { a, b -> a - b },
multiply = { a, b -> a * b },
divide = { a, b -> a / b },
euclideanModulo = { a, b -> throw RuntimeException("Can't perform integer modulo between floating point types") },
remainder = { a, b -> throw RuntimeException("Can't perform integer remainder between floating point types") }
euclideanModulo = { _, _ -> throw RuntimeException("Can't perform integer modulo between floating point types") },
remainder = { _, _ -> throw RuntimeException("Can't perform integer remainder between floating point types") }
)
}
@ -122,8 +122,8 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
subtract = { a, b -> a - b },
multiply = { a, b -> a * b },
divide = { a, b -> a / b },
euclideanModulo = { a, b -> throw RuntimeException("Can't perform integer modulo between floating point types") },
remainder = { a, b -> throw RuntimeException("Can't perform integer remainder between floating point types") }
euclideanModulo = { _, _ -> throw RuntimeException("Can't perform integer modulo between floating point types") },
remainder = { _, _ -> throw RuntimeException("Can't perform integer remainder between floating point types") }
)
}

View File

@ -1 +1,2 @@
org.gradle.warning.mode=none
kotlin.stdlib.default.dependency=false

View File

@ -1,12 +1,16 @@
package gay.pizza.pork.parser
class StringCharSource(val input: String) : CharSource {
private var index = 0
class StringCharSource(
val input: CharSequence,
val startIndex: Int = 0,
val endIndex: Int = input.length - 1
) : CharSource {
private var index = startIndex
override val currentIndex: Int
get() = index
override fun next(): Char {
if (index == input.length) {
if (index == endIndex) {
return CharSource.NullChar
}
val char = input[index]
@ -15,7 +19,7 @@ class StringCharSource(val input: String) : CharSource {
}
override fun peek(): Char {
if (index == input.length) {
if (index == endIndex) {
return CharSource.NullChar
}
return input[index]

View File

@ -10,5 +10,6 @@ include(
":evaluator",
":stdlib",
":ffi",
":tool"
":tool",
":support:pork-idea"
)

View File

@ -0,0 +1,34 @@
plugins {
id("org.jetbrains.intellij") version "1.15.0"
id("gay.pizza.pork.module")
}
dependencies {
implementation(project(":parser"))
}
intellij {
pluginName.set(properties["pluginName"].toString())
version.set(properties["platformVersion"].toString())
type.set(properties["platformType"].toString())
}
tasks {
buildSearchableOptions {
enabled = false
}
patchPluginXml {
version.set(project.properties["pluginVersion"].toString())
sinceBuild.set(project.properties["pluginSinceBuild"].toString())
untilBuild.set(project.properties["pluginUntilBuild"].toString())
pluginDescription.set("Pork Language support for IntelliJ IDEs")
}
}
project.afterEvaluate {
tasks.buildPlugin {
exclude("**/lib/annotations*.jar")
exclude("**/lib/kotlin*.jar")
}
}

View File

@ -0,0 +1,13 @@
# IntelliJ Platform Artifacts Repositories -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html
pluginGroup = gay.pizza.plugins.pork
pluginName = Pork
pluginRepositoryUrl = https://github.com/GayPizzaSpecifications/pork
pluginVersion = 0.1.0
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 232
pluginUntilBuild = 232.*
# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
platformType = IC
platformVersion = 2023.2.1

View File

@ -0,0 +1,26 @@
package gay.pizza.pork.intellij
import com.intellij.openapi.fileTypes.LanguageFileType
import com.intellij.openapi.util.NlsContexts
import com.intellij.openapi.util.NlsSafe
import org.jetbrains.annotations.NonNls
import javax.swing.Icon
@Suppress("UnstableApiUsage")
object PorkFileType : LanguageFileType(PorkLanguage) {
override fun getName(): @NonNls String {
return "Pork File"
}
override fun getDescription(): @NlsContexts.Label String {
return "Pork file"
}
override fun getDefaultExtension(): @NlsSafe String {
return "pork"
}
override fun getIcon(): Icon {
return PorkIcon
}
}

View File

@ -0,0 +1,6 @@
package gay.pizza.pork.intellij
import com.intellij.openapi.util.IconLoader.getIcon
import javax.swing.Icon
val PorkIcon: Icon = getIcon("/icons/pork.png", PorkLanguage::class.java)

View File

@ -0,0 +1,5 @@
package gay.pizza.pork.intellij
import com.intellij.lang.Language
object PorkLanguage : Language("Pork")

View File

@ -0,0 +1,96 @@
package gay.pizza.pork.intellij
import com.intellij.lexer.LexerBase
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.psi.tree.IElementType
import gay.pizza.pork.parser.*
import com.intellij.psi.TokenType as PsiTokenType
class PorkLexer : LexerBase() {
private val log: Logger = Logger.getInstance(PorkLexer::class.java)
private lateinit var source: StringCharSource
private lateinit var tokenizer: Tokenizer
private var internalTokenStart: Int = 0
private var internalTokenEnd: Int = 0
private var internalState: Int = 0
private var currentTokenType: IElementType? = null
override fun start(buffer: CharSequence, startOffset: Int, endOffset: Int, initialState: Int) {
source = StringCharSource(
input = buffer,
startIndex = startOffset,
endIndex = endOffset
)
tokenizer = Tokenizer(source)
internalState = initialState
internalTokenStart = startOffset
internalTokenEnd = startOffset
currentTokenType = null
advance()
}
override fun getState(): Int {
return internalState
}
override fun getTokenType(): IElementType? {
return currentTokenType
}
override fun getTokenStart(): Int {
return internalTokenStart
}
override fun getTokenEnd(): Int {
return internalTokenEnd
}
override fun advance() {
internalTokenStart = internalTokenEnd
if (internalTokenStart == bufferEnd) {
currentTokenType = null
return
}
try {
val currentToken = tokenizer.next()
currentTokenType = tokenAsElement(currentToken)
internalTokenStart = currentToken.start
internalTokenEnd = currentToken.start + currentToken.text.length
} catch (e: ProcessCanceledException) {
throw e
} catch (e: Throwable) {
currentTokenType = PsiTokenType.BAD_CHARACTER
internalTokenEnd = bufferEnd
log.warn(Tokenizer::class.java.name, e)
}
}
override fun getBufferSequence(): CharSequence {
return source.input
}
override fun getBufferEnd(): Int {
return source.endIndex
}
private fun tokenAsElement(token: Token): IElementType = when {
token.type.family == TokenFamily.KeywordFamily ->
PorkTokenTypes.Keyword
token.type.family == TokenFamily.SymbolFamily ->
PorkTokenTypes.Symbol
token.type.family == TokenFamily.OperatorFamily ->
PorkTokenTypes.Operator
token.type.family == TokenFamily.StringLiteralFamily ->
PorkTokenTypes.String
token.type.family == TokenFamily.NumericLiteralFamily ->
PorkTokenTypes.Number
token.type == TokenType.Whitespace ->
PorkTokenTypes.Whitespace
else -> PsiTokenType.CODE_FRAGMENT
}
override fun toString(): String = "Lexer(start=$internalTokenStart, end=$internalTokenEnd)"
}

View File

@ -0,0 +1,49 @@
package gay.pizza.pork.intellij
import com.intellij.lexer.Lexer
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors
import com.intellij.openapi.editor.colors.TextAttributesKey
import com.intellij.openapi.fileTypes.SyntaxHighlighter
import com.intellij.openapi.fileTypes.SyntaxHighlighterBase
import com.intellij.psi.tree.IElementType
object PorkSyntaxHighlighter : SyntaxHighlighter {
override fun getHighlightingLexer(): Lexer {
return PorkLexer()
}
override fun getTokenHighlights(tokenType: IElementType?): Array<TextAttributesKey> {
if (tokenType == null) return emptyArray()
val attributes = when (tokenType) {
PorkTokenTypes.Keyword ->
TextAttributesKey.createTextAttributesKey(
"PORK.KEYWORD",
DefaultLanguageHighlighterColors.KEYWORD
)
PorkTokenTypes.Symbol ->
TextAttributesKey.createTextAttributesKey(
"PORK.SYMBOL",
DefaultLanguageHighlighterColors.LOCAL_VARIABLE
)
PorkTokenTypes.Operator ->
TextAttributesKey.createTextAttributesKey(
"PORK.OPERATOR",
DefaultLanguageHighlighterColors.OPERATION_SIGN
)
PorkTokenTypes.String ->
TextAttributesKey.createTextAttributesKey(
"PORK.STRING",
DefaultLanguageHighlighterColors.STRING
)
PorkTokenTypes.Number ->
TextAttributesKey.createTextAttributesKey(
"PORK.NUMBER",
DefaultLanguageHighlighterColors.NUMBER
)
else -> null
}
return if (attributes == null)
emptyArray()
else SyntaxHighlighterBase.pack(attributes)
}
}

View File

@ -0,0 +1,12 @@
package gay.pizza.pork.intellij
import com.intellij.openapi.fileTypes.SyntaxHighlighter
import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
class PorkSyntaxHighlighterFactory : SyntaxHighlighterFactory() {
override fun getSyntaxHighlighter(project: Project?, virtualFile: VirtualFile?): SyntaxHighlighter {
return PorkSyntaxHighlighter
}
}

View File

@ -0,0 +1,13 @@
package gay.pizza.pork.intellij
import com.intellij.psi.TokenType
import com.intellij.psi.tree.IElementType
object PorkTokenTypes {
val Whitespace = TokenType.WHITE_SPACE
val Keyword = IElementType("keyword", PorkLanguage)
val Symbol = IElementType("symbol", PorkLanguage)
val Operator = IElementType("operator", PorkLanguage)
val String = IElementType("string", PorkLanguage)
val Number = IElementType("number", PorkLanguage)
}

View File

@ -0,0 +1,18 @@
<!-- Plugin Configuration File. Read more: https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html -->
<idea-plugin>
<id>gay.pizza.plugins.pork</id>
<name>Pork</name>
<category>Languages</category>
<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"
implementationClass="gay.pizza.pork.intellij.PorkFileType"/>
<lang.syntaxHighlighterFactory
language="Pork"
implementationClass="gay.pizza.pork.intellij.PorkSyntaxHighlighterFactory"/>
</extensions>
<applicationListeners>
</applicationListeners>
</idea-plugin>

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 270.933 270.933">
<circle cx="-135.467" cy="135.467" r="135.467" style="opacity:1;fill:#f66d71;fill-opacity:1;stroke-width:.264583" transform="scale(-1 1)"/>
<path d="m21.66 63.236-3.97-6.278s-4.494 8.981-9 8.981-6.652-15.505-7.045-18.255c-.394-2.753-.586-8.535.989-9.37 2.73-1.447 12.667-6.785 23.998-13.217a875.884 875.884 0 0 0 21.99-12.96s5.554-3.612 11.782-2.845c8.55 1.055 14.216 6.086 14.216 6.086zm227.614 0 3.969-6.278s4.495 8.981 9 8.981c4.507 0 6.653-15.505 7.045-18.255.394-2.753.587-8.535-.988-9.37-2.73-1.447-12.668-6.785-24-13.217-11.33-6.433-21.988-12.96-21.988-12.96s-5.555-3.612-11.782-2.845c-8.55 1.055-14.217 6.086-14.217 6.086z" style="opacity:1;fill:#f66d71;fill-opacity:1;stroke-width:.264583"/>
<path d="M96.712 92.56c0 11.466-9.295 20.76-20.76 20.76-11.467 0-20.762-9.294-20.762-20.76 0-11.467 9.295-20.762 20.761-20.762s20.761 9.295 20.761 20.762zm77.509 0c0 11.466 9.295 20.76 20.761 20.76s20.761-9.294 20.761-20.76c0-11.467-9.295-20.762-20.76-20.762-11.467 0-20.762 9.295-20.762 20.762z" style="opacity:1;fill:#fff;fill-opacity:1;stroke-width:.271097"/>
<path d="M122.243 166.845c0 11.619-9.418 21.037-21.037 21.037-11.618 0-21.037-9.418-21.037-21.037 0-11.618 9.419-21.037 21.037-21.037 11.619 0 21.037 9.419 21.037 21.037zm13.224-29.411v78.457c-29.536 0-73.486-14.976-73.486-47.713 0-28.115 23.523-30.744 73.486-30.744zm13.223 29.411c0 11.619 9.418 21.037 21.037 21.037 11.618 0 21.037-9.418 21.037-21.037 0-11.618-9.419-21.037-21.037-21.037-11.619 0-21.037 9.419-21.037 21.037zm-13.223-29.411v78.457c29.536 0 73.485-14.976 73.485-47.713 0-28.115-23.523-30.744-73.485-30.744z" style="opacity:1;fill:#fff;fill-rule:evenodd;stroke-width:.236269"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB