Phase 0: strip JetBrains template, register Jai language and file type
- delete demo tool window + message bundle, rewrite plugin.xml metadata - add JaiLanguage, JaiFileType, file icon, JaiTokenTypes (from the compiler's own lexer: modules/Jai_Lexer/module.jai) - add ./jaitest: runs tests and reports the JUnit XML, not just the exit code - ignore .kotlin
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
.gradle
|
||||
.idea
|
||||
.intellijPlatform
|
||||
build
|
||||
.kotlin
|
||||
build
|
||||
|
||||
46
jaitest
Executable file
46
jaitest
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run the test suite and report the JUnit XML, not just the exit code.
|
||||
#
|
||||
# A green `test` task does not prove tests ran (see AGENTS.md), so this always
|
||||
# prints tests/failures/errors per suite and dumps failure messages.
|
||||
#
|
||||
# Usage: ./jaitest [gradle args...] e.g. ./jaitest --tests '*Lexer*'
|
||||
set -uo pipefail
|
||||
|
||||
cd "$(dirname "$0")" || exit 1
|
||||
|
||||
rm -rf build/test-results/test
|
||||
./jaigradle test "$@" 2>&1 | grep -vE '^\[[0-9.]+s\]\[warning\]\[cds\]'
|
||||
gradle_status=${PIPESTATUS[0]}
|
||||
|
||||
echo
|
||||
echo "=== JUnit XML ==="
|
||||
shopt -s nullglob
|
||||
xml=(build/test-results/test/*.xml)
|
||||
if [ ${#xml[@]} -eq 0 ]; then
|
||||
echo "NO TEST XML PRODUCED — tests did not run."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
total=0
|
||||
bad=0
|
||||
for f in "${xml[@]}"; do
|
||||
line=$(sed -n '2p' "$f")
|
||||
name=$(sed -nE 's/^<testsuite name="([^"]*)".*/\1/p' <<<"$line")
|
||||
t=$(sed -nE 's/.*tests="([0-9]*)".*/\1/p' <<<"$line")
|
||||
fa=$(sed -nE 's/.*failures="([0-9]*)".*/\1/p' <<<"$line")
|
||||
er=$(sed -nE 's/.*errors="([0-9]*)".*/\1/p' <<<"$line")
|
||||
sk=$(sed -nE 's/.*skipped="([0-9]*)".*/\1/p' <<<"$line")
|
||||
printf '%-60s tests=%s skipped=%s failures=%s errors=%s\n' "$name" "$t" "$sk" "$fa" "$er"
|
||||
total=$((total + t))
|
||||
bad=$((bad + fa + er))
|
||||
if [ "$fa" != "0" ] || [ "$er" != "0" ]; then
|
||||
grep -E '<(failure|error) ' "$f" | head -40
|
||||
fi
|
||||
done
|
||||
|
||||
echo "--- total tests=$total failures+errors=$bad gradle_exit=$gradle_status"
|
||||
if [ "$total" -eq 0 ] || [ "$bad" -ne 0 ] || [ "$gradle_status" -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
echo "OK"
|
||||
@@ -1,22 +0,0 @@
|
||||
package dev.hgh
|
||||
|
||||
import com.intellij.DynamicBundle
|
||||
import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.annotations.PropertyKey
|
||||
import java.util.function.Supplier
|
||||
|
||||
private const val BUNDLE = "messages.MyMessageBundle"
|
||||
|
||||
internal object MyMessageBundle {
|
||||
private val instance = DynamicBundle(MyMessageBundle::class.java, BUNDLE)
|
||||
|
||||
@JvmStatic
|
||||
fun message(key: @PropertyKey(resourceBundle = BUNDLE) String, vararg params: Any?): @Nls String {
|
||||
return instance.getMessage(key, *params)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun lazyMessage(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any?): Supplier<@Nls String> {
|
||||
return instance.getLazyMessage(key, *params)
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package dev.hgh
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.wm.ToolWindow
|
||||
import com.intellij.openapi.wm.ToolWindowFactory
|
||||
import com.intellij.ui.components.JBLabel
|
||||
import com.intellij.ui.components.JBPanel
|
||||
import com.intellij.ui.content.ContentFactory
|
||||
import javax.swing.JButton
|
||||
import kotlin.random.Random
|
||||
|
||||
class MyToolWindowFactory : ToolWindowFactory {
|
||||
override fun shouldBeAvailable(project: Project) = true
|
||||
|
||||
override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
|
||||
val myToolWindow = MyToolWindow()
|
||||
val content = ContentFactory.getInstance().createContent(myToolWindow.getContent(), null, false)
|
||||
toolWindow.contentManager.addContent(content)
|
||||
}
|
||||
|
||||
class MyToolWindow {
|
||||
private val content = JBPanel<JBPanel<*>>().apply {
|
||||
val label = JBLabel(MyMessageBundle.message("toolwindow.MyToolWindow.number.label", "?"))
|
||||
|
||||
add(label)
|
||||
add(JButton(MyMessageBundle.message("toolwindow.MyToolWindow.shuffle.button")).apply {
|
||||
addActionListener {
|
||||
label.text = MyMessageBundle.message(
|
||||
"toolwindow.MyToolWindow.number.label", Random(System.currentTimeMillis()).nextInt(1000)
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun getContent(): JBPanel<JBPanel<*>> = content
|
||||
}
|
||||
}
|
||||
20
src/main/kotlin/dev/hgh/jai/JaiFileType.kt
Normal file
20
src/main/kotlin/dev/hgh/jai/JaiFileType.kt
Normal file
@@ -0,0 +1,20 @@
|
||||
package dev.hgh.jai
|
||||
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType
|
||||
import com.intellij.openapi.util.IconLoader
|
||||
import javax.swing.Icon
|
||||
|
||||
object JaiIcons {
|
||||
@JvmField
|
||||
val FILE: Icon = IconLoader.getIcon("/icons/jai.svg", JaiIcons::class.java)
|
||||
}
|
||||
|
||||
object JaiFileType : LanguageFileType(JaiLanguage) {
|
||||
override fun getName(): String = "Jai"
|
||||
|
||||
override fun getDescription(): String = "Jai source file"
|
||||
|
||||
override fun getDefaultExtension(): String = "jai"
|
||||
|
||||
override fun getIcon(): Icon = JaiIcons.FILE
|
||||
}
|
||||
11
src/main/kotlin/dev/hgh/jai/JaiLanguage.kt
Normal file
11
src/main/kotlin/dev/hgh/jai/JaiLanguage.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
package dev.hgh.jai
|
||||
|
||||
import com.intellij.lang.Language
|
||||
|
||||
object JaiLanguage : Language("Jai") {
|
||||
private fun readResolve(): Any = JaiLanguage
|
||||
|
||||
override fun getDisplayName(): String = "Jai"
|
||||
|
||||
override fun isCaseSensitive(): Boolean = true
|
||||
}
|
||||
390
src/main/kotlin/dev/hgh/jai/lexer/JaiTokenTypes.kt
Normal file
390
src/main/kotlin/dev/hgh/jai/lexer/JaiTokenTypes.kt
Normal file
@@ -0,0 +1,390 @@
|
||||
package dev.hgh.jai.lexer
|
||||
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import dev.hgh.jai.JaiLanguage
|
||||
|
||||
class JaiTokenType(
|
||||
debugName: String,
|
||||
) : IElementType(debugName, JaiLanguage) {
|
||||
override fun toString(): String = "Jai:" + super.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* The Jai token set.
|
||||
*
|
||||
* Derived from the compiler's own lexer, `~/.local/jai/modules/Jai_Lexer/module.jai`
|
||||
* (`Token_Type` at :17, `check_for_keyword` at :758, `compose_new_token` at :1503).
|
||||
* See `docs/JAI_LANGUAGE_REFERENCE.md` §3/§4.
|
||||
*
|
||||
* Deliberate divergences from the compiler lexer, all in favour of the IDE:
|
||||
* - `#ident` is a single [DIRECTIVE] token (the compiler emits `#` then an ident).
|
||||
* - `#string ID ... ID` is a single [HERE_STRING] token, so the lexer never has to
|
||||
* carry the terminator across a token boundary and can restart anywhere.
|
||||
* - `::` and `:=` are single tokens (the compiler emits separate `:` `:` / `:` `=`).
|
||||
* - The backtick of a backticked identifier is its own [BACKTICK] token (the compiler
|
||||
* folds it into the identifier token as a flag).
|
||||
*/
|
||||
object JaiTokenTypes {
|
||||
// --- trivia -----------------------------------------------------------
|
||||
@JvmField val LINE_COMMENT = JaiTokenType("LINE_COMMENT")
|
||||
|
||||
@JvmField val BLOCK_COMMENT = JaiTokenType("BLOCK_COMMENT")
|
||||
|
||||
// --- literals and names -----------------------------------------------
|
||||
@JvmField val IDENT = JaiTokenType("IDENT")
|
||||
|
||||
@JvmField val NUMBER = JaiTokenType("NUMBER")
|
||||
|
||||
@JvmField val STRING = JaiTokenType("STRING")
|
||||
|
||||
@JvmField val HERE_STRING = JaiTokenType("HERE_STRING")
|
||||
|
||||
@JvmField val DIRECTIVE = JaiTokenType("DIRECTIVE")
|
||||
|
||||
@JvmField val NOTE = JaiTokenType("NOTE")
|
||||
|
||||
// --- keywords ---------------------------------------------------------
|
||||
@JvmField val KW_IF = JaiTokenType("if")
|
||||
|
||||
@JvmField val KW_XX = JaiTokenType("xx")
|
||||
|
||||
@JvmField val KW_IFX = JaiTokenType("ifx")
|
||||
|
||||
@JvmField val KW_FOR = JaiTokenType("for")
|
||||
|
||||
@JvmField val KW_THEN = JaiTokenType("then")
|
||||
|
||||
@JvmField val KW_ELSE = JaiTokenType("else")
|
||||
|
||||
@JvmField val KW_NULL = JaiTokenType("null")
|
||||
|
||||
@JvmField val KW_CASE = JaiTokenType("case")
|
||||
|
||||
@JvmField val KW_ENUM = JaiTokenType("enum")
|
||||
|
||||
@JvmField val KW_TRUE = JaiTokenType("true")
|
||||
|
||||
@JvmField val KW_CAST = JaiTokenType("cast")
|
||||
|
||||
@JvmField val KW_WHILE = JaiTokenType("while")
|
||||
|
||||
@JvmField val KW_BREAK = JaiTokenType("break")
|
||||
|
||||
@JvmField val KW_USING = JaiTokenType("using")
|
||||
|
||||
@JvmField val KW_DEFER = JaiTokenType("defer")
|
||||
|
||||
@JvmField val KW_FALSE = JaiTokenType("false")
|
||||
|
||||
@JvmField val KW_UNION = JaiTokenType("union")
|
||||
|
||||
@JvmField val KW_RETURN = JaiTokenType("return")
|
||||
|
||||
@JvmField val KW_STRUCT = JaiTokenType("struct")
|
||||
|
||||
@JvmField val KW_REMOVE = JaiTokenType("remove")
|
||||
|
||||
@JvmField val KW_INLINE = JaiTokenType("inline")
|
||||
|
||||
@JvmField val KW_SIZE_OF = JaiTokenType("size_of")
|
||||
|
||||
@JvmField val KW_TYPE_OF = JaiTokenType("type_of")
|
||||
|
||||
@JvmField val KW_CODE_OF = JaiTokenType("code_of")
|
||||
|
||||
@JvmField val KW_CONTEXT = JaiTokenType("context")
|
||||
|
||||
@JvmField val KW_CONTINUE = JaiTokenType("continue")
|
||||
|
||||
@JvmField val KW_OPERATOR = JaiTokenType("operator")
|
||||
|
||||
@JvmField val KW_TYPE_INFO = JaiTokenType("type_info")
|
||||
|
||||
@JvmField val KW_NO_INLINE = JaiTokenType("no_inline")
|
||||
|
||||
@JvmField val KW_INTERFACE = JaiTokenType("interface")
|
||||
|
||||
@JvmField val KW_ENUM_FLAGS = JaiTokenType("enum_flags")
|
||||
|
||||
@JvmField val KW_IS_CONSTANT = JaiTokenType("is_constant")
|
||||
|
||||
@JvmField val KW_PUSH_CONTEXT = JaiTokenType("push_context")
|
||||
|
||||
@JvmField val KW_INITIALIZER_OF = JaiTokenType("initializer_of")
|
||||
|
||||
/** `name` -> keyword token. Exactly `check_for_keyword`, nothing more. */
|
||||
@JvmField
|
||||
val KEYWORD_MAP: Map<String, JaiTokenType> =
|
||||
mapOf(
|
||||
"if" to KW_IF,
|
||||
"xx" to KW_XX,
|
||||
"ifx" to KW_IFX,
|
||||
"for" to KW_FOR,
|
||||
"then" to KW_THEN,
|
||||
"else" to KW_ELSE,
|
||||
"null" to KW_NULL,
|
||||
"case" to KW_CASE,
|
||||
"enum" to KW_ENUM,
|
||||
"true" to KW_TRUE,
|
||||
"cast" to KW_CAST,
|
||||
"while" to KW_WHILE,
|
||||
"break" to KW_BREAK,
|
||||
"using" to KW_USING,
|
||||
"defer" to KW_DEFER,
|
||||
"false" to KW_FALSE,
|
||||
"union" to KW_UNION,
|
||||
"return" to KW_RETURN,
|
||||
"struct" to KW_STRUCT,
|
||||
"remove" to KW_REMOVE,
|
||||
"inline" to KW_INLINE,
|
||||
"size_of" to KW_SIZE_OF,
|
||||
"type_of" to KW_TYPE_OF,
|
||||
"code_of" to KW_CODE_OF,
|
||||
"context" to KW_CONTEXT,
|
||||
"continue" to KW_CONTINUE,
|
||||
"operator" to KW_OPERATOR,
|
||||
"type_info" to KW_TYPE_INFO,
|
||||
"no_inline" to KW_NO_INLINE,
|
||||
"interface" to KW_INTERFACE,
|
||||
"enum_flags" to KW_ENUM_FLAGS,
|
||||
"is_constant" to KW_IS_CONSTANT,
|
||||
"push_context" to KW_PUSH_CONTEXT,
|
||||
"initializer_of" to KW_INITIALIZER_OF,
|
||||
)
|
||||
|
||||
/**
|
||||
* Built-in type names. These are ordinary identifiers to the compiler — they are
|
||||
* *not* reserved — but they get their own highlight. Kept as a name set, not a
|
||||
* token type, so the parser can never depend on them being keywords.
|
||||
* See `docs/JAI_LANGUAGE_REFERENCE.md` §3.
|
||||
*/
|
||||
@JvmField
|
||||
val BUILTIN_TYPE_NAMES: Set<String> =
|
||||
setOf(
|
||||
"s8",
|
||||
"s16",
|
||||
"s32",
|
||||
"s64",
|
||||
"u8",
|
||||
"u16",
|
||||
"u32",
|
||||
"u64",
|
||||
"int",
|
||||
"float",
|
||||
"float32",
|
||||
"float64",
|
||||
"bool",
|
||||
"string",
|
||||
"void",
|
||||
"Type",
|
||||
"Any",
|
||||
"Code",
|
||||
)
|
||||
|
||||
/** Implicit `for` loop variables. Ordinary identifiers, highlighted specially. */
|
||||
@JvmField
|
||||
val LOOP_VARIABLE_NAMES: Set<String> = setOf("it", "it_index")
|
||||
|
||||
// --- operators and punctuation ----------------------------------------
|
||||
@JvmField val PLUS = JaiTokenType("+")
|
||||
|
||||
@JvmField val MINUS = JaiTokenType("-")
|
||||
|
||||
@JvmField val STAR = JaiTokenType("*")
|
||||
|
||||
@JvmField val SLASH = JaiTokenType("/")
|
||||
|
||||
@JvmField val PERCENT = JaiTokenType("%")
|
||||
|
||||
@JvmField val PLUS_EQ = JaiTokenType("+=")
|
||||
|
||||
@JvmField val MINUS_EQ = JaiTokenType("-=")
|
||||
|
||||
@JvmField val STAR_EQ = JaiTokenType("*=")
|
||||
|
||||
@JvmField val SLASH_EQ = JaiTokenType("/=")
|
||||
|
||||
@JvmField val PERCENT_EQ = JaiTokenType("%=")
|
||||
|
||||
@JvmField val EQ = JaiTokenType("=")
|
||||
|
||||
@JvmField val EQ_EQ = JaiTokenType("==")
|
||||
|
||||
@JvmField val EQ_EQ_EQ = JaiTokenType("===")
|
||||
|
||||
@JvmField val NOT_EQ = JaiTokenType("!=")
|
||||
|
||||
@JvmField val NOT = JaiTokenType("!")
|
||||
|
||||
@JvmField val LT = JaiTokenType("<")
|
||||
|
||||
@JvmField val GT = JaiTokenType(">")
|
||||
|
||||
@JvmField val LT_EQ = JaiTokenType("<=")
|
||||
|
||||
@JvmField val GT_EQ = JaiTokenType(">=")
|
||||
|
||||
@JvmField val AND_AND = JaiTokenType("&&")
|
||||
|
||||
@JvmField val OR_OR = JaiTokenType("||")
|
||||
|
||||
@JvmField val AND_AND_EQ = JaiTokenType("&&=")
|
||||
|
||||
@JvmField val OR_OR_EQ = JaiTokenType("||=")
|
||||
|
||||
@JvmField val AND = JaiTokenType("&")
|
||||
|
||||
@JvmField val OR = JaiTokenType("|")
|
||||
|
||||
@JvmField val XOR = JaiTokenType("^")
|
||||
|
||||
@JvmField val TILDE = JaiTokenType("~")
|
||||
|
||||
@JvmField val AND_EQ = JaiTokenType("&=")
|
||||
|
||||
@JvmField val OR_EQ = JaiTokenType("|=")
|
||||
|
||||
@JvmField val XOR_EQ = JaiTokenType("^=")
|
||||
|
||||
@JvmField val SHL = JaiTokenType("<<")
|
||||
|
||||
@JvmField val SHR = JaiTokenType(">>")
|
||||
|
||||
@JvmField val SHL_EQ = JaiTokenType("<<=")
|
||||
|
||||
@JvmField val SHR_EQ = JaiTokenType(">>=")
|
||||
|
||||
@JvmField val ROL = JaiTokenType("<<<")
|
||||
|
||||
@JvmField val ROR = JaiTokenType(">>>")
|
||||
|
||||
@JvmField val ROL_EQ = JaiTokenType("<<<=")
|
||||
|
||||
@JvmField val ROR_EQ = JaiTokenType(">>>=")
|
||||
|
||||
@JvmField val RIGHT_ARROW = JaiTokenType("->")
|
||||
|
||||
@JvmField val QUICK_LAMBDA = JaiTokenType("=>")
|
||||
|
||||
@JvmField val DOUBLE_DOT = JaiTokenType("..")
|
||||
|
||||
@JvmField val TRIPLE_MINUS = JaiTokenType("---")
|
||||
|
||||
@JvmField val DOUBLE_MINUS = JaiTokenType("--")
|
||||
|
||||
@JvmField val DOUBLE_COMMA = JaiTokenType(",,")
|
||||
|
||||
@JvmField val BEGIN_STRUCT_LITERAL = JaiTokenType(".{")
|
||||
|
||||
@JvmField val BEGIN_ARRAY_LITERAL = JaiTokenType(".[")
|
||||
|
||||
@JvmField val POSTFIX_DEREFERENCE = JaiTokenType(".*")
|
||||
|
||||
@JvmField val DOLLAR = JaiTokenType("$")
|
||||
|
||||
@JvmField val DOUBLE_DOLLAR = JaiTokenType("$$")
|
||||
|
||||
@JvmField val COLON = JaiTokenType(":")
|
||||
|
||||
@JvmField val COLON_COLON = JaiTokenType("::")
|
||||
|
||||
@JvmField val COLON_EQ = JaiTokenType(":=")
|
||||
|
||||
@JvmField val SEMICOLON = JaiTokenType(";")
|
||||
|
||||
@JvmField val COMMA = JaiTokenType(",")
|
||||
|
||||
@JvmField val DOT = JaiTokenType(".")
|
||||
|
||||
@JvmField val QUESTION = JaiTokenType("?")
|
||||
|
||||
@JvmField val BACKTICK = JaiTokenType("`")
|
||||
|
||||
@JvmField val BACKSLASH = JaiTokenType("\\")
|
||||
|
||||
@JvmField val HASH = JaiTokenType("#")
|
||||
|
||||
@JvmField val AT = JaiTokenType("@")
|
||||
|
||||
@JvmField val LPAREN = JaiTokenType("(")
|
||||
|
||||
@JvmField val RPAREN = JaiTokenType(")")
|
||||
|
||||
@JvmField val LBRACKET = JaiTokenType("[")
|
||||
|
||||
@JvmField val RBRACKET = JaiTokenType("]")
|
||||
|
||||
@JvmField val LBRACE = JaiTokenType("{")
|
||||
|
||||
@JvmField val RBRACE = JaiTokenType("}")
|
||||
|
||||
// --- token sets -------------------------------------------------------
|
||||
@JvmField val COMMENTS: TokenSet = TokenSet.create(LINE_COMMENT, BLOCK_COMMENT)
|
||||
|
||||
@JvmField val STRINGS: TokenSet = TokenSet.create(STRING, HERE_STRING)
|
||||
|
||||
@JvmField val KEYWORDS: TokenSet = TokenSet.create(*KEYWORD_MAP.values.toTypedArray())
|
||||
|
||||
@JvmField
|
||||
val OPERATORS: TokenSet =
|
||||
TokenSet.create(
|
||||
PLUS,
|
||||
MINUS,
|
||||
STAR,
|
||||
SLASH,
|
||||
PERCENT,
|
||||
PLUS_EQ,
|
||||
MINUS_EQ,
|
||||
STAR_EQ,
|
||||
SLASH_EQ,
|
||||
PERCENT_EQ,
|
||||
EQ,
|
||||
EQ_EQ,
|
||||
EQ_EQ_EQ,
|
||||
NOT_EQ,
|
||||
NOT,
|
||||
LT,
|
||||
GT,
|
||||
LT_EQ,
|
||||
GT_EQ,
|
||||
AND_AND,
|
||||
OR_OR,
|
||||
AND_AND_EQ,
|
||||
OR_OR_EQ,
|
||||
AND,
|
||||
OR,
|
||||
XOR,
|
||||
TILDE,
|
||||
AND_EQ,
|
||||
OR_EQ,
|
||||
XOR_EQ,
|
||||
SHL,
|
||||
SHR,
|
||||
SHL_EQ,
|
||||
SHR_EQ,
|
||||
ROL,
|
||||
ROR,
|
||||
ROL_EQ,
|
||||
ROR_EQ,
|
||||
RIGHT_ARROW,
|
||||
QUICK_LAMBDA,
|
||||
DOUBLE_DOT,
|
||||
DOUBLE_MINUS,
|
||||
BEGIN_STRUCT_LITERAL,
|
||||
BEGIN_ARRAY_LITERAL,
|
||||
POSTFIX_DEREFERENCE,
|
||||
DOLLAR,
|
||||
DOUBLE_DOLLAR,
|
||||
COLON,
|
||||
COLON_COLON,
|
||||
COLON_EQ,
|
||||
DOUBLE_COMMA,
|
||||
DOT,
|
||||
QUESTION,
|
||||
BACKTICK,
|
||||
BACKSLASH,
|
||||
HASH,
|
||||
AT,
|
||||
)
|
||||
}
|
||||
@@ -1,33 +1,25 @@
|
||||
<!-- Plugin Configuration File. Read more: https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html -->
|
||||
<idea-plugin>
|
||||
<!-- Unique identifier of the plugin. It should be FQN. It cannot be changed between the plugin versions. -->
|
||||
<id>dev.hgh.intellijai</id>
|
||||
|
||||
<!-- Public plugin name should be written in Title Case.
|
||||
Guidelines: https://plugins.jetbrains.com/docs/marketplace/best-practices-for-listing.html#plugin-name -->
|
||||
<name>Intellijai</name>
|
||||
<name>Jai</name>
|
||||
|
||||
<!-- A displayed Vendor name or Organization ID displayed on the Plugins Page. -->
|
||||
<vendor url="https://www.yourcompany.com">YourCompany</vendor>
|
||||
<vendor>hgh</vendor>
|
||||
|
||||
<!-- Description of the plugin displayed on the Plugin Page and IDE Plugin Manager.
|
||||
Guidelines: https://plugins.jetbrains.com/docs/marketplace/best-practices-for-listing.html#plugin-description -->
|
||||
<description><![CDATA[
|
||||
Enter short description for your plugin here.<br>
|
||||
<em>most HTML tags may be used</em>
|
||||
Support for the <b>Jai</b> programming language.<br/>
|
||||
Syntax highlighting for <code>.jai</code> files.
|
||||
]]></description>
|
||||
|
||||
<!-- Product and plugin compatibility requirements.
|
||||
Read more: https://plugins.jetbrains.com/docs/intellij/plugin-compatibility.html -->
|
||||
<depends>com.intellij.modules.platform</depends>
|
||||
|
||||
<resource-bundle>messages.MyMessageBundle</resource-bundle>
|
||||
|
||||
<!-- Extensions defined by the plugin.
|
||||
Read more: https://plugins.jetbrains.com/docs/intellij/plugin-extension-points.html -->
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<toolWindow id="MyToolWindow" factoryClass="dev.hgh.MyToolWindowFactory"
|
||||
icon="AllIcons.Toolwindows.ToolWindowPalette"/>
|
||||
<fileType
|
||||
name="Jai"
|
||||
implementationClass="dev.hgh.jai.JaiFileType"
|
||||
fieldName="INSTANCE"
|
||||
language="Jai"
|
||||
extensions="jai"/>
|
||||
</extensions>
|
||||
|
||||
</idea-plugin>
|
||||
|
||||
6
src/main/resources/icons/jai.svg
Normal file
6
src/main/resources/icons/jai.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<rect x="1" y="1" width="14" height="14" rx="3" fill="none" stroke="#3574F0" stroke-width="1.2"/>
|
||||
<path d="M6.2 4.2h1.5v5.1a2.4 2.4 0 0 1-2.4 2.4H5v-1.4h.2a1.1 1.1 0 0 0 1-1.1z" fill="#3574F0"/>
|
||||
<rect x="9.4" y="4.2" width="1.5" height="1.5" fill="#3574F0"/>
|
||||
<rect x="9.4" y="6.4" width="1.5" height="5.3" fill="#3574F0"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 422 B |
@@ -1,3 +0,0 @@
|
||||
toolwindow.stripe.MyToolWindow=My Tool Window
|
||||
toolwindow.MyToolWindow.number.label=The random number is: {0}
|
||||
toolwindow.MyToolWindow.shuffle.button=Shuffle
|
||||
25
src/test/kotlin/dev/hgh/jai/JaiFileTypeTest.kt
Normal file
25
src/test/kotlin/dev/hgh/jai/JaiFileTypeTest.kt
Normal file
@@ -0,0 +1,25 @@
|
||||
package dev.hgh.jai
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager
|
||||
import com.intellij.testFramework.fixtures.BasePlatformTestCase
|
||||
|
||||
/**
|
||||
* Verifies plugin.xml wiring: the `.jai` extension resolves to our file type and
|
||||
* our language, without launching an IDE.
|
||||
*/
|
||||
class JaiFileTypeTest : BasePlatformTestCase() {
|
||||
fun testJaiExtensionIsRegistered() {
|
||||
val type = FileTypeManager.getInstance().getFileTypeByExtension("jai")
|
||||
assertEquals(JaiFileType, type)
|
||||
}
|
||||
|
||||
/**
|
||||
* The *virtual* file already resolves to our type. The PSI file's language stays
|
||||
* plain text until a ParserDefinition is registered (phase 3) — asserting that here
|
||||
* would be asserting the platform's fallback, not our wiring.
|
||||
*/
|
||||
fun testVirtualFileUsesJaiFileType() {
|
||||
val file = myFixture.configureByText("sample.jai", "main :: () { }")
|
||||
assertEquals(JaiFileType, file.virtualFile.fileType)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user