mirror of
https://github.com/chylex/IntelliJ-Rainbow-Brackets.git
synced 2025-01-30 13:45:59 +01:00
Compare commits
3 Commits
02f46987b4
...
ad617451c7
Author | SHA1 | Date | |
---|---|---|---|
ad617451c7 | |||
0e379b3a45 | |||
92baf7cad5 |
@ -3,7 +3,8 @@ intellij {
|
|||||||
|
|
||||||
plugins.set(listOf(
|
plugins.set(listOf(
|
||||||
// Built-in
|
// Built-in
|
||||||
"cidr-base-plugin"
|
"cidr-base-plugin",
|
||||||
|
//"org.jetbrains.plugins.clion.radler" // Only in 2024.1 or newer. Worked around by only including the .xml file, and taking the implementation from Rider.
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
clion/src/main/resources/META-INF/cpp-nova-brackets.xml
Normal file
10
clion/src/main/resources/META-INF/cpp-nova-brackets.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<idea-plugin>
|
||||||
|
<extensions defaultExtensionNs="com.chylex.coloredbrackets">
|
||||||
|
<bracePairProvider language="C++"
|
||||||
|
implementationClass="com.chylex.intellij.coloredbrackets.provider.CppBracePairProvider" />
|
||||||
|
</extensions>
|
||||||
|
|
||||||
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
|
<highlightVisitor implementation="com.chylex.intellij.coloredbrackets.visitor.CppRainbowVisitor" />
|
||||||
|
</extensions>
|
||||||
|
</idea-plugin>
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.chylex.intellij.coloredbrackets.provider
|
||||||
|
|
||||||
|
import com.intellij.lang.BracePair
|
||||||
|
import com.jetbrains.rider.cpp.fileType.lexer.CppTokenTypes
|
||||||
|
|
||||||
|
class CppBracePairProvider : BracePairProvider {
|
||||||
|
override fun pairs(): List<BracePair> = listOf(
|
||||||
|
BracePair(CppTokenTypes.LPAR, CppTokenTypes.RPAR, false),
|
||||||
|
BracePair(CppTokenTypes.LBRACE, CppTokenTypes.RBRACE, false),
|
||||||
|
BracePair(CppTokenTypes.LBRACKET, CppTokenTypes.RBRACKET, false),
|
||||||
|
BracePair(CppTokenTypes.LT, CppTokenTypes.GT, false),
|
||||||
|
)
|
||||||
|
}
|
@ -2,130 +2,25 @@ package com.chylex.intellij.coloredbrackets.visitor
|
|||||||
|
|
||||||
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings
|
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings
|
||||||
import com.intellij.codeInsight.daemon.impl.HighlightVisitor
|
import com.intellij.codeInsight.daemon.impl.HighlightVisitor
|
||||||
import com.intellij.lang.BracePair
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
|
||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
import com.jetbrains.rider.languages.fileTypes.csharp.kotoparser.lexer.CSharpTokenType
|
import com.jetbrains.rider.languages.fileTypes.csharp.kotoparser.lexer.CSharpTokenType
|
||||||
import com.jetbrains.rider.languages.fileTypes.csharp.psi.CSharpDummyNode
|
import com.jetbrains.rider.languages.fileTypes.csharp.psi.CSharpDummyNode
|
||||||
|
|
||||||
class CSharpRainbowVisitor : RainbowHighlightVisitor() {
|
class CSharpRainbowVisitor : ReSharperRainbowVisitor("C#") {
|
||||||
|
|
||||||
override fun suitableForFile(file: PsiFile)
|
override fun suitableForFile(file: PsiFile): Boolean {
|
||||||
: Boolean = super.suitableForFile(file) &&
|
return super.suitableForFile(file) && RainbowSettings.instance.isEnableRainbowAngleBrackets
|
||||||
RainbowSettings.instance.isEnableRainbowAngleBrackets &&
|
}
|
||||||
(file.language.id == "C#" ||
|
|
||||||
file.viewProvider.allFiles.any { it.language.id == "C#" }
|
override fun isAllowedElementType(type: IElementType): Boolean {
|
||||||
)
|
return type == CSharpTokenType.LPARENTH || type == CSharpTokenType.RPARENTH
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun PsiElement.isDummyNode(): Boolean {
|
||||||
|
return this is CSharpDummyNode
|
||||||
|
}
|
||||||
|
|
||||||
override fun clone(): HighlightVisitor = CSharpRainbowVisitor()
|
override fun clone(): HighlightVisitor = CSharpRainbowVisitor()
|
||||||
|
|
||||||
override fun visit(element: PsiElement) {
|
|
||||||
val type = (element as? LeafPsiElement)?.elementType ?: return
|
|
||||||
val pair = map[type]
|
|
||||||
if (pair != null) {
|
|
||||||
val level = element.getBracketLevel(pair, type)
|
|
||||||
if (RainbowSettings.instance.isDoNOTRainbowifyTheFirstLevel) {
|
|
||||||
if (level >= 1) {
|
|
||||||
rainbowPairs(element, pair, level)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (level >= 0) {
|
|
||||||
rainbowPairs(element, pair, level)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun rainbowPairs(element: LeafPsiElement, pair: BracePair, level: Int) {
|
|
||||||
val startElement = element.takeIf { it.elementType == pair.leftBraceType }
|
|
||||||
val endElement = element.takeIf { it.elementType == pair.rightBraceType }
|
|
||||||
element.setHighlightInfo(element.parent, level, startElement, endElement)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val map = mapOf(
|
|
||||||
CSharpTokenType.LPARENTH to BracePair(CSharpTokenType.LPARENTH, CSharpTokenType.RPARENTH, true),
|
|
||||||
CSharpTokenType.RPARENTH to BracePair(CSharpTokenType.LPARENTH, CSharpTokenType.RPARENTH, true),
|
|
||||||
//LT to BracePair(LT, GT, true),
|
|
||||||
//GT to BracePair(LT, GT, true),
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun LeafPsiElement.getBracketLevel(pair: BracePair, type: IElementType): Int = iterateBracketParents(this, pair, -1, type)
|
|
||||||
|
|
||||||
private tailrec fun iterateBracketParents(element: PsiElement?, pair: BracePair, count: Int, type: IElementType): Int {
|
|
||||||
if (element == null || element is PsiFile) {
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
var nextCount = count
|
|
||||||
|
|
||||||
if (element is LeafPsiElement && type == pair.leftBraceType && element.elementType == pair.rightBraceType) {
|
|
||||||
nextCount--
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element is LeafPsiElement && type == pair.rightBraceType && element.elementType == pair.leftBraceType) {
|
|
||||||
nextCount--
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element is LeafPsiElement && element.elementType == type) {
|
|
||||||
nextCount++
|
|
||||||
}
|
|
||||||
|
|
||||||
return if (type == pair.leftBraceType) {
|
|
||||||
val prev = element.prevSibling
|
|
||||||
if (prev == null) {
|
|
||||||
iterateBracketParents(element.parent.prevSibling.iterForPreDummyNode()?.lastChild, pair, nextCount, type)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iterateBracketParents(prev, pair, nextCount, type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
val next = element.nextSibling
|
|
||||||
if (next == null) {
|
|
||||||
iterateBracketParents(element.parent.nextSibling.iterForNextDummyNode()?.firstChild, pair, nextCount, type)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iterateBracketParents(next, pair, nextCount, type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private tailrec fun PsiElement?.iterForNextDummyNode(): PsiElement? {
|
|
||||||
return if (this == null) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
else if (this is CSharpDummyNode) {
|
|
||||||
this
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (this.nextSibling == null) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.nextSibling.iterForNextDummyNode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private tailrec fun PsiElement?.iterForPreDummyNode(): PsiElement? {
|
|
||||||
return if (this == null) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
else if (this is CSharpDummyNode) {
|
|
||||||
this
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (this.prevSibling == null) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.prevSibling.iterForPreDummyNode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.chylex.intellij.coloredbrackets.visitor
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.daemon.impl.HighlightVisitor
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
import com.jetbrains.rider.cpp.fileType.lexer.CppTokenTypes
|
||||||
|
import com.jetbrains.rider.cpp.fileType.psi.CppDummyNode
|
||||||
|
|
||||||
|
class CppRainbowVisitor : ReSharperRainbowVisitor("C++") {
|
||||||
|
|
||||||
|
override fun clone(): HighlightVisitor = CppRainbowVisitor()
|
||||||
|
|
||||||
|
override fun isAllowedElementType(type: IElementType): Boolean {
|
||||||
|
return type == CppTokenTypes.LPAR || type == CppTokenTypes.RPAR
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun PsiElement.isDummyNode(): Boolean {
|
||||||
|
return this is CppDummyNode
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
package com.chylex.intellij.coloredbrackets.visitor
|
||||||
|
|
||||||
|
import com.chylex.intellij.coloredbrackets.bracePairs
|
||||||
|
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings
|
||||||
|
import com.intellij.lang.BracePair
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
import com.intellij.psi.util.elementType
|
||||||
|
|
||||||
|
abstract class ReSharperRainbowVisitor(private val languageId: String) : RainbowHighlightVisitor() {
|
||||||
|
|
||||||
|
override fun suitableForFile(file: PsiFile): Boolean {
|
||||||
|
return super.suitableForFile(file) && (file.language.id == languageId || file.viewProvider.allFiles.any { it.language.id == languageId })
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun isAllowedElementType(type: IElementType): Boolean
|
||||||
|
|
||||||
|
final override fun visit(element: PsiElement) {
|
||||||
|
val type = (element as? LeafPsiElement)?.elementType?.takeIf(::isAllowedElementType) ?: return
|
||||||
|
val pair = type.language.bracePairs?.getValue(type.toString())?.singleOrNull() ?: return
|
||||||
|
|
||||||
|
val settings = RainbowSettings.instance
|
||||||
|
|
||||||
|
if (settings.isDoNOTRainbowifyBracketsWithoutContent) {
|
||||||
|
if (pair.leftBraceType == type && element.nextSibling?.elementType == pair.rightBraceType) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pair.rightBraceType == type && element.prevSibling?.elementType == pair.leftBraceType) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val level = element.getBracketLevel(pair, type)
|
||||||
|
|
||||||
|
if (settings.isDoNOTRainbowifyTheFirstLevel) {
|
||||||
|
if (level >= 1) {
|
||||||
|
rainbowPairs(element, pair, level)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (level >= 0) {
|
||||||
|
rainbowPairs(element, pair, level)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rainbowPairs(element: LeafPsiElement, pair: BracePair, level: Int) {
|
||||||
|
val startElement = element.takeIf { it.elementType == pair.leftBraceType }
|
||||||
|
val endElement = element.takeIf { it.elementType == pair.rightBraceType }
|
||||||
|
element.setHighlightInfo(element.parent, level, startElement, endElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun LeafPsiElement.getBracketLevel(pair: BracePair, type: IElementType): Int {
|
||||||
|
return iterateBracketParents(this, pair, -1, type)
|
||||||
|
}
|
||||||
|
|
||||||
|
private tailrec fun iterateBracketParents(element: PsiElement?, pair: BracePair, count: Int, type: IElementType): Int {
|
||||||
|
if (element == null || element is PsiFile) {
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
var nextCount = count
|
||||||
|
|
||||||
|
if (element is LeafPsiElement) {
|
||||||
|
if (type == pair.leftBraceType && element.elementType == pair.rightBraceType) {
|
||||||
|
nextCount--
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == pair.rightBraceType && element.elementType == pair.leftBraceType) {
|
||||||
|
nextCount--
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == element.elementType) {
|
||||||
|
nextCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (type == pair.leftBraceType) {
|
||||||
|
val prev = element.prevSibling
|
||||||
|
if (prev == null) {
|
||||||
|
iterateBracketParents(element.parent.prevSibling.iterForPreDummyNode()?.lastChild, pair, nextCount, type)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
iterateBracketParents(prev, pair, nextCount, type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val next = element.nextSibling
|
||||||
|
if (next == null) {
|
||||||
|
iterateBracketParents(element.parent.nextSibling.iterForNextDummyNode()?.firstChild, pair, nextCount, type)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
iterateBracketParents(next, pair, nextCount, type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun PsiElement.isDummyNode(): Boolean
|
||||||
|
|
||||||
|
private tailrec fun PsiElement?.iterForNextDummyNode(): PsiElement? {
|
||||||
|
return when {
|
||||||
|
this == null -> null
|
||||||
|
this.isDummyNode() -> this
|
||||||
|
this.nextSibling == null -> null
|
||||||
|
else -> this.nextSibling.iterForNextDummyNode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private tailrec fun PsiElement?.iterForPreDummyNode(): PsiElement? {
|
||||||
|
return when {
|
||||||
|
this == null -> null
|
||||||
|
this.isDummyNode() -> this
|
||||||
|
this.prevSibling == null -> null
|
||||||
|
else -> this.prevSibling.iterForPreDummyNode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
rider/src/main/resources/META-INF/cpp-rider-brackets.xml
Normal file
10
rider/src/main/resources/META-INF/cpp-rider-brackets.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<idea-plugin>
|
||||||
|
<extensions defaultExtensionNs="com.chylex.coloredbrackets">
|
||||||
|
<bracePairProvider language="C++"
|
||||||
|
implementationClass="com.chylex.intellij.coloredbrackets.provider.CppBracePairProvider" />
|
||||||
|
</extensions>
|
||||||
|
|
||||||
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
|
<highlightVisitor implementation="com.chylex.intellij.coloredbrackets.visitor.CppRainbowVisitor" />
|
||||||
|
</extensions>
|
||||||
|
</idea-plugin>
|
@ -69,12 +69,12 @@ object BracePairs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
language.displayName to braceMap
|
language.id to braceMap
|
||||||
}
|
}
|
||||||
.toMap()
|
.toMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBracePairs(language: Language): MutableMap<String, MutableList<BracePair>>? = bracePairs.value[language.displayName]
|
fun getBracePairs(language: Language): MutableMap<String, MutableList<BracePair>>? = bracePairs.value[language.id]
|
||||||
|
|
||||||
private fun getBraceTypeSetOf(language: Language): Set<IElementType> = getBracePairs(language)?.values?.flatten()?.map { listOf(it.leftBraceType, it.rightBraceType) }?.flatten()?.toSet() ?: emptySet()
|
private fun getBraceTypeSetOf(language: Language): Set<IElementType> = getBracePairs(language)?.values?.flatten()?.map { listOf(it.leftBraceType, it.rightBraceType) }?.flatten()?.toSet() ?: emptySet()
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@ abstract class RainbowHighlightVisitor : HighlightVisitor {
|
|||||||
onBeforeAnalyze(file, updateWholeFile)
|
onBeforeAnalyze(file, updateWholeFile)
|
||||||
try {
|
try {
|
||||||
action.run()
|
action.run()
|
||||||
} catch (e: Throwable) {
|
|
||||||
} finally {
|
} finally {
|
||||||
onAfterAnalyze()
|
onAfterAnalyze()
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,8 @@
|
|||||||
<depends optional="true" config-file="JSX.xml">JavaScript</depends>
|
<depends optional="true" config-file="JSX.xml">JavaScript</depends>
|
||||||
<depends optional="true" config-file="dart-brackets.xml">Dart</depends>
|
<depends optional="true" config-file="dart-brackets.xml">Dart</depends>
|
||||||
<depends optional="true" config-file="groovy-brackets.xml">org.intellij.groovy</depends>
|
<depends optional="true" config-file="groovy-brackets.xml">org.intellij.groovy</depends>
|
||||||
<!--<depends optional="true" config-file="csharp-annotator.xml">com.intellij.modules.rider</depends>-->
|
<depends optional="true" config-file="cpp-nova-brackets.xml">org.jetbrains.plugins.clion.radler</depends>
|
||||||
|
<depends optional="true" config-file="cpp-rider-brackets.xml">com.intellij.modules.rider</depends>
|
||||||
<depends optional="true" config-file="csharp-brackets.xml">com.intellij.modules.rider</depends>
|
<depends optional="true" config-file="csharp-brackets.xml">com.intellij.modules.rider</depends>
|
||||||
<depends optional="true" config-file="intellij-haskell-annotator.xml">intellij.haskell</depends>
|
<depends optional="true" config-file="intellij-haskell-annotator.xml">intellij.haskell</depends>
|
||||||
<depends optional="true" config-file="sql-brackets.xml">com.intellij.database</depends>
|
<depends optional="true" config-file="sql-brackets.xml">com.intellij.database</depends>
|
||||||
|
Loading…
Reference in New Issue
Block a user