Skip to content

Commit

Permalink
support: basic idea plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
azenla committed Sep 10, 2023
1 parent 0024a8b commit 0bc3128
Show file tree
Hide file tree
Showing 17 changed files with 298 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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") }
)
}

Expand All @@ -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") }
)
}

Expand Down
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
org.gradle.warning.mode=none
kotlin.stdlib.default.dependency=false
12 changes: 8 additions & 4 deletions parser/src/main/kotlin/gay/pizza/pork/parser/StringCharSource.kt
Original file line number Diff line number Diff line change
@@ -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]
Expand All @@ -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]
Expand Down
3 changes: 2 additions & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ include(
":evaluator",
":stdlib",
":ffi",
":tool"
":tool",
":support:pork-idea"
)
34 changes: 34 additions & 0 deletions support/pork-idea/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -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")
}
}
13 changes: 13 additions & 0 deletions support/pork-idea/gradle.properties
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package gay.pizza.pork.intellij

import com.intellij.lang.Language

object PorkLanguage : Language("Pork")
Original file line number Diff line number Diff line change
@@ -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)"
}
Original file line number Diff line number Diff line change
@@ -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)
}
}
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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)
}
18 changes: 18 additions & 0 deletions support/pork-idea/src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
@@ -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>
6 changes: 6 additions & 0 deletions support/pork-idea/src/main/resources/META-INF/pluginIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 0bc3128

Please sign in to comment.