1 Commits
Author SHA1 Message Date
chylex 201b6e1f3a Fork Rainbow Brackets 6.26 2024-11-30 16:50:15 +01:00
120 changed files with 2016 additions and 1958 deletions
-3
View File
@@ -1,8 +1,5 @@
/.idea/* /.idea/*
!/.idea/dictionaries
!/.idea/runConfigurations !/.idea/runConfigurations
/.gradle/ /.gradle/
/.kotlin/
/.intellijPlatform/
/build/ /build/
-7
View File
@@ -1,7 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="project">
<words>
<w>Rainbowify</w>
</words>
</dictionary>
</component>
-27
View File
@@ -1,27 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run CLion" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":clion:runIde" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<GradleProfilingDisabled>false</GradleProfilingDisabled>
<GradleCoverageDisabled>false</GradleCoverageDisabled>
<method v="2" />
</configuration>
</component>
-27
View File
@@ -1,27 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run IDEA" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":base:runIde" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<GradleProfilingDisabled>false</GradleProfilingDisabled>
<GradleCoverageDisabled>false</GradleCoverageDisabled>
<method v="2" />
</configuration>
</component>
-27
View File
@@ -1,27 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Rider" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":rider:runIde" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<GradleProfilingDisabled>false</GradleProfilingDisabled>
<GradleCoverageDisabled>false</GradleCoverageDisabled>
<method v="2" />
</configuration>
</component>
Generated
+24
View File
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CommitMessageInspectionProfile">
<profile version="1.0">
<inspection_tool class="GrazieCommit" enabled="true" level="TYPO" enabled_by_default="true"/>
</profile>
</component>
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git"/>
</component>
<component name="IssueNavigationConfiguration">
<option name="links">
<list>
<IssueNavigationLink>
<option name="issueRegexp" value="#(\d+)"/>
<option name="linkRegexp" value="https://github.com//izhangzhihao/intellij-rainbow-brackets/issues/$1"/>
</IssueNavigationLink>
</list>
</option>
</component>
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git"/>
</component>
</project>
-9
View File
@@ -1,12 +1,3 @@
# Colored Brackets # Colored Brackets
This is a fork of the [🌈Rainbow Brackets](https://github.com/izhangzhihao/intellij-rainbow-brackets) plugin by [izhangzhihao](https://github.com/izhangzhihao), based on version 6.26. This is a fork of the [🌈Rainbow Brackets](https://github.com/izhangzhihao/intellij-rainbow-brackets) plugin by [izhangzhihao](https://github.com/izhangzhihao), based on version 6.26.
## Key Changes
- Updates for new IntelliJ Platform versions
- Support for C# (Rider)
- Support for C++
- Support for Settings Sync
- Improved highlighting performance
- Increased default setting for maximum line count from 1K to 100K
-44
View File
@@ -1,44 +0,0 @@
import org.jetbrains.intellij.platform.gradle.TestFrameworkType
import org.jetbrains.intellij.platform.gradle.extensions.excludeCoroutines
import org.jetbrains.intellij.platform.gradle.extensions.excludeKotlinStdlib
val ideaVersion: String by project
dependencies {
intellijPlatform {
@Suppress("DEPRECATION")
intellijIdeaUltimate(ideaVersion)
bundledPlugin("JavaScript")
bundledPlugin("com.intellij.css")
bundledPlugin("com.intellij.database")
bundledPlugin("com.intellij.java")
bundledPlugin("org.intellij.groovy")
bundledPlugin("org.intellij.plugins.markdown")
bundledPlugin("org.jetbrains.kotlin")
bundledPlugin("org.jetbrains.plugins.yaml")
compatiblePlugin("PythonCore")
compatiblePlugin("com.intellij.clion")
compatiblePlugin("com.intellij.nativeDebug")
compatiblePlugin("com.jetbrains.php")
compatiblePlugin("com.jetbrains.plugins.jade")
compatiblePlugin("com.jetbrains.sh")
compatiblePlugin("org.intellij.scala")
compatiblePlugin("org.jetbrains.plugins.clion.radler")
compatiblePlugin("org.jetbrains.plugins.go-template")
compatiblePlugin("org.jetbrains.plugins.ruby")
plugin("Dart:507.0.0") // https://plugins.jetbrains.com/plugin/6351-dart/versions/stable
testFramework(TestFrameworkType.Platform)
testFramework(TestFrameworkType.Plugin.Java)
testFramework(TestFrameworkType.Plugin.JavaScript)
}
testImplementation("junit:junit:4.13.2")
testImplementation("io.kotest:kotest-assertions-core:5.8.0") {
excludeKotlinStdlib()
excludeCoroutines()
}
}
@@ -1,33 +0,0 @@
package com.chylex.intellij.coloredbrackets.action
import com.chylex.intellij.coloredbrackets.RainbowHighlighter
import com.chylex.intellij.coloredbrackets.RainbowInfo
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings
import com.intellij.codeInsight.highlighting.HighlightManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.markup.RangeHighlighter
import java.util.LinkedList
class ScopeHighlightingAction : AbstractScopeHighlightingAction() {
override fun Editor.addHighlighter(
editor: Editor,
highlightManager: HighlightManager,
rainbowInfo: RainbowInfo,
): Collection<RangeHighlighter> {
val attributesKey = RainbowHighlighter.updateScopeHighlightingAttributes(editor.colorsScheme, rainbowInfo)
val highlighters = LinkedList<RangeHighlighter>()
highlightManager.addRangeHighlight(
this,
rainbowInfo.startOffset,
rainbowInfo.endOffset,
attributesKey,
false,
RainbowSettings.instance.pressAnyKeyToRemoveTheHighlightingEffects,
highlighters
)
return highlighters
}
}
@@ -1,52 +0,0 @@
package com.chylex.intellij.coloredbrackets.action
import com.chylex.intellij.coloredbrackets.RainbowHighlighter
import com.chylex.intellij.coloredbrackets.RainbowInfo
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings
import com.intellij.codeInsight.highlighting.HighlightManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.markup.RangeHighlighter
import java.util.LinkedList
class ScopeOutsideHighlightingRestrainAction : AbstractScopeHighlightingAction() {
override fun Editor.addHighlighter(
editor: Editor,
highlightManager: HighlightManager,
rainbowInfo: RainbowInfo,
): Collection<RangeHighlighter> {
val attributesKey = RainbowHighlighter.updateScopeOutsideHighlightingAttributes(editor.colorsScheme)
val highlighters = LinkedList<RangeHighlighter>()
val startOffset = rainbowInfo.startOffset
val hideByAnyKey = RainbowSettings.instance.pressAnyKeyToRemoveTheHighlightingEffects
if (startOffset > 0) {
highlightManager.addRangeHighlight(
this,
0,
startOffset,
attributesKey,
false,
hideByAnyKey,
highlighters
)
}
val endOffset = rainbowInfo.endOffset
val lastOffset = document.textLength
if (endOffset < lastOffset) {
highlightManager.addRangeHighlight(
this,
endOffset,
lastOffset,
attributesKey,
false,
hideByAnyKey,
highlighters
)
}
return highlighters
}
}
@@ -1,13 +0,0 @@
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),
)
}
@@ -1,20 +0,0 @@
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
}
}
@@ -1,217 +0,0 @@
package com.chylex.intellij.coloredbrackets.visitor
import com.chylex.intellij.coloredbrackets.BracePairs.bracePairs
import com.chylex.intellij.coloredbrackets.BracePairs.braceTypeSet
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings
import com.intellij.codeInsight.daemon.impl.HighlightVisitor
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 it.unimi.dsi.fastutil.objects.Object2ByteOpenHashMap
class DefaultRainbowVisitor : RainbowHighlightVisitor() {
override fun clone(): HighlightVisitor = DefaultRainbowVisitor()
private var processor: Processor? = null
override fun onBeforeAnalyze(file: PsiFile, updateWholeFile: Boolean) {
processor = Processor(RainbowSettings.instance)
}
override fun visit(element: PsiElement) {
val type = (element as? LeafPsiElement)?.elementType ?: return
val processor = processor!!
val matching = processor.filterPairs(type, element) ?: return
val pair = when (matching.size) {
1 -> matching[0]
else -> matching.find { processor.isValidBracket(element, it) } ?: return
}
val level = processor.getBracketLevel(element, pair)
if (processor.settings.isDoNOTRainbowifyTheFirstLevel) {
if (level >= 1) {
rainbowPairs(element, pair, level)
}
}
else {
if (level >= 0) {
rainbowPairs(element, pair, level)
}
}
}
override fun onAfterAnalyze() {
processor = null
}
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 class Processor(val settings: RainbowSettings) {
private companion object {
private const val CACHE_MISS = (-1).toByte()
}
private data class HasBracketsCacheKey(val element: PsiElement, val pair: BracePair) {
private val hashCode = (31 * System.identityHashCode(element)) + System.identityHashCode(pair)
override fun equals(other: Any?): Boolean {
return other is HasBracketsCacheKey && element === other.element && pair === other.pair
}
override fun hashCode(): Int {
return hashCode
}
}
private val hasBracketsCache = Object2ByteOpenHashMap<HasBracketsCacheKey>().apply { defaultReturnValue(CACHE_MISS) }
fun getBracketLevel(element: LeafPsiElement, pair: BracePair): Int = iterateBracketParents(element.parent, pair, -1)
private tailrec fun iterateBracketParents(element: PsiElement?, pair: BracePair, count: Int): Int {
if (element == null || element is PsiFile) {
return count
}
var nextCount = count
if (!settings.cycleCountOnAllBrackets) {
if (element.hasBrackets(
pair,
{ it.elementType == pair.leftBraceType },
{ it.elementType == pair.rightBraceType })
) {
nextCount++
}
}
else {
if (element.hasBrackets(
pair,
{ element.language.braceTypeSet.contains(it.elementType) },
{ element.language.braceTypeSet.contains(it.elementType) })
) {
nextCount++
}
}
return iterateBracketParents(element.parent, pair, nextCount)
}
private inline fun PsiElement.hasBrackets(
pair: BracePair,
checkLeft: (LeafPsiElement) -> Boolean,
checkRight: (LeafPsiElement) -> Boolean,
): Boolean {
if (this is LeafPsiElement) {
return false
}
val cacheKey = HasBracketsCacheKey(this, pair)
val cacheValue = hasBracketsCache.getByte(cacheKey)
if (cacheValue != CACHE_MISS) {
return cacheValue == 1.toByte()
}
val hasBrackets = run {
var findLeftBracket = false
var findRightBracket = false
var left: PsiElement? = firstChild
var right: PsiElement? = lastChild
while (left != right && (!findLeftBracket || !findRightBracket)) {
val needBreak = left == null || left.nextSibling == right
if (left is LeafPsiElement && checkLeft(left)) {
findLeftBracket = true
}
else {
left = left?.nextSibling
}
if (right is LeafPsiElement && checkRight(right)) {
findRightBracket = true
}
else {
right = right?.prevSibling
}
if (needBreak) {
break
}
}
// For https://github.com/izhangzhihao/intellij-rainbow-brackets/issues/830
if (settings.doNOTRainbowifyTemplateString && left?.prevSibling?.textMatches("$") == true) {
false
}
else {
findLeftBracket && findRightBracket
}
}
hasBracketsCache.put(cacheKey, if (hasBrackets) 1.toByte() else 0.toByte())
return hasBrackets
}
fun isValidBracket(element: LeafPsiElement, pair: BracePair): Boolean {
val pairType = when (element.elementType) {
pair.leftBraceType -> pair.rightBraceType
pair.rightBraceType -> pair.leftBraceType
else -> return false
}
return if (pairType == pair.leftBraceType) {
checkBracePair(element, element.parent.firstChild, pairType, PsiElement::getNextSibling)
}
else {
checkBracePair(element, element.parent.lastChild, pairType, PsiElement::getPrevSibling)
}
}
private fun checkBracePair(
brace: PsiElement,
start: PsiElement,
type: IElementType,
next: PsiElement.() -> PsiElement?,
): Boolean {
var element: PsiElement? = start
while (element != null && element != brace) {
if (element is LeafPsiElement && element.elementType == type) {
return true
}
element = element.next()
}
return false
}
fun filterPairs(type: IElementType, element: LeafPsiElement): List<BracePair>? {
val pairs = element.language.bracePairs ?: return null
val filterBraceType = pairs[type.toString()]
return when {
filterBraceType.isNullOrEmpty() -> null
// https://github.com/izhangzhihao/intellij-rainbow-brackets/issues/198
element.javaClass.simpleName == "OCMacroForeignLeafElement" -> null
settings.isDoNOTRainbowifyBracketsWithoutContent -> filterBraceType
.filterNot { it.leftBraceType == type && element.nextSibling?.elementType() == it.rightBraceType }
.filterNot { it.rightBraceType == type && element.prevSibling?.elementType() == it.leftBraceType }
else -> filterBraceType
}
}
private fun PsiElement.elementType(): IElementType? {
return (this as? LeafPsiElement)?.elementType
}
}
}
@@ -1,120 +0,0 @@
package com.chylex.intellij.coloredbrackets.visitor
import com.chylex.intellij.coloredbrackets.BracePairs.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()
}
}
}
@@ -1,10 +0,0 @@
<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>
@@ -1,5 +0,0 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<highlightVisitor implementation="com.chylex.intellij.coloredbrackets.visitor.PugRainbowVisitor" />
</extensions>
</idea-plugin>
@@ -1,9 +0,0 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<highlightVisitor implementation="com.chylex.intellij.coloredbrackets.visitor.ReactJSXRainbowVisitor" />
</extensions>
<extensions defaultExtensionNs="com.chylex.coloredbrackets">
<bracePairProvider language="JavaScript"
implementationClass="com.chylex.intellij.coloredbrackets.provider.TSBracePairProvider" />
</extensions>
</idea-plugin>
@@ -1,12 +0,0 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<annotator language="kotlin"
implementationClass="com.chylex.intellij.coloredbrackets.annotator.KotlinLambdaExpressionArrowAnnotator" />
<annotator language="kotlin"
implementationClass="com.chylex.intellij.coloredbrackets.annotator.KotlinLabelAnnotator" />
</extensions>
<extensions defaultExtensionNs="com.chylex.coloredbrackets">
<bracePairProvider language="kotlin"
implementationClass="com.chylex.intellij.coloredbrackets.provider.KotlinBracePairProvider" />
</extensions>
</idea-plugin>
@@ -1,5 +0,0 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<highlightVisitor implementation="com.chylex.intellij.coloredbrackets.visitor.PythonRainbowVisitor" />
</extensions>
</idea-plugin>
-118
View File
@@ -1,118 +0,0 @@
<idea-plugin require-restart="true">
<id>com.chylex.coloredbrackets</id>
<name>Colored Brackets</name>
<vendor url="https://chylex.com">chylex</vendor>
<description><![CDATA[
Fork of the <a href="https://github.com/izhangzhihao/intellij-rainbow-brackets">Rainbow Brackets</a> plugin by <a href="https://github.com/izhangzhihao">izhangzhihao</a>, based on version 6.26.
<br><br>
<b>Key Changes</b>
<ul>
<li>Updates for new IntelliJ Platform versions</li>
<li>Support for C# (Rider)</li>
<li>Support for C++</li>
<li>Support for Settings Sync</li>
<li>Improved highlighting performance</li>
<li>Increased default setting for maximum line count from 1K to 100K</li>
</ul>
]]></description>
<change-notes><![CDATA[
<b>Version 1.5.0</b>
<ul>
<li>Updated to IntelliJ Platform 2026.2.</li>
<li>Added support for C++ plugin for IntelliJ IDEA.</li>
</ul>
<b>Version 1.4.0</b>
<ul>
<li>Updated to IntelliJ Platform 2025.3.</li>
<li>Removed support for the Haskell plugin, since it is no longer available.</li>
</ul>
<b>Version 1.3.0</b>
<ul>
<li>Fixed assertion error caused by missing read lock in indent guide renderer.</li>
</ul>
<b>Version 1.2.0</b>
<ul>
<li>Fixed not re-highlighting open files after changing settings.</li>
<li>Fixed exception when opening certain diff editors.</li>
</ul>
<b>Version 1.1.0</b>
<ul>
<li>Added support for C++ in Rider and CLion Nova.</li>
<li>Fixed broken option to not color parentheses without content in C#.</li>
<li>Improved highlighting performance.</li>
<li>Increased default setting for maximum line count from 1K to 100K.</li>
</ul>
<b>Version 1.0.0</b>
<ul>
<li>Restored support for CLion and Rider.</li>
<li>Added support for Settings Sync.</li>
<li>Fixed service initialization warnings reported by IntelliJ Platform 2024.2.</li>
</ul>
]]></change-notes>
<depends>com.intellij.modules.lang</depends>
<depends optional="true" config-file="plugin-clion-classic.xml">com.intellij.cidr.lang</depends>
<depends optional="true" config-file="plugin-cpp.xml">org.jetbrains.plugins.clion.radler</depends>
<depends optional="true" config-file="plugin-dart.xml">Dart</depends>
<depends optional="true" config-file="plugin-go-template.xml">org.jetbrains.plugins.go-template</depends>
<depends optional="true" config-file="plugin-groovy.xml">org.intellij.groovy</depends>
<depends optional="true" config-file="plugin-jade.xml">com.jetbrains.plugins.jade</depends>
<depends optional="true" config-file="plugin-javascript.xml">JavaScript</depends>
<depends optional="true" config-file="plugin-kotlin.xml">org.jetbrains.kotlin</depends>
<depends optional="true" config-file="plugin-php.xml">com.jetbrains.php</depends>
<depends optional="true" config-file="plugin-python.xml">com.intellij.modules.python</depends>
<depends optional="true" config-file="plugin-rider.xml">com.intellij.modules.rider</depends>
<depends optional="true" config-file="plugin-sh.xml">com.jetbrains.sh</depends>
<depends optional="true" config-file="plugin-sql.xml">com.intellij.database</depends>
<extensionPoints>
<extensionPoint name="bracePairProvider" beanClass="com.intellij.lang.LanguageExtensionPoint" dynamic="true">
<with attribute="implementationClass" implements="com.chylex.intellij.coloredbrackets.provider.BracePairProvider" />
</extensionPoint>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
<highlightVisitor implementation="com.chylex.intellij.coloredbrackets.visitor.DefaultRainbowVisitor" />
<highlightVisitor implementation="com.chylex.intellij.coloredbrackets.visitor.XmlRainbowVisitor" />
<applicationConfigurable instance="com.chylex.intellij.coloredbrackets.settings.RainbowConfigurable" displayName="Colored Brackets" parentId="appearance" />
<applicationService serviceImplementation="com.chylex.intellij.coloredbrackets.settings.RainbowSettings" />
<colorAndFontPanelFactory implementation="com.chylex.intellij.coloredbrackets.settings.RainbowColorsPageFactory" />
<colorAndFontDescriptorProvider implementation="com.chylex.intellij.coloredbrackets.settings.RainbowColorsPageFactory" />
<additionalTextAttributes scheme="Default" file="colorSchemes/rainbow-color-default.xml" />
<additionalTextAttributes scheme="Darcula" file="colorSchemes/rainbow-color-default-darcula.xml" />
<highlightingPassFactory implementation="com.chylex.intellij.coloredbrackets.indents.RainbowIndentsPassFactory" />
<editorNotificationProvider implementation="com.chylex.intellij.coloredbrackets.RainbowifyBanner" />
</extensions>
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<supportsKotlinPluginMode supportsK2="true" />
</extensions>
<applicationListeners>
<listener class="com.chylex.intellij.coloredbrackets.listener.RainbowColorsSchemeListener" topic="com.intellij.openapi.editor.colors.EditorColorsListener" />
</applicationListeners>
<actions>
<action class="com.chylex.intellij.coloredbrackets.action.ScopeHighlightingAction"
id="Rainbow.ScopeHighlightingAction"
text="Highlight Current Scope"
description="Highlight current scope.">
<mouse-shortcut keymap="$default" keystroke="control button3" />
<mouse-shortcut keymap="Mac OS X" keystroke="meta button3" />
<mouse-shortcut keymap="Mac OS X 10.5+" keystroke="meta button3" />
</action>
<action class="com.chylex.intellij.coloredbrackets.action.ScopeOutsideHighlightingRestrainAction"
id="Rainbow.ScopeOutsideHighlightingRestrainAction"
text="Restrain Scope Highlighting"
description="Restrain outside of current scope highlighting.">
<mouse-shortcut keymap="$default" keystroke="alt button3" />
<mouse-shortcut keymap="Mac OS X" keystroke="alt button3" />
<mouse-shortcut keymap="Mac OS X 10.5+" keystroke="alt button3" />
</action>
</actions>
</idea-plugin>
@@ -1,219 +0,0 @@
package com.chylex.intellij.coloredbrackets
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.lang.javascript.JSXFileType
import com.intellij.lang.javascript.JavaScriptFileType
import com.intellij.lang.javascript.TypeScriptFileType
import com.intellij.openapi.extensions.PluginId
import com.intellij.psi.PsiDocumentManager
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
import io.kotest.matchers.shouldBe
import org.intellij.lang.annotations.Language
class RainbowJavaScriptTest : LightJavaCodeInsightFixtureTestCase() {
fun testJavaScriptPluginEnabled() {
assertTrue(PluginManagerCore.isLoaded(PluginId("JavaScript")))
}
fun testIssue11() {
@Language("JavaScript") val code = """
"use strict";
const _ = require('lodash') || false
const moment = require('moment')
""".trimIndent()
myFixture.configureByText(JavaScriptFileType, code)
PsiDocumentManager.getInstance(project).commitAllDocuments()
val doHighlighting = myFixture.doHighlighting()
assertFalse(doHighlighting.isEmpty())
doHighlighting.getBrackets().shouldBe(
arrayOf(
roundLevel(0),
roundLevel(0),
roundLevel(0),
roundLevel(0)
)
)
}
fun testIssue12() {
@Language("JavaScript") val code = """
"use strict";
console.log(a > b)
console.log(a == b)
""".trimIndent()
myFixture.configureByText(JavaScriptFileType, code)
PsiDocumentManager.getInstance(project).commitAllDocuments()
val doHighlighting = myFixture.doHighlighting()
assertFalse(doHighlighting.isEmpty())
doHighlighting.getBrackets().shouldBe(
arrayOf(
roundLevel(0),
roundLevel(0),
roundLevel(0),
roundLevel(0)
)
)
}
fun testIssue21() {
@Language("JavaScript") val code = $$"open (${f})\nopen (${f} )"
myFixture.configureByText(JavaScriptFileType, code)
PsiDocumentManager.getInstance(project).commitAllDocuments()
val doHighlighting = myFixture.doHighlighting()
assertFalse(doHighlighting.isEmpty())
doHighlighting.getBrackets().shouldBe(
arrayOf(
roundLevel(0),
roundLevel(0),
roundLevel(0),
roundLevel(0)
)
)
}
fun testIssue23() {
@Language("JavaScript") val code = """
"use strict";
var a;
if ((a.field_detail && a.is) ||
(a.field_detail && a.is) ||
(a.field_detail && a.is) ||
(a.field_detail && a.is) ||
(a.field_detail && a.is) ||
(a.field_detail && a.is) ||
(a.field_detail && a.is)
) ;
""".trimIndent()
myFixture.configureByText(JavaScriptFileType, code)
PsiDocumentManager.getInstance(project).commitAllDocuments()
val doHighlighting = myFixture.doHighlighting()
assertFalse(doHighlighting.isEmpty())
doHighlighting.getBrackets().shouldBe(
arrayOf(
roundLevel(0),
roundLevel(1),
roundLevel(1),
roundLevel(1),
roundLevel(1),
roundLevel(1),
roundLevel(1),
roundLevel(1),
roundLevel(1),
roundLevel(1),
roundLevel(1),
roundLevel(1),
roundLevel(1),
roundLevel(1),
roundLevel(1),
roundLevel(0)
)
)
}
fun testIssue38() {
@Language("JavaScript") val code = """
const element = ( <div> <h1>Hello, world!</h1> </div> );
""".trimIndent()
myFixture.configureByText(JSXFileType, code)
PsiDocumentManager.getInstance(project).commitAllDocuments()
val doHighlighting = myFixture.doHighlighting()
assertFalse(doHighlighting.isEmpty())
doHighlighting.getBrackets().shouldBe(
arrayOf(
roundLevel(0),
angleLevel(0),
angleLevel(0),
angleLevel(1),
angleLevel(1),
angleLevel(1),
angleLevel(1),
angleLevel(0),
angleLevel(0),
roundLevel(0)
)
)
}
fun testIssue39() {
@Language("JavaScript") val code = """
const html = '<div><div><div>Hello</div></div></div>'
""".trimIndent()
myFixture.configureByText(JavaScriptFileType, code)
PsiDocumentManager.getInstance(project).commitAllDocuments()
val doHighlighting = myFixture.doHighlighting()
assertFalse(doHighlighting.isEmpty())
doHighlighting.getBrackets().shouldBe(
arrayOf(
angleLevel(0),
angleLevel(0),
angleLevel(1),
angleLevel(1),
angleLevel(2),
angleLevel(2),
angleLevel(2),
angleLevel(2),
angleLevel(1),
angleLevel(1),
angleLevel(0),
angleLevel(0)
)
)
}
fun testIssue31() {
@Language("JavaScript") val code = """
"use strict";
const f = () => {}
const a = [1,2,3]
const s = `<ololo>`
""".trimIndent()
myFixture.configureByText(TypeScriptFileType, code)
PsiDocumentManager.getInstance(project).commitAllDocuments()
val doHighlighting = myFixture.doHighlighting()
assertFalse(doHighlighting.isEmpty())
doHighlighting.getBrackets().shouldBe(
arrayOf(
roundLevel(0),
roundLevel(0),
squigglyLevel(0),
squigglyLevel(0),
squareLevel(0),
squareLevel(0),
angleLevel(0),
angleLevel(0)
)
)
}
fun testIssue427() {
@Language("TypeScript") val code = """let example: Array<Map<string,string>>;""".trimIndent()
myFixture.configureByText(TypeScriptFileType, code)
PsiDocumentManager.getInstance(project).commitAllDocuments()
val doHighlighting = myFixture.doHighlighting()
assertFalse(doHighlighting.isEmpty())
doHighlighting.getBrackets().shouldBe(
arrayOf(
angleLevel(0),
angleLevel(1),
angleLevel(1),
angleLevel(0)
)
)
}
}
@@ -1,134 +0,0 @@
package com.chylex.intellij.coloredbrackets
import com.intellij.psi.PsiDocumentManager
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
import io.kotest.matchers.shouldBe
import org.intellij.lang.annotations.Language
import org.jetbrains.kotlin.idea.KotlinFileType
class RainbowKotlinTest : LightJavaCodeInsightFixtureTestCase() {
fun testRainbowForKotlin() {
@Language("kotlin") val code =
"""
fun <T> filter(l: List<T>, f: (T) -> Boolean): MutableList<T> {
val res = mutableListOf<T>()
l.forEach { if (f(it)) { res += it } }
return res
}
""".trimIndent()
myFixture.configureByText(KotlinFileType.INSTANCE, code)
PsiDocumentManager.getInstance(project).commitAllDocuments()
val doHighlighting = myFixture.doHighlighting()
assertFalse(doHighlighting.isEmpty())
doHighlighting.getBrackets().shouldBe(
arrayOf(
angleLevel(0),
angleLevel(0),
roundLevel(0),
angleLevel(0),
angleLevel(0),
roundLevel(1),
roundLevel(1),
roundLevel(0),
angleLevel(0),
angleLevel(0),
squigglyLevel(0),
angleLevel(0),
angleLevel(0),
roundLevel(0),
roundLevel(0),
squigglyLevel(1),
roundLevel(0),
roundLevel(1),
roundLevel(1),
roundLevel(0),
squigglyLevel(2),
squigglyLevel(2),
squigglyLevel(1),
squigglyLevel(0)
)
)
}
fun testRainbowArrowForKotlin() {
@Language("kotlin") val code =
"""
val a: (Int) -> Unit = { aa ->
val b: (Int) -> Unit = { bb ->
val c: (Int) -> Unit = { cc ->
val d: (Int) -> Unit = { dd ->
}
}
}
}
""".trimIndent()
myFixture.configureByText(KotlinFileType.INSTANCE, code)
PsiDocumentManager.getInstance(project).commitAllDocuments()
val doHighlighting = myFixture.doHighlighting()
assertFalse(doHighlighting.isEmpty())
doHighlighting.getBrackets().shouldBe(
arrayOf(
roundLevel(0),
roundLevel(0),
squigglyLevel(0),
roundLevel(0),
roundLevel(0),
squigglyLevel(1),
roundLevel(0),
roundLevel(0),
squigglyLevel(2),
roundLevel(0),
roundLevel(0),
squigglyLevel(3),
squigglyLevel(3),
squigglyLevel(2),
squigglyLevel(1),
squigglyLevel(0)
)
)
}
fun testKotlinFunctionLiteralBracesAndArrow() {
@Language("kotlin") val code =
"""
val a :Int = 1
fun t() {
a?.let {
}
}
""".trimIndent()
myFixture.configureByText(KotlinFileType.INSTANCE, code)
PsiDocumentManager.getInstance(project).commitAllDocuments()
val doHighlighting = myFixture.doHighlighting()
assertFalse(doHighlighting.isEmpty())
doHighlighting.getBrackets().shouldBe(
arrayOf(
roundLevel(0),
roundLevel(0),
squigglyLevel(0),
squigglyLevel(1),
squigglyLevel(1),
squigglyLevel(0)
)
)
}
}
@@ -1,71 +0,0 @@
package com.chylex.intellij.coloredbrackets
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings
import com.intellij.ide.highlighter.XmlFileType
import com.intellij.psi.PsiDocumentManager
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
import io.kotest.matchers.shouldBe
import org.intellij.lang.annotations.Language
class RainbowXMLTest : LightJavaCodeInsightFixtureTestCase() {
fun testRainbowForXML() {
@Language("XML") val code =
"""
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note SYSTEM>
<idea-plugin>
<name>Rainbow Brackets</name>
<description>
<p>Supported languages:</p>
<p>Java, Scala, Clojure, Kotlin, Python, Haskell, Agda, Rust, JavaScript, TypeScript, Erlang, Go, Groovy, Ruby, Elixir, ObjectiveC, PHP, C#, HTML, XML, SQL, Apex language ...</p>
<br/>
</description>
</idea-plugin>
""".trimIndent()
val rainbowSettings = RainbowSettings.instance
rainbowSettings.rainbowifyTagNameInXML = false
myFixture.configureByText(XmlFileType.INSTANCE, code)
PsiDocumentManager.getInstance(project).commitAllDocuments()
val doHighlighting = myFixture.doHighlighting()
assertFalse(doHighlighting.isEmpty())
doHighlighting.getBrackets().shouldBe(
arrayOf(
angleLevel(0),
angleLevel(0),
angleLevel(0),
angleLevel(0),
angleLevel(0),
angleLevel(0),
angleLevel(1),
angleLevel(1),
angleLevel(1),
angleLevel(1),
angleLevel(1),
angleLevel(1),
angleLevel(2),
angleLevel(2),
angleLevel(2),
angleLevel(2),
angleLevel(2),
angleLevel(2),
angleLevel(2),
angleLevel(2),
angleLevel(2),
angleLevel(2),
angleLevel(1),
angleLevel(1),
angleLevel(0),
angleLevel(0)
)
)
}
}
@@ -1,20 +0,0 @@
package com.chylex.intellij.coloredbrackets
import com.chylex.intellij.coloredbrackets.visitor.RainbowHighlightVisitor
import com.intellij.codeInsight.daemon.impl.HighlightInfo
import java.awt.Color
fun List<HighlightInfo>.getBrackets(): Array<Color> {
return this
.filter { it.toolId?.let { id -> id is Class<*> && RainbowHighlightVisitor::class.java.isAssignableFrom(id) } == true }
.map { it.forcedTextAttributesKey.defaultAttributes.foregroundColor }
.toTypedArray()
}
fun roundLevel(level: Int) = RainbowHighlighter.getRainbowColor(RainbowHighlighter.NAME_ROUND_BRACKETS, level)
fun squigglyLevel(level: Int) = RainbowHighlighter.getRainbowColor(RainbowHighlighter.NAME_SQUIGGLY_BRACKETS, level)
fun angleLevel(level: Int) = RainbowHighlighter.getRainbowColor(RainbowHighlighter.NAME_ANGLE_BRACKETS, level)
fun squareLevel(level: Int) = RainbowHighlighter.getRainbowColor(RainbowHighlighter.NAME_SQUARE_BRACKETS, level)
+47 -67
View File
@@ -1,90 +1,70 @@
@file:Suppress("ConvertLambdaToReference") @file:Suppress("ConvertLambdaToReference")
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
kotlin("jvm") kotlin("jvm") version "1.9.21"
id("org.jetbrains.intellij.platform") id("org.jetbrains.intellij") version "1.17.4"
} }
group = "com.chylex.intellij.coloredbrackets" group = "com.chylex.intellij.coloredbrackets"
version = "1.5.0" version = "0.0.1"
val ideaVersion = "2026.2" repositories {
mavenCentral()
allprojects {
apply(plugin = "org.jetbrains.kotlin.jvm")
apply(plugin = "org.jetbrains.intellij.platform")
ext {
set("ideaVersion", ideaVersion)
}
repositories {
mavenCentral()
intellijPlatform {
defaultRepositories()
}
}
intellijPlatform {
sandboxContainer.set(layout.buildDirectory.map { it.dir("idea-sandbox") })
pluginConfiguration {
ideaVersion {
sinceBuild.set("262")
untilBuild.set(provider { null })
}
}
pluginVerification {
ides {
current()
}
}
}
kotlin {
jvmToolchain(17)
compilerOptions {
freeCompilerArgs = listOf(
"-X" + "jvm-default=all",
)
}
}
} }
subprojects { intellij {
version = rootProject.version type.set("IU")
version.set("2023.3")
updateSinceUntilBuild.set(false)
intellijPlatform { plugins.set(
buildSearchableOptions = false listOf(
} // Built-in
"Groovy",
"JavaScript",
"com.intellij.css",
"com.intellij.database",
"com.intellij.java",
"org.intellij.plugins.markdown",
"org.jetbrains.kotlin",
"org.jetbrains.plugins.yaml",
// Downloaded
"Dart:233.11799.172", // https://plugins.jetbrains.com/plugin/6351-dart/versions/stable
"Pythonid:233.11799.300", // https://plugins.jetbrains.com/plugin/631-python/versions
"com.jetbrains.php:233.11799.300", // https://plugins.jetbrains.com/plugin/6610-php/versions
"com.jetbrains.sh:233.11799.165", // https://plugins.jetbrains.com/plugin/13122-shell-script/versions
"org.intellij.scala:2023.3.19", // https://plugins.jetbrains.com/plugin/1347-scala/versions
"org.jetbrains.plugins.go-template:233.11799.172", // https://plugins.jetbrains.com/plugin/10581-go-template/versions
"org.jetbrains.plugins.ruby:233.11799.300", // https://plugins.jetbrains.com/plugin/1293-ruby/versions
)
)
} }
idea { kotlin {
module { jvmToolchain(17)
excludeDirs.add(file(".kotlin"))
excludeDirs.add(file("build"))
excludeDirs.add(file("gradle"))
}
} }
dependencies { dependencies {
intellijPlatform { compileOnly(fileTree("libs"))
@Suppress("DEPRECATION")
intellijIdeaUltimate(ideaVersion) testImplementation("junit:junit:4.13.2")
testImplementation("io.kotest:kotest-assertions-core:5.8.0") {
pluginComposedModule(implementation(project(":base"))) exclude(group = "org.jetbrains.kotlin")
pluginComposedModule(implementation(project(":clion")))
pluginComposedModule(implementation(project(":rider")))
} }
} }
intellijPlatform { tasks.patchPluginXml {
buildSearchableOptions.set(true) sinceBuild.set("233")
} }
tasks.test { tasks.test {
useJUnit() useJUnit()
} }
tasks.withType<KotlinCompile> {
kotlinOptions.freeCompilerArgs = listOf(
"-Xjvm-default=all"
)
}
-1
View File
@@ -1 +0,0 @@
/build/
-11
View File
@@ -1,11 +0,0 @@
val ideaVersion: String by project
dependencies {
implementation(project(":base"))
intellijPlatform {
clion(ideaVersion)
compatiblePlugin("com.intellij.cidr.lang")
}
}
@@ -1,8 +0,0 @@
package com.chylex.intellij.coloredbrackets.provider
import com.intellij.lang.BracePair
import com.jetbrains.cidr.lang.parser.OCLexerTokenTypes
class OCBracePairProvider : BracePairProvider {
override fun pairs(): List<BracePair> = listOf(BracePair(OCLexerTokenTypes.LT, OCLexerTokenTypes.GT, false))
}
-1
View File
@@ -1,2 +1 @@
kotlin.stdlib.default.dependency=false kotlin.stdlib.default.dependency=false
org.gradle.jvmargs=-Xmx1G
Binary file not shown.
+1 -3
View File
@@ -1,9 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000 networkTimeout=10000
retries=0
retryBackOffMs=500
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
Vendored
+8 -7
View File
@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# Copyright © 2015 the original authors. # Copyright © 2015-2021 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@@ -15,8 +15,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
# SPDX-License-Identifier: Apache-2.0
#
############################################################################## ##############################################################################
# #
@@ -57,7 +55,7 @@
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.
@@ -86,7 +84,7 @@ done
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum
@@ -114,6 +112,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;; NONSTOP* ) nonstop=true ;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
@@ -171,6 +170,7 @@ fi
# For Cygwin or MSYS, switch paths to Windows format before running java # For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" ) JAVACMD=$( cygpath --unix "$JAVACMD" )
@@ -203,14 +203,15 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command: # Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped. # and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line. # treated as '${Hostname}' itself on the command line.
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ -classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@" "$@"
# Stop when "xargs" is not available. # Stop when "xargs" is not available.
Vendored
+32 -22
View File
@@ -13,8 +13,6 @@
@rem See the License for the specific language governing permissions and @rem See the License for the specific language governing permissions and
@rem limitations under the License. @rem limitations under the License.
@rem @rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off @if "%DEBUG%"=="" @echo off
@rem ########################################################################## @rem ##########################################################################
@@ -23,8 +21,8 @@
@rem @rem
@rem ########################################################################## @rem ##########################################################################
@rem Set local scope for the variables, and ensure extensions are enabled @rem Set local scope for the variables with windows NT shell
setlocal EnableExtensions if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=. if "%DIRNAME%"=="" set DIRNAME=.
@@ -45,13 +43,13 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2 echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo. 1>&2 echo.
echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation. 1>&2 echo location of your Java installation.
"%COMSPEC%" /c exit 1 goto fail
:findJavaFromJavaHome :findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
@@ -59,24 +57,36 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute if exist "%JAVA_EXE%" goto execute
echo. 1>&2 echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo. 1>&2 echo.
echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation. 1>&2 echo location of your Java installation.
"%COMSPEC%" /c exit 1 goto fail
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
@rem which allows us to clear the local environment before executing the java command
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
:exitWithErrorLevel :end
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts @rem End local scope for the variables with windows NT shell
"%COMSPEC%" /c exit %ERRORLEVEL% if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
/build/
-13
View File
@@ -1,13 +0,0 @@
val ideaVersion: String by project
dependencies {
implementation(project(":base"))
intellijPlatform {
rider(ideaVersion) {
useInstaller = false
}
bundledModule("intellij.rider.languages")
}
}
@@ -1,13 +0,0 @@
package com.chylex.intellij.coloredbrackets.provider
import com.intellij.lang.BracePair
import com.jetbrains.rider.languages.fileTypes.csharp.kotoparser.lexer.CSharpTokenType
class CSharpBracePairProvider : BracePairProvider {
override fun pairs(): List<BracePair> = listOf(
BracePair(CSharpTokenType.LPARENTH, CSharpTokenType.RPARENTH, false),
BracePair(CSharpTokenType.LBRACE, CSharpTokenType.RBRACE, false),
BracePair(CSharpTokenType.LBRACKET, CSharpTokenType.RBRACKET, false),
BracePair(CSharpTokenType.LT, CSharpTokenType.GT, false),
)
}
@@ -1,26 +0,0 @@
package com.chylex.intellij.coloredbrackets.visitor
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings
import com.intellij.codeInsight.daemon.impl.HighlightVisitor
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.tree.IElementType
import com.jetbrains.rider.languages.fileTypes.csharp.kotoparser.lexer.CSharpTokenType
import com.jetbrains.rider.languages.fileTypes.csharp.psi.CSharpDummyNode
class CSharpRainbowVisitor : ReSharperRainbowVisitor("C#") {
override fun suitableForFile(file: PsiFile): Boolean {
return super.suitableForFile(file) && RainbowSettings.instance.isEnableRainbowAngleBrackets
}
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()
}
@@ -1,10 +0,0 @@
<idea-plugin>
<extensions defaultExtensionNs="com.chylex.coloredbrackets">
<bracePairProvider language="C#"
implementationClass="com.chylex.intellij.coloredbrackets.provider.CSharpBracePairProvider" />
</extensions>
<extensions defaultExtensionNs="com.intellij">
<highlightVisitor implementation="com.chylex.intellij.coloredbrackets.visitor.CSharpRainbowVisitor" />
</extensions>
</idea-plugin>
-11
View File
@@ -1,12 +1 @@
rootProject.name = "ColoredBrackets" rootProject.name = "ColoredBrackets"
pluginManagement {
plugins {
kotlin("jvm") version "2.4.10"
id("org.jetbrains.intellij.platform") version "2.18.1"
}
}
include(":base")
include(":clion")
include(":rider")
@@ -1,7 +1,7 @@
package com.chylex.intellij.coloredbrackets package com.github.izhangzhihao.rainbow.brackets
import com.chylex.intellij.coloredbrackets.provider.BracePairProvider import com.github.izhangzhihao.rainbow.brackets.provider.BracePairProvider
import com.chylex.intellij.coloredbrackets.util.memoize import com.github.izhangzhihao.rainbow.brackets.util.memoize
import com.intellij.codeInsight.highlighting.BraceMatchingUtil import com.intellij.codeInsight.highlighting.BraceMatchingUtil
import com.intellij.lang.BracePair import com.intellij.lang.BracePair
import com.intellij.lang.CompositeLanguage import com.intellij.lang.CompositeLanguage
@@ -11,12 +11,11 @@ import com.intellij.lang.LanguageExtension
import com.intellij.lang.PairedBraceMatcher import com.intellij.lang.PairedBraceMatcher
import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.IElementType
@Suppress("ConvertLambdaToReference")
object BracePairs { object BracePairs {
private val providers = LanguageExtension<BracePairProvider>("com.chylex.coloredbrackets.bracePairProvider") private val providers = LanguageExtension<BracePairProvider>("com.chylex.coloredbrackets.bracePairProvider")
val bracePairs = lazy { private val bracePairs =
Language.getRegisteredLanguages() Language.getRegisteredLanguages()
.map { language -> .map { language ->
if (language is CompositeLanguage) { if (language is CompositeLanguage) {
@@ -57,7 +56,8 @@ object BracePairs {
true true
} }
} }
?.flatMap { listOf(Pair(it.leftBraceType.toString(), it), Pair(it.rightBraceType.toString(), it)) } ?.map { listOf(Pair(it.leftBraceType.toString(), it), Pair(it.rightBraceType.toString(), it)) }
?.flatten()
?.forEach { ?.forEach {
val bracePairs = braceMap[it.first] val bracePairs = braceMap[it.first]
if (bracePairs == null) { if (bracePairs == null) {
@@ -68,18 +68,19 @@ object BracePairs {
} }
} }
language.id to braceMap language.displayName to braceMap
} }
.toMap() .toMap()
}
private fun getBraceTypeSetOf(language: Language): Set<IElementType> = language.bracePairs?.values?.flatten()?.flatMap { listOf(it.leftBraceType, it.rightBraceType) }?.toSet() ?: emptySet() fun getBracePairs(language: Language): MutableMap<String, MutableList<BracePair>>? = bracePairs[language.displayName]
private fun getBraceTypeSetOf(language: Language): Set<IElementType> = getBracePairs(language)?.values?.flatten()?.map { listOf(it.leftBraceType, it.rightBraceType) }?.flatten()?.toSet() ?: emptySet()
val braceTypeSet: (Language) -> Set<IElementType> = { language: Language -> getBraceTypeSetOf(language) }.memoize() val braceTypeSet: (Language) -> Set<IElementType> = { language: Language -> getBraceTypeSetOf(language) }.memoize()
inline val Language.bracePairs: MutableMap<String, MutableList<BracePair>>?
get() = BracePairs.bracePairs.value[this.id]
inline val Language.braceTypeSet: Set<IElementType>
get() = BracePairs.braceTypeSet(this)
} }
inline val Language.bracePairs: MutableMap<String, MutableList<BracePair>>?
get() = BracePairs.getBracePairs(this)
inline val Language.braceTypeSet: Set<IElementType>
get() = BracePairs.braceTypeSet(this)
@@ -1,9 +1,7 @@
package com.chylex.intellij.coloredbrackets package com.github.izhangzhihao.rainbow.brackets
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.chylex.intellij.coloredbrackets.util.alphaBlend import com.github.izhangzhihao.rainbow.brackets.util.memoize
import com.chylex.intellij.coloredbrackets.util.create
import com.chylex.intellij.coloredbrackets.util.memoize
import com.intellij.codeInsight.daemon.impl.HighlightInfo import com.intellij.codeInsight.daemon.impl.HighlightInfo
import com.intellij.codeInsight.daemon.impl.HighlightInfoType import com.intellij.codeInsight.daemon.impl.HighlightInfoType
import com.intellij.lang.annotation.HighlightSeverity import com.intellij.lang.annotation.HighlightSeverity
@@ -41,24 +39,16 @@ object RainbowHighlighter {
private val squigglyBrackets: CharArray = charArrayOf('{', '}') private val squigglyBrackets: CharArray = charArrayOf('{', '}')
private val angleBrackets: CharArray = charArrayOf('<', '>') private val angleBrackets: CharArray = charArrayOf('<', '>')
private val settings private val settings = RainbowSettings.instance
get() = RainbowSettings.instance
private val roundBracketsRainbowColorKeys = lazy { private val roundBracketsRainbowColorKeys: Array<TextAttributesKey> =
createRainbowAttributesKeys(KEY_ROUND_BRACKETS, settings.numberOfColors) createRainbowAttributesKeys(KEY_ROUND_BRACKETS, settings.numberOfColors)
} private val squareBracketsRainbowColorKeys: Array<TextAttributesKey> =
private val squareBracketsRainbowColorKeys = lazy {
createRainbowAttributesKeys(KEY_SQUARE_BRACKETS, settings.numberOfColors) createRainbowAttributesKeys(KEY_SQUARE_BRACKETS, settings.numberOfColors)
} private val squigglyBracketsRainbowColorKeys: Array<TextAttributesKey> =
private val squigglyBracketsRainbowColorKeys = lazy {
createRainbowAttributesKeys(KEY_SQUIGGLY_BRACKETS, settings.numberOfColors) createRainbowAttributesKeys(KEY_SQUIGGLY_BRACKETS, settings.numberOfColors)
} private val angleBracketsRainbowColorKeys: Array<TextAttributesKey> =
private val angleBracketsRainbowColorKeys = lazy {
createRainbowAttributesKeys(KEY_ANGLE_BRACKETS, settings.numberOfColors) createRainbowAttributesKeys(KEY_ANGLE_BRACKETS, settings.numberOfColors)
}
private val SCOPE_HIGHLIGHTING_KEY = TextAttributesKey.createTempTextAttributesKey("ColoredBrackets:ScopeHighlighting", TextAttributes.ERASE_MARKER)
private val SCOPE_OUTSIDE_HIGHLIGHTING_KEY = TextAttributesKey.createTempTextAttributesKey("ColoredBrackets:ScopeOutsideHighlighting", TextAttributes.ERASE_MARKER)
private val rainbowElement: HighlightInfoType = HighlightInfoType private val rainbowElement: HighlightInfoType = HighlightInfoType
.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, DefaultLanguageHighlighterColors.CONSTANT) .HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, DefaultLanguageHighlighterColors.CONSTANT)
@@ -78,10 +68,10 @@ object RainbowHighlighter {
fun getRainbowAttributesKeys(rainbowName: String): Array<TextAttributesKey> { fun getRainbowAttributesKeys(rainbowName: String): Array<TextAttributesKey> {
return when (rainbowName) { return when (rainbowName) {
NAME_ROUND_BRACKETS -> roundBracketsRainbowColorKeys.value NAME_ROUND_BRACKETS -> roundBracketsRainbowColorKeys
NAME_SQUARE_BRACKETS -> squareBracketsRainbowColorKeys.value NAME_SQUARE_BRACKETS -> squareBracketsRainbowColorKeys
NAME_SQUIGGLY_BRACKETS -> squigglyBracketsRainbowColorKeys.value NAME_SQUIGGLY_BRACKETS -> squigglyBracketsRainbowColorKeys
NAME_ANGLE_BRACKETS -> angleBracketsRainbowColorKeys.value NAME_ANGLE_BRACKETS -> angleBracketsRainbowColorKeys
else -> throw IllegalArgumentException("Unknown rainbow name: $rainbowName") else -> throw IllegalArgumentException("Unknown rainbow name: $rainbowName")
} }
} }
@@ -142,7 +132,7 @@ object RainbowHighlighter {
} }
private fun genByOption(option: String, rainbowName: String, level: Int) = private fun genByOption(option: String, rainbowName: String, level: Int) =
create( com.github.izhangzhihao.rainbow.brackets.util.create(
"$rainbowName-$level", "$rainbowName-$level",
TextAttributes(randomColor(option), null, null, null, 0) TextAttributes(randomColor(option), null, null, null, 0)
) )
@@ -188,6 +178,7 @@ object RainbowHighlighter {
.create() .create()
} }
private val KEY_HTML_CODE: TextAttributesKey by lazy { TextAttributesKey.createTextAttributesKey("HTML_CODE") } private val KEY_HTML_CODE: TextAttributesKey by lazy { TextAttributesKey.createTextAttributesKey("HTML_CODE") }
private val KEY_KOTLIN_LABEL: TextAttributesKey by lazy { TextAttributesKey.createTextAttributesKey("KOTLIN_LABEL") } private val KEY_KOTLIN_LABEL: TextAttributesKey by lazy { TextAttributesKey.createTextAttributesKey("KOTLIN_LABEL") }
private val KEY_MATCHED_BRACE_ATTRIBUTES: TextAttributesKey by lazy { private val KEY_MATCHED_BRACE_ATTRIBUTES: TextAttributesKey by lazy {
@@ -197,6 +188,7 @@ object RainbowHighlighter {
TextAttributesKey.createTextAttributesKey("KOTLIN_FUNCTION_LITERAL_BRACES_AND_ARROW") TextAttributesKey.createTextAttributesKey("KOTLIN_FUNCTION_LITERAL_BRACES_AND_ARROW")
} }
fun fixHighlighting(scheme: EditorColorsScheme = EditorColorsManager.getInstance().globalScheme) { fun fixHighlighting(scheme: EditorColorsScheme = EditorColorsManager.getInstance().globalScheme) {
// html code // html code
scheme.setInherited(KEY_HTML_CODE, !settings.isRainbowifyHTMLInsideJS) scheme.setInherited(KEY_HTML_CODE, !settings.isRainbowifyHTMLInsideJS)
@@ -230,23 +222,4 @@ object RainbowHighlighter {
private fun EditorColorsScheme.setInherited(key: TextAttributesKey, inherited: Boolean) { private fun EditorColorsScheme.setInherited(key: TextAttributesKey, inherited: Boolean) {
setAttributes(key, if (inherited) AbstractColorsScheme.INHERITED_ATTRS_MARKER else TextAttributes()) setAttributes(key, if (inherited) AbstractColorsScheme.INHERITED_ATTRS_MARKER else TextAttributes())
} }
fun updateScopeHighlightingAttributes(scheme: EditorColorsScheme, rainbowInfo: RainbowInfo): TextAttributesKey {
val defaultBackground = EditorColorsManager.getInstance().globalScheme.defaultBackground
val background = rainbowInfo.color.alphaBlend(defaultBackground, 0.2f)
val attributes = TextAttributes(null, background, rainbowInfo.color, EffectType.BOXED, Font.PLAIN)
scheme.setAttributes(SCOPE_HIGHLIGHTING_KEY, attributes)
return SCOPE_HIGHLIGHTING_KEY
}
fun updateScopeOutsideHighlightingAttributes(scheme: EditorColorsScheme): TextAttributesKey {
val defaultBackground = scheme.defaultBackground
val background = Color.GRAY.alphaBlend(defaultBackground, 0.05f)
val foreground = Color.GRAY.alphaBlend(defaultBackground, 0.55f)
val attributes = TextAttributes(foreground, background, background, EffectType.BOXED, Font.PLAIN)
scheme.setAttributes(SCOPE_OUTSIDE_HIGHLIGHTING_KEY, attributes)
return SCOPE_OUTSIDE_HIGHLIGHTING_KEY
}
} }
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets package com.github.izhangzhihao.rainbow.brackets
import com.intellij.openapi.util.Key import com.intellij.openapi.util.Key
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
@@ -1,45 +1,38 @@
package com.chylex.intellij.coloredbrackets package com.github.izhangzhihao.rainbow.brackets
import com.chylex.intellij.coloredbrackets.settings.RainbowConfigurable import com.github.izhangzhihao.rainbow.brackets.settings.RainbowConfigurable
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.chylex.intellij.coloredbrackets.util.memoizedFileExtension import com.github.izhangzhihao.rainbow.brackets.util.memoizedFileExtension
import com.chylex.intellij.coloredbrackets.util.toPsiFile import com.github.izhangzhihao.rainbow.brackets.util.toPsiFile
import com.chylex.intellij.coloredbrackets.visitor.RainbowHighlightVisitor.Companion.checkForBigFile import com.github.izhangzhihao.rainbow.brackets.visitor.RainbowHighlightVisitor.Companion.checkForBigFile
import com.intellij.icons.AllIcons import com.intellij.icons.AllIcons
import com.intellij.ide.actions.ShowSettingsUtilImpl import com.intellij.ide.actions.ShowSettingsUtilImpl
import com.intellij.openapi.fileEditor.FileEditor import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.Ref import com.intellij.openapi.util.Ref
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.ui.EditorNotificationPanel import com.intellij.ui.EditorNotificationPanel
import com.intellij.ui.EditorNotificationProvider
import com.intellij.ui.EditorNotifications import com.intellij.ui.EditorNotifications
import com.intellij.ui.HyperlinkLabel import com.intellij.ui.HyperlinkLabel
import java.util.function.Function
import javax.swing.JComponent
class RainbowifyBanner : EditorNotificationProvider { class RainbowifyBanner : EditorNotifications.Provider<EditorNotificationPanel>() {
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?> { override fun getKey(): Key<EditorNotificationPanel> = KEY
return Function { createNotificationPanel(project, file) }
}
private fun createNotificationPanel(project: Project, file: VirtualFile): EditorNotificationPanel? { override fun createNotificationPanel(file: VirtualFile, fileEditor: FileEditor, project: Project): EditorNotificationPanel? {
val settings = RainbowSettings.instance
if (!settings.isRainbowEnabled) { if (!RainbowSettings.instance.isRainbowEnabled) {
if (settings.suppressDisabledCheck) { if (RainbowSettings.instance.suppressDisabledCheck) return null
return null
}
return EditorNotificationPanel().apply { return EditorNotificationPanel().apply {
text("Colored Brackets is now disabled") text("Colored Brackets is now disabled")
icon(AllIcons.General.GearPlain) icon(AllIcons.General.GearPlain)
createComponentActionLabel("got it, don't show again") { createComponentActionLabel("got it, don't show again") {
settings.suppressDisabledCheck = true RainbowSettings.instance.suppressDisabledCheck = true
EditorNotifications.getInstance(project).updateAllNotifications() EditorNotifications.getInstance(project).updateAllNotifications()
} }
createComponentActionLabel("enable Colored Brackets") { createComponentActionLabel("enable Colored Brackets") {
settings.isRainbowEnabled = true RainbowSettings.instance.isRainbowEnabled = true
EditorNotifications.getInstance(project).updateAllNotifications() EditorNotifications.getInstance(project).updateAllNotifications()
} }
} }
@@ -47,14 +40,12 @@ class RainbowifyBanner : EditorNotificationProvider {
val psiFile = file.toPsiFile(project) val psiFile = file.toPsiFile(project)
if (psiFile != null && !checkForBigFile(psiFile)) { if (psiFile != null && !checkForBigFile(psiFile)) {
if (settings.suppressBigFileCheck) { if (RainbowSettings.instance.suppressBigFileCheck) return null
return null
}
return EditorNotificationPanel().apply { return EditorNotificationPanel().apply {
text("Rainbowify is disabled for files > " + settings.bigFilesLinesThreshold + " lines") text("Rainbowify is disabled for files > " + RainbowSettings.instance.bigFilesLinesThreshold + " lines")
icon(AllIcons.General.InspectionsEye) icon(AllIcons.General.InspectionsEye)
createComponentActionLabel("got it, don't show again") { createComponentActionLabel("got it, don't show again") {
settings.suppressBigFileCheck = true RainbowSettings.instance.suppressBigFileCheck = true
EditorNotifications.getInstance(project).updateAllNotifications() EditorNotifications.getInstance(project).updateAllNotifications()
} }
@@ -66,18 +57,16 @@ class RainbowifyBanner : EditorNotificationProvider {
} }
if ( if (
settings.languageBlacklist.contains(file.fileType.name) || RainbowSettings.instance.languageBlacklist.contains(file.fileType.name) ||
settings.languageBlacklist.contains(memoizedFileExtension(file.name)) RainbowSettings.instance.languageBlacklist.contains(memoizedFileExtension(file.name))
) { ) {
if (settings.suppressBlackListCheck) { if (RainbowSettings.instance.suppressBlackListCheck) return null
return null
}
return EditorNotificationPanel().apply { return EditorNotificationPanel().apply {
text("Rainbowify is disabled because the language/file extension is in the black list") text("Rainbowify is disabled because the language/file extension is in the black list")
icon(AllIcons.General.InspectionsEye) icon(AllIcons.General.InspectionsEye)
createComponentActionLabel("got it, don't show again") { createComponentActionLabel("got it, don't show again") {
settings.suppressBlackListCheck = true RainbowSettings.instance.suppressBlackListCheck = true
EditorNotifications.getInstance(project).updateAllNotifications() EditorNotifications.getInstance(project).updateAllNotifications()
} }
@@ -91,10 +80,14 @@ class RainbowifyBanner : EditorNotificationProvider {
return null return null
} }
private fun EditorNotificationPanel.createComponentActionLabel(labelText: String, callback: (HyperlinkLabel) -> Unit) { companion object {
val label: Ref<HyperlinkLabel> = Ref.create() private val KEY = Key.create<EditorNotificationPanel>("RainbowifyBanner")
label.set(createActionLabel(labelText) {
callback(label.get()) fun EditorNotificationPanel.createComponentActionLabel(labelText: String, callback: (HyperlinkLabel) -> Unit) {
}) val label: Ref<HyperlinkLabel> = Ref.create()
label.set(createActionLabel(labelText) {
callback(label.get())
})
}
} }
} }
@@ -1,18 +1,17 @@
package com.chylex.intellij.coloredbrackets package com.github.izhangzhihao.rainbow.brackets
import com.chylex.intellij.coloredbrackets.color.Luminosity
import com.chylex.intellij.coloredbrackets.color.fromString
import com.chylex.intellij.coloredbrackets.color.randomColor
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.github.izhangzhihao.rainbow.brackets.color.Luminosity
import com.github.izhangzhihao.rainbow.brackets.color.fromString
import java.awt.Color import java.awt.Color
val mapper: ObjectMapper by lazy { jacksonObjectMapper() } val mapper: ObjectMapper by lazy { jacksonObjectMapper() }
fun randomColor(options: String): Color { fun randomColor(options: String): Color {
val ops: Map<String, String> = mapper.readValue(options) val ops: Map<String, String> = mapper.readValue(options)
return randomColor( return com.github.izhangzhihao.rainbow.brackets.color.randomColor(
fromString(ops.getOrDefault("hue", "random")), fromString(ops.getOrDefault("hue", "random")),
Luminosity.valueOf(ops.getOrDefault("luminosity", "random")) Luminosity.valueOf(ops.getOrDefault("luminosity", "random"))
) )
@@ -1,8 +1,7 @@
package com.chylex.intellij.coloredbrackets.action package com.github.izhangzhihao.rainbow.brackets.action
import com.chylex.intellij.coloredbrackets.RainbowInfo import com.github.izhangzhihao.rainbow.brackets.RainbowInfo
import com.intellij.codeInsight.highlighting.HighlightManager import com.intellij.codeInsight.highlighting.HighlightManager
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.actionSystem.CommonDataKeys
@@ -18,12 +17,9 @@ import java.awt.event.FocusListener
import java.awt.event.KeyAdapter import java.awt.event.KeyAdapter
import java.awt.event.KeyEvent import java.awt.event.KeyEvent
abstract class AbstractScopeHighlightingAction : AnAction() { abstract class AbstractScopeHighlightingAction : AnAction() {
final override fun getActionUpdateThread(): ActionUpdateThread {
return ActionUpdateThread.BGT
}
final override fun update(e: AnActionEvent) { final override fun update(e: AnActionEvent) {
e.presentation.isEnabledAndVisible = e.editor.let { it != null && it !is TextComponentEditor } e.presentation.isEnabledAndVisible = e.editor.let { it != null && it !is TextComponentEditor }
} }
@@ -35,7 +31,7 @@ abstract class AbstractScopeHighlightingAction : AnAction() {
val offset = editor.caretModel.offset val offset = editor.caretModel.offset
val rainbowInfo = psiFile.findRainbowInfoAt(offset) ?: return val rainbowInfo = psiFile.findRainbowInfoAt(offset) ?: return
val highlightManager = HighlightManager.getInstance(project) val highlightManager = HighlightManager.getInstance(project)
val highlighters = editor.addHighlighter(editor, highlightManager, rainbowInfo) val highlighters = editor.addHighlighter(highlightManager, rainbowInfo)
editor.highlightingDisposer?.dispose() editor.highlightingDisposer?.dispose()
if (highlighters.isNotEmpty()) { if (highlighters.isNotEmpty()) {
@@ -47,7 +43,6 @@ abstract class AbstractScopeHighlightingAction : AnAction() {
} }
protected abstract fun Editor.addHighlighter( protected abstract fun Editor.addHighlighter(
editor: Editor,
highlightManager: HighlightManager, highlightManager: HighlightManager,
rainbowInfo: RainbowInfo, rainbowInfo: RainbowInfo,
): Collection<RangeHighlighter> ): Collection<RangeHighlighter>
@@ -0,0 +1,39 @@
package com.github.izhangzhihao.rainbow.brackets.action
import com.github.izhangzhihao.rainbow.brackets.RainbowInfo
import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.github.izhangzhihao.rainbow.brackets.util.alphaBlend
import com.intellij.codeInsight.highlighting.HighlightManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.colors.EditorColorsManager
import com.intellij.openapi.editor.markup.EffectType
import com.intellij.openapi.editor.markup.RangeHighlighter
import com.intellij.openapi.editor.markup.TextAttributes
import java.awt.Font
import java.util.LinkedList
class ScopeHighlightingAction : AbstractScopeHighlightingAction() {
override fun Editor.addHighlighter(
highlightManager: HighlightManager,
rainbowInfo: RainbowInfo,
): Collection<RangeHighlighter> {
val defaultBackground = EditorColorsManager.getInstance().globalScheme.defaultBackground
val background = rainbowInfo.color.alphaBlend(defaultBackground, 0.2f)
val attributes = TextAttributes(null, background, rainbowInfo.color, EffectType.BOXED, Font.PLAIN)
val highlighters = LinkedList<RangeHighlighter>()
highlightManager.addRangeHighlight(
this,
rainbowInfo.startOffset,
rainbowInfo.endOffset,
attributes, //create("ScopeHighlightingAction", attributes),
false, //hideByTextChange
RainbowSettings.instance.pressAnyKeyToRemoveTheHighlightingEffects, //hideByAnyKey
highlighters
)
return highlighters
}
}
@@ -0,0 +1,58 @@
package com.github.izhangzhihao.rainbow.brackets.action
import com.github.izhangzhihao.rainbow.brackets.RainbowInfo
import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.github.izhangzhihao.rainbow.brackets.util.alphaBlend
import com.intellij.codeInsight.highlighting.HighlightManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.colors.EditorColorsManager
import com.intellij.openapi.editor.markup.EffectType
import com.intellij.openapi.editor.markup.RangeHighlighter
import com.intellij.openapi.editor.markup.TextAttributes
import java.awt.Color
import java.awt.Font
import java.util.LinkedList
class ScopeOutsideHighlightingRestrainAction : AbstractScopeHighlightingAction() {
override fun Editor.addHighlighter(
highlightManager: HighlightManager,
rainbowInfo: RainbowInfo,
): Collection<RangeHighlighter> {
val defaultBackground = EditorColorsManager.getInstance().globalScheme.defaultBackground
val background = Color.GRAY.alphaBlend(defaultBackground, 0.05f)
val foreground = Color.GRAY.alphaBlend(defaultBackground, 0.55f)
val attributes = TextAttributes(foreground, background, background, EffectType.BOXED, Font.PLAIN)
val highlighters = LinkedList<RangeHighlighter>()
val startOffset = rainbowInfo.startOffset
if (startOffset > 0) {
highlightManager.addRangeHighlight(
this,
0,
startOffset,
attributes, //create("ScopeOutsideHighlightingRestrainAction", attributes),
false, //hideByTextChange
RainbowSettings.instance.pressAnyKeyToRemoveTheHighlightingEffects, //hideByAnyKey
highlighters
)
}
val endOffset = rainbowInfo.endOffset
val lastOffset = document.textLength
if (endOffset < lastOffset) {
highlightManager.addRangeHighlight(
this,
endOffset,
lastOffset,
attributes, //create("ScopeOutsideHighlightingRestrainAction", attributes),
false, //hideByTextChange
RainbowSettings.instance.pressAnyKeyToRemoveTheHighlightingEffects, //hideByAnyKey
highlighters
)
}
return highlighters
}
}
@@ -1,8 +1,8 @@
package com.chylex.intellij.coloredbrackets.annotator package com.github.izhangzhihao.rainbow.brackets.annotator
import com.chylex.intellij.coloredbrackets.RainbowHighlighter import com.github.izhangzhihao.rainbow.brackets.RainbowHighlighter
import com.chylex.intellij.coloredbrackets.RainbowInfo import com.github.izhangzhihao.rainbow.brackets.RainbowInfo
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.intellij.lang.annotation.AnnotationHolder import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.lang.annotation.Annotator import com.intellij.lang.annotation.Annotator
import com.intellij.lang.annotation.HighlightSeverity import com.intellij.lang.annotation.HighlightSeverity
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.psi.KtLabeledExpression
import org.jetbrains.kotlin.psi.KtLambdaExpression import org.jetbrains.kotlin.psi.KtLambdaExpression
import java.awt.Font import java.awt.Font
class KotlinLabelAnnotator : Annotator { class KotlinLabelAnnotator : Annotator {
override fun annotate(element: PsiElement, holder: AnnotationHolder) { override fun annotate(element: PsiElement, holder: AnnotationHolder) {
if (!RainbowSettings.instance.isRainbowifyKotlinLabel) { if (!RainbowSettings.instance.isRainbowifyKotlinLabel) {
@@ -47,13 +48,13 @@ class KotlinLabelAnnotator : Annotator {
refElement = when (refElement) { refElement = when (refElement) {
is KtBlockExpression, is KtBlockExpression,
is KtFunctionLiteral, is KtFunctionLiteral,
-> refElement -> refElement
is KtFunction -> refElement.lastChild.takeIf { it is KtBlockExpression } is KtFunction -> refElement.lastChild.takeIf { it is KtBlockExpression }
is KtClass -> refElement.lastChild.takeIf { it is KtClassBody } is KtClass -> refElement.lastChild.takeIf { it is KtClassBody }
is KtCallExpression, is KtCallExpression,
is KtLambdaExpression, is KtLambdaExpression,
-> PsiTreeUtil.findChildOfType(refElement, KtFunctionLiteral::class.java) -> PsiTreeUtil.findChildOfType(refElement, KtFunctionLiteral::class.java)
else -> null else -> null
} }
@@ -65,11 +66,11 @@ class KotlinLabelAnnotator : Annotator {
when (it) { when (it) {
is KtBlockExpression, is KtBlockExpression,
is KtFunctionLiteral, is KtFunctionLiteral,
-> it -> it
is KtCallExpression, is KtCallExpression,
is KtLambdaExpression, is KtLambdaExpression,
-> PsiTreeUtil.findChildOfType(it, KtFunctionLiteral::class.java) -> PsiTreeUtil.findChildOfType(it, KtFunctionLiteral::class.java)
else -> null else -> null
} }
@@ -85,7 +86,7 @@ class KotlinLabelAnnotator : Annotator {
holder.newSilentAnnotation(HighlightSeverity.INFORMATION) holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
.range(target) .range(target)
.textAttributes( .textAttributes(
com.chylex.intellij.coloredbrackets.util.create( com.github.izhangzhihao.rainbow.brackets.util.create(
"rainbow-kotlin-label", "rainbow-kotlin-label",
TextAttributes(it, null, null, EffectType.BOXED, Font.PLAIN) TextAttributes(it, null, null, EffectType.BOXED, Font.PLAIN)
) )
@@ -1,6 +1,6 @@
package com.chylex.intellij.coloredbrackets.annotator package com.github.izhangzhihao.rainbow.brackets.annotator
import com.chylex.intellij.coloredbrackets.RainbowInfo import com.github.izhangzhihao.rainbow.brackets.RainbowInfo
import com.intellij.lang.annotation.AnnotationHolder import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.lang.annotation.Annotator import com.intellij.lang.annotation.Annotator
import com.intellij.lang.annotation.HighlightSeverity import com.intellij.lang.annotation.HighlightSeverity
@@ -11,14 +11,15 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import java.awt.Font import java.awt.Font
class KotlinLambdaExpressionArrowAnnotator : Annotator { class KotlinLambdaExpressionArrowAnnotator : Annotator {
override fun annotate(element: PsiElement, holder: AnnotationHolder) { override fun annotate(element: PsiElement, holder: AnnotationHolder) {
if ((element as? LeafPsiElement)?.elementType == KtTokens.ARROW) { if ((element as? LeafPsiElement)?.elementType == KtTokens.ARROW) {
RainbowInfo.RAINBOW_INFO_KEY[element.parent]?.color?.let { RainbowInfo.RAINBOW_INFO_KEY[element.parent]?.color?.let {
holder.newSilentAnnotation(HighlightSeverity.INFORMATION) holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
.range(element as PsiElement) // Cast necessary due to overload conflict in Kotlin 2 compiler. .range(element)
.textAttributes( .textAttributes(
com.chylex.intellij.coloredbrackets.util.create( com.github.izhangzhihao.rainbow.brackets.util.create(
"rainbow-kotlin-arrow", "rainbow-kotlin-arrow",
TextAttributes(it, null, null, EffectType.BOXED, Font.PLAIN) TextAttributes(it, null, null, EffectType.BOXED, Font.PLAIN)
) )
@@ -0,0 +1,122 @@
package com.github.izhangzhihao.rainbow.brackets.annotator
import com.github.izhangzhihao.rainbow.brackets.RainbowHighlighter.NAME_ANGLE_BRACKETS
import com.github.izhangzhihao.rainbow.brackets.RainbowHighlighter.NAME_ROUND_BRACKETS
import com.github.izhangzhihao.rainbow.brackets.RainbowHighlighter.NAME_SQUARE_BRACKETS
import com.github.izhangzhihao.rainbow.brackets.RainbowHighlighter.NAME_SQUIGGLY_BRACKETS
import com.github.izhangzhihao.rainbow.brackets.RainbowHighlighter.getRainbowColorByLevel
import com.github.izhangzhihao.rainbow.brackets.annotator.RainbowUtils.annotateUtil
import com.github.izhangzhihao.rainbow.brackets.annotator.RainbowUtils.settings
import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.lang.annotation.Annotator
import com.intellij.lang.annotation.HighlightSeverity
import com.intellij.openapi.editor.colors.EditorColorsManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.impl.source.tree.LeafPsiElement
class RainbowAnnotator : Annotator {
override fun annotate(element: PsiElement, holder: AnnotationHolder) {
if (settings.isRainbowEnabled && element is LeafPsiElement) {
if (!settings.applyColorsOfRoundForAllBrackets) {
if (settings.isEnableRainbowRoundBrackets) annotateUtil(element, holder, "(", ")", NAME_ROUND_BRACKETS)
if (settings.isEnableRainbowSquareBrackets) annotateUtil(element, holder, "[", "]", NAME_SQUARE_BRACKETS)
if (settings.isEnableRainbowSquigglyBrackets) annotateUtil(element, holder, "{", "}", NAME_SQUIGGLY_BRACKETS)
if (settings.isEnableRainbowAngleBrackets) annotateUtil(element, holder, "<", ">", NAME_ANGLE_BRACKETS)
}
else {
if (settings.isEnableRainbowRoundBrackets) annotateUtil(element, holder, "(", ")", NAME_ROUND_BRACKETS)
if (settings.isEnableRainbowSquareBrackets) annotateUtil(element, holder, "[", "]", NAME_ROUND_BRACKETS)
if (settings.isEnableRainbowSquigglyBrackets) annotateUtil(element, holder, "{", "}", NAME_ROUND_BRACKETS)
if (settings.isEnableRainbowAngleBrackets) annotateUtil(element, holder, "<", ">", NAME_ROUND_BRACKETS)
}
}
}
}
object RainbowUtils {
private val leftBracketsSet = setOf("(", "[", "{", "<")
private val rightBracketsSet = setOf(")", "]", "}", ">")
val settings = RainbowSettings.instance
private tailrec fun iterateChildren(
LEFT: String,
RIGHT: String,
currentNode: PsiElement,
currentLevel: Int,
currentChild: PsiElement,
): Int {
val calculatedLevel = if (currentChild is LeafPsiElement) {
//Using `currentChild.elementType.toString()` if we didn't want add more dependencies.
if (!settings.cycleCountOnAllBrackets) {
when (currentChild.text) {
LEFT -> currentLevel + 1
RIGHT -> currentLevel - 1
else -> currentLevel
}
}
else {
when {
leftBracketsSet.contains(currentChild.text) -> currentLevel + 1
rightBracketsSet.contains(currentChild.text) -> currentLevel - 1
else -> currentLevel
}
}
}
else currentLevel
return if ((currentChild != currentNode) && (currentChild != currentNode.parent.lastChild))
iterateChildren(LEFT, RIGHT, currentNode, calculatedLevel, currentChild.nextSibling)
else
calculatedLevel
}
private tailrec fun iterateParents(
LEFT: String,
RIGHT: String,
currentNode: PsiElement,
currentLevel: Int,
): Int = if (currentNode.parent !is PsiFile) {
val calculatedLevel = iterateChildren(LEFT, RIGHT, currentNode, currentLevel, currentNode.parent.firstChild)
iterateParents(LEFT, RIGHT, currentNode.parent, calculatedLevel)
}
else currentLevel
private fun getBracketLevel(element: LeafPsiElement, LEFT: String, RIGHT: String): Int {
//Using `element.elementType.toString()` if we didn't want add more dependencies.
val startLevel = if (element.text == RIGHT) 0 else -1
return iterateParents(LEFT, RIGHT, element, startLevel)
}
fun annotateUtil(
element: LeafPsiElement, holder: AnnotationHolder,
LEFT: String, RIGHT: String, rainbowName: String,
) {
//Using `element.elementType.toString()` if we didn't want add more dependencies.
val level = when (element.text) {
LEFT, RIGHT -> getBracketLevel(element, LEFT, RIGHT)
else -> -1
}
val scheme = EditorColorsManager.getInstance().globalScheme
if (RainbowSettings.instance.isDoNOTRainbowifyTheFirstLevel) {
if (level >= 1) {
holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
.range(element.psi)
.textAttributes(getRainbowColorByLevel(scheme, rainbowName, level))
.create()
}
}
else {
if (level >= 0) {
holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
.range(element.psi)
.textAttributes(getRainbowColorByLevel(scheme, rainbowName, level))
.create()
}
}
}
}
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.color package com.github.izhangzhihao.rainbow.brackets.color
import kotlin.math.floor import kotlin.math.floor
@@ -1,4 +1,5 @@
package com.chylex.intellij.coloredbrackets.color package com.github.izhangzhihao.rainbow.brackets.color
sealed class Hue sealed class Hue
object RandomHue : Hue() object RandomHue : Hue()
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.color package com.github.izhangzhihao.rainbow.brackets.color
enum class Luminosity { enum class Luminosity {
random, random,
@@ -1,8 +1,9 @@
package com.chylex.intellij.coloredbrackets.color package com.github.izhangzhihao.rainbow.brackets.color
import kotlin.math.floor import kotlin.math.floor
import kotlin.random.Random import kotlin.random.Random
/** /**
* Generate a single random color with specified (or random) hue and luminosity. * Generate a single random color with specified (or random) hue and luminosity.
*/ */
@@ -71,6 +72,7 @@ private fun toColor(hueValue: Int, saturation: Int, brightness: Int): java.awt.C
return java.awt.Color(rgb.first, rgb.second, rgb.third) return java.awt.Color(rgb.first, rgb.second, rgb.third)
} }
private fun HSVtoRGB(hueValue: Int, saturation: Int, brightness: Int): Triple<Int, Int, Int> { private fun HSVtoRGB(hueValue: Int, saturation: Int, brightness: Int): Triple<Int, Int, Int> {
// This doesn't work for the values of 0 and 360 // This doesn't work for the values of 0 and 360
// Here's the hacky fix // Here's the hacky fix
@@ -134,14 +136,13 @@ private fun matchColor(hueValue: Int, hue: Hue): Color {
hueVal -= 360 hueVal -= 360
} }
for (color in Color.entries) { for (color in Color.values()) {
if (hueVal in color.hueRange.first..color.hueRange.second) { if (hueVal in color.hueRange.first..color.hueRange.second) {
return color return color
} }
} }
// Returning Monochrome if we can't find a value, but this should never happen // Returning Monochrome if we can't find a value, but this should never happen
Color.monochrome return Color.monochrome
} }
} }
} }
@@ -1,27 +1,24 @@
package com.chylex.intellij.coloredbrackets.indents package com.github.izhangzhihao.rainbow.brackets.indents
import com.chylex.intellij.coloredbrackets.RainbowInfo import com.github.izhangzhihao.rainbow.brackets.RainbowInfo
import com.chylex.intellij.coloredbrackets.util.alphaBlend import com.github.izhangzhihao.rainbow.brackets.util.alphaBlend
import com.chylex.intellij.coloredbrackets.util.endOffset import com.github.izhangzhihao.rainbow.brackets.util.endOffset
import com.chylex.intellij.coloredbrackets.util.findNextSibling import com.github.izhangzhihao.rainbow.brackets.util.findNextSibling
import com.chylex.intellij.coloredbrackets.util.findPrevSibling import com.github.izhangzhihao.rainbow.brackets.util.findPrevSibling
import com.chylex.intellij.coloredbrackets.util.lineNumber import com.github.izhangzhihao.rainbow.brackets.util.lineNumber
import com.chylex.intellij.coloredbrackets.util.startOffset import com.github.izhangzhihao.rainbow.brackets.util.startOffset
import com.intellij.openapi.application.ReadAction
import com.intellij.openapi.editor.Document import com.intellij.openapi.editor.Document
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.SoftWrap import com.intellij.openapi.editor.SoftWrap
import com.intellij.openapi.editor.ex.DocumentEx
import com.intellij.openapi.editor.ex.EditorEx import com.intellij.openapi.editor.ex.EditorEx
import com.intellij.openapi.editor.impl.EditorImpl import com.intellij.openapi.editor.impl.EditorImpl
import com.intellij.openapi.editor.impl.view.EditorPainter import com.intellij.openapi.editor.impl.view.EditorPainter
import com.intellij.openapi.editor.impl.view.VisualLinesIterator import com.intellij.openapi.editor.impl.view.VisualLinesIterator
import com.intellij.openapi.editor.markup.CustomHighlighterRenderer import com.intellij.openapi.editor.markup.CustomHighlighterRenderer
import com.intellij.openapi.editor.markup.RangeHighlighter import com.intellij.openapi.editor.markup.RangeHighlighter
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Condition import com.intellij.openapi.util.Condition
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.xml.XmlFile import com.intellij.psi.xml.XmlFile
import com.intellij.psi.xml.XmlTag import com.intellij.psi.xml.XmlTag
@@ -38,15 +35,13 @@ import kotlin.math.max
* */ * */
class RainbowIndentGuideRenderer : CustomHighlighterRenderer { class RainbowIndentGuideRenderer : CustomHighlighterRenderer {
override fun paint(editor: Editor, highlighter: RangeHighlighter, g: Graphics) { override fun paint(editor: Editor, highlighter: RangeHighlighter, g: Graphics) {
if (editor !is EditorEx) { if (editor !is EditorEx) return
return
} val rainbowInfo = getRainbowInfo(editor, highlighter) ?: return
val startOffset = highlighter.startOffset val startOffset = highlighter.startOffset
val doc = highlighter.document val doc = highlighter.document
if (startOffset >= doc.textLength) { if (startOffset >= doc.textLength) return
return
}
val endOffset = highlighter.endOffset val endOffset = highlighter.endOffset
@@ -64,21 +59,15 @@ class RainbowIndentGuideRenderer : CustomHighlighterRenderer {
val startPosition = editor.offsetToVisualPosition(off) val startPosition = editor.offsetToVisualPosition(off)
val indentColumn = startPosition.column val indentColumn = startPosition.column
if (indentColumn <= 0) { if (indentColumn <= 0) return
return
}
val foldingModel = editor.foldingModel val foldingModel = editor.foldingModel
if (foldingModel.isOffsetCollapsed(off)) { if (foldingModel.isOffsetCollapsed(off)) return
return
}
val headerRegion = foldingModel.getCollapsedRegionAtOffset(doc.getLineEndOffset(doc.getLineNumber(off))) val headerRegion = foldingModel.getCollapsedRegionAtOffset(doc.getLineEndOffset(doc.getLineNumber(off)))
val tailRegion = foldingModel.getCollapsedRegionAtOffset(doc.getLineStartOffset(doc.getLineNumber(endOffset))) val tailRegion = foldingModel.getCollapsedRegionAtOffset(doc.getLineStartOffset(doc.getLineNumber(endOffset)))
if (tailRegion != null && tailRegion === headerRegion) { if (tailRegion != null && tailRegion === headerRegion) return
return
}
val guide = editor.indentsModel.caretIndentGuide val guide = editor.indentsModel.caretIndentGuide
val selected = if (guide != null) { val selected = if (guide != null) {
@@ -88,7 +77,7 @@ class RainbowIndentGuideRenderer : CustomHighlighterRenderer {
} }
else false else false
val lineHeight = editor.lineHeight val lineHeight = editor.getLineHeight()
val start = editor.visualPositionToXY(startPosition) val start = editor.visualPositionToXY(startPosition)
start.y += lineHeight start.y += lineHeight
val endPosition = editor.offsetToVisualPosition(endOffset) val endPosition = editor.offsetToVisualPosition(endOffset)
@@ -105,11 +94,7 @@ class RainbowIndentGuideRenderer : CustomHighlighterRenderer {
} }
maxY = StrictMath.min(maxY, clip.y + clip.height) maxY = StrictMath.min(maxY, clip.y + clip.height)
} }
if (start.y >= maxY) { if (start.y >= maxY) return
return
}
val rainbowInfo = getRainbowInfo(editor, highlighter) ?: return
val targetX = max(0, start.x + EditorPainter.getIndentGuideShift(editor)).toDouble() val targetX = max(0, start.x + EditorPainter.getIndentGuideShift(editor)).toDouble()
g.color = if (selected) { g.color = if (selected) {
rainbowInfo.color rainbowInfo.color
@@ -177,19 +162,13 @@ class RainbowIndentGuideRenderer : CustomHighlighterRenderer {
} }
private fun getRainbowInfo(editor: EditorEx, highlighter: RangeHighlighter): RainbowInfo? { private fun getRainbowInfo(editor: EditorEx, highlighter: RangeHighlighter): RainbowInfo? {
val project = editor.project ?: return null val virtualFile = editor.virtualFile?.takeIf { it.isValid } ?: return null
val document = editor.document val document = editor.document
val project = editor.project ?: return null
return ReadAction.computeBlocking<RainbowInfo?, Throwable> { val psiFile = PsiManager.getInstance(project).findFile(virtualFile) ?: return null
getRainbowInfoInReadAction(project, document, highlighter)
}
}
private fun getRainbowInfoInReadAction(project: Project, document: DocumentEx, highlighter: RangeHighlighter): RainbowInfo? {
val psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document) ?: return null
var element = try { var element = try {
psiFile.findElementAt(highlighter.endOffset)?.parent ?: return null psiFile.findElementAt(highlighter.endOffset)?.parent ?: return null
} catch (_: Throwable) { } catch (e: Throwable) {
return null return null
} }
@@ -285,5 +264,6 @@ class RainbowIndentGuideRenderer : CustomHighlighterRenderer {
private fun XmlTag.getEndTagStartLineNumber(document: Document): Int? = private fun XmlTag.getEndTagStartLineNumber(document: Document): Int? =
lastChild?.findPrevSibling(XML_END_TAG_START_CONDITION)?.let { document.lineNumber(it.startOffset) } lastChild?.findPrevSibling(XML_END_TAG_START_CONDITION)?.let { document.lineNumber(it.startOffset) }
} }
} }
@@ -1,13 +1,15 @@
package com.chylex.intellij.coloredbrackets.indents package com.github.izhangzhihao.rainbow.brackets.indents
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.intellij.codeHighlighting.TextEditorHighlightingPass import com.intellij.codeHighlighting.TextEditorHighlightingPass
import com.intellij.codeInsight.highlighting.BraceMatchingUtil import com.intellij.codeInsight.highlighting.BraceMatchingUtil
import com.intellij.codeInsight.highlighting.CodeBlockSupportHandler import com.intellij.codeInsight.highlighting.CodeBlockSupportHandler
import com.intellij.ide.actions.ToggleZenModeAction import com.intellij.ide.actions.ToggleZenModeAction
import com.intellij.lang.Language
import com.intellij.lang.LanguageParserDefinitions import com.intellij.lang.LanguageParserDefinitions
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.IndentGuideDescriptor import com.intellij.openapi.editor.IndentGuideDescriptor
import com.intellij.openapi.editor.ex.EditorEx
import com.intellij.openapi.editor.ex.util.EditorUtil import com.intellij.openapi.editor.ex.util.EditorUtil
import com.intellij.openapi.editor.markup.HighlighterTargetArea import com.intellij.openapi.editor.markup.HighlighterTargetArea
import com.intellij.openapi.editor.markup.MarkupModel import com.intellij.openapi.editor.markup.MarkupModel
@@ -22,8 +24,8 @@ import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.psi.tree.TokenSet import com.intellij.psi.tree.TokenSet
import com.intellij.util.DocumentUtil import com.intellij.util.DocumentUtil
import com.intellij.util.containers.IntStack
import com.intellij.util.text.CharArrayUtil import com.intellij.util.text.CharArrayUtil
import it.unimi.dsi.fastutil.ints.IntArrayList
import java.lang.StrictMath.abs import java.lang.StrictMath.abs
import java.lang.StrictMath.min import java.lang.StrictMath.min
import java.util.Collections import java.util.Collections
@@ -34,9 +36,11 @@ import java.util.Collections
* */ * */
class RainbowIndentsPass internal constructor( class RainbowIndentsPass internal constructor(
project: Project, project: Project,
private val myEditor: Editor, editor: Editor,
private val myFile: PsiFile, private val myFile: PsiFile,
) : TextEditorHighlightingPass(project, myEditor.document, false), DumbAware { ) : TextEditorHighlightingPass(project, editor.document, false), DumbAware {
private val myEditor: EditorEx = editor as EditorEx
@Volatile @Volatile
private var myRanges = emptyList<TextRange>() private var myRanges = emptyList<TextRange>()
@@ -46,9 +50,7 @@ class RainbowIndentsPass internal constructor(
override fun doCollectInformation(progress: ProgressIndicator) { override fun doCollectInformation(progress: ProgressIndicator) {
val stamp = myEditor.getUserData(LAST_TIME_INDENTS_BUILT) val stamp = myEditor.getUserData(LAST_TIME_INDENTS_BUILT)
if (stamp != null && stamp == nowStamp()) { if (stamp != null && stamp.toLong() == nowStamp()) return
return
}
myDescriptors = buildDescriptors() myDescriptors = buildDescriptors()
@@ -74,9 +76,7 @@ class RainbowIndentsPass internal constructor(
val stamp = myEditor.getUserData(LAST_TIME_INDENTS_BUILT) val stamp = myEditor.getUserData(LAST_TIME_INDENTS_BUILT)
val nowStamp = nowStamp() val nowStamp = nowStamp()
if (stamp == nowStamp) { if (stamp == nowStamp) return
return
}
myEditor.putUserData(LAST_TIME_INDENTS_BUILT, nowStamp) myEditor.putUserData(LAST_TIME_INDENTS_BUILT, nowStamp)
@@ -146,16 +146,14 @@ class RainbowIndentsPass internal constructor(
} }
private fun buildDescriptors(): List<IndentGuideDescriptor> { private fun buildDescriptors(): List<IndentGuideDescriptor> {
if (!isRainbowIndentGuidesShown(this.myProject)) { if (!isRainbowIndentGuidesShown(this.myProject)) return emptyList()
return emptyList()
}
val calculator = IndentsCalculator() val calculator = IndentsCalculator()
calculator.calculate() calculator.calculate()
val lineIndents = calculator.lineIndents val lineIndents = calculator.lineIndents
val lines = IntArrayList() val lines = IntStack()
val indents = IntArrayList() val indents = IntStack()
lines.push(0) lines.push(0)
indents.push(0) indents.push(0)
@@ -164,10 +162,10 @@ class RainbowIndentsPass internal constructor(
ProgressManager.checkCanceled() ProgressManager.checkCanceled()
val curIndent = abs(lineIndents[line]) val curIndent = abs(lineIndents[line])
while (!indents.isEmpty && curIndent <= indents.peekInt(0)) { while (!indents.empty() && curIndent <= indents.peek()) {
ProgressManager.checkCanceled() ProgressManager.checkCanceled()
val level = indents.popInt() val level = indents.pop()
val startLine = lines.popInt() val startLine = lines.pop()
if (level > 0) { if (level > 0) {
for (i in startLine until line) { for (i in startLine until line) {
if (level != abs(lineIndents[i])) { if (level != abs(lineIndents[i])) {
@@ -187,10 +185,10 @@ class RainbowIndentsPass internal constructor(
} }
} }
while (!indents.isEmpty) { while (!indents.empty()) {
ProgressManager.checkCanceled() ProgressManager.checkCanceled()
val level = indents.popInt() val level = indents.pop()
val startLine = lines.popInt() val startLine = lines.pop()
if (level > 0) { if (level > 0) {
descriptors.add(createDescriptor(level, startLine, document.lineCount, lineIndents)) descriptors.add(createDescriptor(level, startLine, document.lineCount, lineIndents))
} }
@@ -210,12 +208,38 @@ class RainbowIndentsPass internal constructor(
return IndentGuideDescriptor(level, sLine, endLine) return IndentGuideDescriptor(level, sLine, endLine)
} }
/*
private fun findCodeConstructStart(startLine: Int): Int? {
val document = myEditor.document
val text = document.immutableCharSequence
val lineStartOffset = document.getLineStartOffset(startLine)
val firstNonWsOffset = CharArrayUtil.shiftForward(text, lineStartOffset, " \t")
val type = PsiUtilBase.getPsiFileAtOffset(myFile, firstNonWsOffset).fileType
val language = PsiUtilCore.getLanguageAtOffset(myFile, firstNonWsOffset)
val braceMatcher = BraceMatchingUtil.getBraceMatcher(type, language)
val iterator = myEditor.highlighter.createIterator(firstNonWsOffset)
return if (braceMatcher.isLBraceToken(iterator, text, type)) {
braceMatcher.getCodeConstructStart(myFile, firstNonWsOffset)
} else null
}
private fun findCodeConstructStartLine(startLine: Int): Int {
val codeConstructStart = findCodeConstructStart(startLine)
return if (codeConstructStart != null) myEditor.document.getLineNumber(codeConstructStart) else startLine
}
*/
private inner class IndentsCalculator { private inner class IndentsCalculator {
val myComments: MutableMap<String, TokenSet> = HashMap() val myComments: MutableMap<Language, TokenSet> = HashMap()
val lineIndents = IntArray(document.lineCount) // negative value means the line is empty (or contains a comment) and indent val lineIndents = IntArray(document.lineCount) // negative value means the line is empty (or contains a comment) and indent
// (denoted by absolute value) was deduced from enclosing non-empty lines // (denoted by absolute value) was deduced from enclosing non-empty lines
val myChars = document.charsSequence val myChars: CharSequence
init {
myChars = document.charsSequence
}
/** /**
* Calculates line indents for the [target document][.myDocument]. * Calculates line indents for the [target document][.myDocument].
@@ -293,7 +317,7 @@ class RainbowIndentsPass internal constructor(
return false return false
} }
val language = tokenType.language val language = tokenType.language
var comments: TokenSet? = myComments[language.id] var comments: TokenSet? = myComments[language]
if (comments == null) { if (comments == null) {
val definition = LanguageParserDefinitions.INSTANCE.forLanguage(language) val definition = LanguageParserDefinitions.INSTANCE.forLanguage(language)
if (definition != null) { if (definition != null) {
@@ -303,7 +327,7 @@ class RainbowIndentsPass internal constructor(
return false return false
} }
else { else {
myComments[language.id] = comments myComments[language] = comments
} }
} }
return comments.contains(tokenType) return comments.contains(tokenType)
@@ -1,22 +1,19 @@
package com.chylex.intellij.coloredbrackets.indents package com.github.izhangzhihao.rainbow.brackets.indents
import com.intellij.codeHighlighting.Pass import com.intellij.codeHighlighting.Pass
import com.intellij.codeHighlighting.TextEditorHighlightingPass
import com.intellij.codeHighlighting.TextEditorHighlightingPassFactory import com.intellij.codeHighlighting.TextEditorHighlightingPassFactory
import com.intellij.codeHighlighting.TextEditorHighlightingPassFactoryRegistrar import com.intellij.codeHighlighting.TextEditorHighlightingPassFactoryRegistrar
import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.impl.ImaginaryEditor
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
class RainbowIndentsPassFactory : class RainbowIndentsPassFactory :
TextEditorHighlightingPassFactoryRegistrar, TextEditorHighlightingPassFactory { TextEditorHighlightingPassFactoryRegistrar, TextEditorHighlightingPassFactory {
override fun createHighlightingPass(file: PsiFile, editor: Editor): RainbowIndentsPass? { override fun createHighlightingPass(file: PsiFile, editor: Editor): TextEditorHighlightingPass {
return when (editor) { return RainbowIndentsPass(file.project, editor, file)
is ImaginaryEditor -> null
else -> RainbowIndentsPass(file.project, editor, file)
}
} }
override fun registerHighlightingPassFactory(registrar: TextEditorHighlightingPassRegistrar, project: Project) { override fun registerHighlightingPassFactory(registrar: TextEditorHighlightingPassRegistrar, project: Project) {
@@ -1,6 +1,6 @@
package com.chylex.intellij.coloredbrackets.listener package com.github.izhangzhihao.rainbow.brackets.listener
import com.chylex.intellij.coloredbrackets.RainbowHighlighter import com.github.izhangzhihao.rainbow.brackets.RainbowHighlighter
import com.intellij.openapi.editor.colors.EditorColorsListener import com.intellij.openapi.editor.colors.EditorColorsListener
import com.intellij.openapi.editor.colors.EditorColorsScheme import com.intellij.openapi.editor.colors.EditorColorsScheme
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.provider package com.github.izhangzhihao.rainbow.brackets.provider
import com.intellij.lang.BracePair import com.intellij.lang.BracePair
@@ -0,0 +1,18 @@
package com.github.izhangzhihao.rainbow.brackets.provider
import com.intellij.lang.BracePair
import com.jetbrains.rider.ideaInterop.fileTypes.csharp.lexer.CSharpTokenType.GT
import com.jetbrains.rider.ideaInterop.fileTypes.csharp.lexer.CSharpTokenType.LBRACE
import com.jetbrains.rider.ideaInterop.fileTypes.csharp.lexer.CSharpTokenType.LBRACKET
import com.jetbrains.rider.ideaInterop.fileTypes.csharp.lexer.CSharpTokenType.LT
import com.jetbrains.rider.ideaInterop.fileTypes.csharp.lexer.CSharpTokenType.RBRACE
import com.jetbrains.rider.ideaInterop.fileTypes.csharp.lexer.CSharpTokenType.RBRACKET
class CSharpBracePairProvider : BracePairProvider {
override fun pairs(): List<BracePair> = listOf(
//BracePair(LPARENTH, RPARENTH, false),
BracePair(LBRACE, RBRACE, false),
BracePair(LBRACKET, RBRACKET, false),
BracePair(LT, GT, false),
)
}
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.provider package com.github.izhangzhihao.rainbow.brackets.provider
import com.intellij.lang.BracePair import com.intellij.lang.BracePair
import com.jetbrains.lang.dart.DartTokenTypes.GT import com.jetbrains.lang.dart.DartTokenTypes.GT
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.provider package com.github.izhangzhihao.rainbow.brackets.provider
import com.goide.template.GoTemplateTypes.LDOUBLE_BRACE import com.goide.template.GoTemplateTypes.LDOUBLE_BRACE
import com.goide.template.GoTemplateTypes.LPAREN import com.goide.template.GoTemplateTypes.LPAREN
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.provider package com.github.izhangzhihao.rainbow.brackets.provider
import com.intellij.lang.BracePair import com.intellij.lang.BracePair
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mGT import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mGT
@@ -1,9 +1,10 @@
package com.chylex.intellij.coloredbrackets.provider package com.github.izhangzhihao.rainbow.brackets.provider
import com.intellij.lang.BracePair import com.intellij.lang.BracePair
import org.jetbrains.kotlin.lexer.KtTokens.GT import org.jetbrains.kotlin.lexer.KtTokens.GT
import org.jetbrains.kotlin.lexer.KtTokens.LT import org.jetbrains.kotlin.lexer.KtTokens.LT
class KotlinBracePairProvider : BracePairProvider { class KotlinBracePairProvider : BracePairProvider {
override fun pairs(): List<BracePair> = listOf(BracePair(LT, GT, false)) override fun pairs(): List<BracePair> = listOf(BracePair(LT, GT, false))
} }
@@ -0,0 +1,8 @@
package com.github.izhangzhihao.rainbow.brackets.provider
import com.intellij.lang.BracePair
import com.jetbrains.cidr.lang.parser.OCTokenTypes
class OCBracePairProvider : BracePairProvider {
override fun pairs(): List<BracePair> = listOf(BracePair(OCTokenTypes.LT, OCTokenTypes.GT, false))
}
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.provider package com.github.izhangzhihao.rainbow.brackets.provider
import com.intellij.lang.BracePair import com.intellij.lang.BracePair
import com.jetbrains.php.lang.lexer.PhpTokenTypes import com.jetbrains.php.lang.lexer.PhpTokenTypes
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.provider package com.github.izhangzhihao.rainbow.brackets.provider
import com.intellij.lang.BracePair import com.intellij.lang.BracePair
import com.intellij.sh.ShTypes import com.intellij.sh.ShTypes
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.provider package com.github.izhangzhihao.rainbow.brackets.provider
import com.intellij.lang.BracePair import com.intellij.lang.BracePair
import com.intellij.sql.psi.SqlCommonKeywords.SQL_CASE import com.intellij.sql.psi.SqlCommonKeywords.SQL_CASE
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.provider package com.github.izhangzhihao.rainbow.brackets.provider
import com.intellij.lang.BracePair import com.intellij.lang.BracePair
import com.intellij.lang.javascript.JSTokenTypes.GT import com.intellij.lang.javascript.JSTokenTypes.GT
@@ -1,7 +1,7 @@
package com.chylex.intellij.coloredbrackets.settings package com.github.izhangzhihao.rainbow.brackets.settings
import com.chylex.intellij.coloredbrackets.RainbowHighlighter import com.github.izhangzhihao.rainbow.brackets.RainbowHighlighter
import com.chylex.intellij.coloredbrackets.settings.form.RainbowOptionsPanel import com.github.izhangzhihao.rainbow.brackets.settings.form.RainbowOptionsPanel
import com.intellij.application.options.colors.ColorAndFontOptions import com.intellij.application.options.colors.ColorAndFontOptions
import com.intellij.application.options.colors.ColorAndFontPanelFactory import com.intellij.application.options.colors.ColorAndFontPanelFactory
import com.intellij.application.options.colors.ColorAndFontSettingsListener import com.intellij.application.options.colors.ColorAndFontSettingsListener
@@ -14,6 +14,7 @@ import com.intellij.openapi.options.colors.ColorDescriptor
import com.intellij.psi.codeStyle.DisplayPriority import com.intellij.psi.codeStyle.DisplayPriority
import com.intellij.psi.codeStyle.DisplayPrioritySortable import com.intellij.psi.codeStyle.DisplayPrioritySortable
class RainbowColorsPageFactory : ColorAndFontPanelFactory, ColorAndFontDescriptorsProvider, DisplayPrioritySortable { class RainbowColorsPageFactory : ColorAndFontPanelFactory, ColorAndFontDescriptorsProvider, DisplayPrioritySortable {
override fun getDisplayName(): String = RAINBOW_BRACKETS_GROUP override fun getDisplayName(): String = RAINBOW_BRACKETS_GROUP
@@ -1,10 +1,8 @@
package com.chylex.intellij.coloredbrackets.settings package com.github.izhangzhihao.rainbow.brackets.settings
import com.chylex.intellij.coloredbrackets.settings.form.RainbowSettingsForm import com.github.izhangzhihao.rainbow.brackets.settings.form.RainbowSettingsForm
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
import com.intellij.openapi.options.ConfigurationException import com.intellij.openapi.options.ConfigurationException
import com.intellij.openapi.options.SearchableConfigurable import com.intellij.openapi.options.SearchableConfigurable
import com.intellij.openapi.project.ProjectManager
import org.jetbrains.annotations.Nls import org.jetbrains.annotations.Nls
import javax.swing.JComponent import javax.swing.JComponent
@@ -17,7 +15,7 @@ class RainbowConfigurable : SearchableConfigurable {
} }
override fun isModified(): Boolean { override fun isModified(): Boolean {
return settingsForm?.isModified ?: false return settingsForm?.isModified ?: return false
} }
@Throws(ConfigurationException::class) @Throws(ConfigurationException::class)
@@ -47,10 +45,6 @@ class RainbowConfigurable : SearchableConfigurable {
settings.doNOTRainbowifyBigFiles = settingsForm?.doNOTRainbowifyBigFiles() ?: true settings.doNOTRainbowifyBigFiles = settingsForm?.doNOTRainbowifyBigFiles() ?: true
settings.bigFilesLinesThreshold = settingsForm?.bigFilesLinesThreshold() ?: 1000 settings.bigFilesLinesThreshold = settingsForm?.bigFilesLinesThreshold() ?: 1000
settings.rainbowifyPythonKeywords = settingsForm?.rainbowifyPythonKeywords() ?: false settings.rainbowifyPythonKeywords = settingsForm?.rainbowifyPythonKeywords() ?: false
ProjectManager.getInstanceIfCreated()?.openProjects?.forEach {
DaemonCodeAnalyzer.getInstance(it).restart(this)
}
} }
override fun reset() { override fun reset() {
@@ -67,6 +61,6 @@ class RainbowConfigurable : SearchableConfigurable {
override fun getId(): String = ID override fun getId(): String = ID
companion object { companion object {
const val ID = "com.chylex.coloredbrackets.settings" const val ID = "preferences.rainbow.brackets"
} }
} }
@@ -1,14 +1,14 @@
package com.chylex.intellij.coloredbrackets.settings package com.github.izhangzhihao.rainbow.brackets.settings
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.PersistentStateComponent import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.SettingsCategory
import com.intellij.openapi.components.State import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage import com.intellij.openapi.components.Storage
import com.intellij.util.xmlb.XmlSerializerUtil import com.intellij.util.xmlb.XmlSerializerUtil.copyBean
import org.jetbrains.annotations.Nullable import org.jetbrains.annotations.Nullable
@State(name = "ColoredBracketsSettings", storages = [Storage("colored_brackets.xml")], category = SettingsCategory.UI)
@State(name = "RainbowSettings", storages = [(Storage("rainbow_brackets.xml"))])
class RainbowSettings : PersistentStateComponent<RainbowSettings> { class RainbowSettings : PersistentStateComponent<RainbowSettings> {
/** /**
* default value * default value
@@ -38,7 +38,7 @@ class RainbowSettings : PersistentStateComponent<RainbowSettings> {
var rainbowifyTagNameInXML = false var rainbowifyTagNameInXML = false
var doNOTRainbowifyTemplateString = false var doNOTRainbowifyTemplateString = false
var doNOTRainbowifyBigFiles = true var doNOTRainbowifyBigFiles = true
var bigFilesLinesThreshold = 100_000 var bigFilesLinesThreshold = 1000
var languageBlacklist: Set<String> = setOf("hocon", "mxml") var languageBlacklist: Set<String> = setOf("hocon", "mxml")
@@ -51,7 +51,7 @@ class RainbowSettings : PersistentStateComponent<RainbowSettings> {
override fun getState() = this override fun getState() = this
override fun loadState(state: RainbowSettings) { override fun loadState(state: RainbowSettings) {
XmlSerializerUtil.copyBean(state, this) copyBean(state, this)
} }
companion object { companion object {
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.chylex.intellij.coloredbrackets.settings.form.RainbowOptionsPanel"> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.github.izhangzhihao.rainbow.brackets.settings.form.RainbowOptionsPanel">
<grid id="d747" binding="rootPanel" layout-manager="BorderLayout" hgap="0" vgap="0"> <grid id="d747" binding="rootPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints> <constraints>
<xy x="20" y="20" width="500" height="400"/> <xy x="20" y="20" width="500" height="400"/>
@@ -1,7 +1,7 @@
package com.chylex.intellij.coloredbrackets.settings.form package com.github.izhangzhihao.rainbow.brackets.settings.form
import com.chylex.intellij.coloredbrackets.RainbowHighlighter import com.github.izhangzhihao.rainbow.brackets.RainbowHighlighter
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.intellij.application.options.colors.ColorAndFontOptions import com.intellij.application.options.colors.ColorAndFontOptions
import com.intellij.application.options.colors.ColorAndFontSettingsListener import com.intellij.application.options.colors.ColorAndFontSettingsListener
import com.intellij.application.options.colors.OptionsPanel import com.intellij.application.options.colors.OptionsPanel
@@ -22,6 +22,7 @@ import javax.swing.tree.DefaultTreeModel
import javax.swing.tree.TreePath import javax.swing.tree.TreePath
import javax.swing.tree.TreeSelectionModel import javax.swing.tree.TreeSelectionModel
class RainbowOptionsPanel( class RainbowOptionsPanel(
private val options: ColorAndFontOptions, private val options: ColorAndFontOptions,
private val schemesProvider: SchemesPanel, private val schemesProvider: SchemesPanel,
@@ -39,7 +40,7 @@ class RainbowOptionsPanel(
private lateinit var colorLabel4: JLabel private lateinit var colorLabel4: JLabel
private lateinit var colorLabel5: JLabel private lateinit var colorLabel5: JLabel
private val colorLabels = arrayOf(colorLabel1, colorLabel2, colorLabel3, colorLabel4, colorLabel5) private val colorLabels: Array<JLabel>
private lateinit var color1: ColorPanel private lateinit var color1: ColorPanel
private lateinit var color2: ColorPanel private lateinit var color2: ColorPanel
@@ -47,7 +48,7 @@ class RainbowOptionsPanel(
private lateinit var color4: ColorPanel private lateinit var color4: ColorPanel
private lateinit var color5: ColorPanel private lateinit var color5: ColorPanel
private val colors = arrayOf(color1, color2, color3, color4, color5) private val colors: Array<ColorPanel>
private lateinit var gradientLabel: JLabel private lateinit var gradientLabel: JLabel
@@ -56,6 +57,9 @@ class RainbowOptionsPanel(
EventDispatcher.create(ColorAndFontSettingsListener::class.java) EventDispatcher.create(ColorAndFontSettingsListener::class.java)
init { init {
colors = arrayOf(color1, color2, color3, color4, color5)
colorLabels = arrayOf(colorLabel1, colorLabel2, colorLabel3, colorLabel4, colorLabel5)
val actionListener = ActionListener { val actionListener = ActionListener {
eventDispatcher.multicaster.settingsChanged() eventDispatcher.multicaster.settingsChanged()
options.stateChanged() options.stateChanged()
@@ -67,9 +71,7 @@ class RainbowOptionsPanel(
options.addListener(object : ColorAndFontSettingsListener.Abstract() { options.addListener(object : ColorAndFontSettingsListener.Abstract() {
override fun settingsChanged() { override fun settingsChanged() {
if (!schemesProvider.areSchemesLoaded()) { if (!schemesProvider.areSchemesLoaded()) return
return
}
if (optionsTree.selectedValue != null) { if (optionsTree.selectedValue != null) {
// update options after global state change // update options after global state change
processListValueChanged() processListValueChanged()
@@ -170,6 +172,7 @@ class RainbowOptionsPanel(
} }
} }
override fun applyChangesToScheme() { override fun applyChangesToScheme() {
val scheme = options.selectedScheme val scheme = options.selectedScheme
val (rainbowName, descriptions) = optionsTree.selectedDescriptions ?: return val (rainbowName, descriptions) = optionsTree.selectedDescriptions ?: return
@@ -235,9 +238,7 @@ class RainbowOptionsPanel(
} }
val pathInChild = findOption(childObject, matcher) val pathInChild = findOption(childObject, matcher)
if (pathInChild != null) { if (pathInChild != null) return pathInChild
return pathInChild
}
} }
return null return null
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.chylex.intellij.coloredbrackets.settings.form.RainbowSettingsForm"> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.github.izhangzhihao.rainbow.brackets.settings.form.RainbowSettingsForm">
<grid id="27dc6" binding="panel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <grid id="27dc6" binding="panel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/> <margin top="0" left="0" bottom="0" right="0"/>
<constraints> <constraints>
@@ -1,6 +1,6 @@
package com.chylex.intellij.coloredbrackets.settings.form package com.github.izhangzhihao.rainbow.brackets.settings.form
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import javax.swing.JCheckBox import javax.swing.JCheckBox
import javax.swing.JComponent import javax.swing.JComponent
import javax.swing.JPanel import javax.swing.JPanel
@@ -8,7 +8,6 @@ import javax.swing.JTextField
class RainbowSettingsForm { class RainbowSettingsForm {
private var panel: JPanel? = null private var panel: JPanel? = null
@Suppress("unused") @Suppress("unused")
private var appearancePanel: JPanel? = null private var appearancePanel: JPanel? = null
private var enableRainbow: JCheckBox? = null private var enableRainbow: JCheckBox? = null
@@ -1,7 +1,8 @@
package com.chylex.intellij.coloredbrackets.util package com.github.izhangzhihao.rainbow.brackets.util
import java.awt.Color import java.awt.Color
fun Color.alphaBlend(background: Color, alpha: Float): Color { fun Color.alphaBlend(background: Color, alpha: Float): Color {
require(alpha in 0.0..1.0) { "alpha(0.0 <= alpha <= 1.0): $alpha" } require(alpha in 0.0..1.0) { "alpha(0.0 <= alpha <= 1.0): $alpha" }
@@ -1,5 +1,5 @@
package com.chylex.intellij.coloredbrackets.util package com.github.izhangzhihao.rainbow.brackets.util
import com.intellij.openapi.editor.Document import com.intellij.openapi.editor.Document
fun Document.lineNumber(offset: Int): Int? = if (offset in 0 until textLength) getLineNumber(offset) else null fun Document.lineNumber(offset: Int): Int? = if (offset in 0 until textLength) getLineNumber(offset) else null
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.util package com.github.izhangzhihao.rainbow.brackets.util
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
@@ -17,13 +17,14 @@ fun <A, B, C, R> ((A, B, C) -> R).memoize(): (A, B, C) -> R = object : (A, B, C)
override fun invoke(a: A, b: B, c: C) = m(MemoizeKey3(a, b, c)) override fun invoke(a: A, b: B, c: C) = m(MemoizeKey3(a, b, c))
} }
private interface MemoizedCall<in F, out R> { private interface MemoizedCall<in F, out R> {
operator fun invoke(f: F): R operator fun invoke(f: F): R
} }
private class MemoizedHandler<F, in K : MemoizedCall<F, R>, out R>(val f: F) { private class MemoizedHandler<F, in K : MemoizedCall<F, R>, out R>(val f: F) {
private val m = Platform.newConcurrentMap<K, R>() private val m = Platform.newConcurrentMap<K, R>()
operator fun invoke(k: K): R = m[k] ?: m.putSafely(k, k(f)) operator fun invoke(k: K): R = m[k] ?: run { m.putSafely(k, k(f)) }
} }
private data class MemoizeKey1<out A, R>(val a: A) : MemoizedCall<(A) -> R, R> { private data class MemoizeKey1<out A, R>(val a: A) : MemoizedCall<(A) -> R, R> {
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.util package com.github.izhangzhihao.rainbow.brackets.util
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.util package com.github.izhangzhihao.rainbow.brackets.util
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
@@ -1,5 +1,6 @@
package com.chylex.intellij.coloredbrackets.util package com.github.izhangzhihao.rainbow.brackets.util
fun fileExtension(fileName: String) = fileName.substring(fileName.lastIndexOf(".") + 1) fun fileExtension(fileName: String) = fileName.substring(fileName.lastIndexOf(".") + 1)
val memoizedFileExtension = { fileName: String -> fileExtension(fileName) }.memoize() val memoizedFileExtension = { fileName: String -> fileExtension(fileName) }.memoize()
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.util package com.github.izhangzhihao.rainbow.brackets.util
import com.intellij.openapi.editor.colors.TextAttributesKey import com.intellij.openapi.editor.colors.TextAttributesKey
import com.intellij.openapi.editor.markup.TextAttributes import com.intellij.openapi.editor.markup.TextAttributes
@@ -0,0 +1,134 @@
package com.github.izhangzhihao.rainbow.brackets.visitor
import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.intellij.codeInsight.daemon.impl.HighlightVisitor
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.jetbrains.rider.ideaInterop.fileTypes.csharp.lexer.CSharpTokenType.LPARENTH
import com.jetbrains.rider.ideaInterop.fileTypes.csharp.lexer.CSharpTokenType.RPARENTH
import com.jetbrains.rider.ideaInterop.fileTypes.csharp.psi.CSharpDummyNode
class CSharpRainbowVisitor : RainbowHighlightVisitor() {
override fun suitableForFile(file: PsiFile)
: Boolean = super.suitableForFile(file) &&
RainbowSettings.instance.isEnableRainbowAngleBrackets &&
(file.language.id == "C#" ||
file.viewProvider.allFiles.any { it.language.id == "C#" }
)
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(
LPARENTH to BracePair(LPARENTH, RPARENTH, true),
RPARENTH to BracePair(LPARENTH, 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,181 @@
package com.github.izhangzhihao.rainbow.brackets.visitor
import com.github.izhangzhihao.rainbow.brackets.bracePairs
import com.github.izhangzhihao.rainbow.brackets.braceTypeSet
import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.intellij.codeInsight.daemon.impl.HighlightVisitor
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
class DefaultRainbowVisitor : RainbowHighlightVisitor() {
override fun clone(): HighlightVisitor = DefaultRainbowVisitor()
override fun visit(element: PsiElement) {
val type = (element as? LeafPsiElement)?.elementType ?: return
val matching = filterPairs(type, element) ?: return
val pair =
if (matching.size == 1) {
matching[0]
}
else {
matching.find { element.isValidBracket(it) }
} ?: return
val level = element.getBracketLevel(pair)
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 {
private fun LeafPsiElement.getBracketLevel(pair: BracePair): Int = iterateBracketParents(parent, pair, -1)
private tailrec fun iterateBracketParents(element: PsiElement?, pair: BracePair, count: Int): Int {
if (element == null || element is PsiFile) {
return count
}
var nextCount = count
if (!RainbowSettings.instance.cycleCountOnAllBrackets) {
if (element.haveBrackets(
{ it.elementType() == pair.leftBraceType },
{ it.elementType() == pair.rightBraceType })
) {
nextCount++
}
}
else {
if (element.haveBrackets(
{ element.language.braceTypeSet.contains(it.elementType()) },
{ element.language.braceTypeSet.contains(it.elementType()) })
) {
nextCount++
}
}
return iterateBracketParents(element.parent, pair, nextCount)
}
private inline fun PsiElement.haveBrackets(
checkLeft: (PsiElement) -> Boolean,
checkRight: (PsiElement) -> Boolean,
): Boolean {
if (this is LeafPsiElement) {
return false
}
var findLeftBracket = false
var findRightBracket = false
var left: PsiElement? = firstChild
var right: PsiElement? = lastChild
while (left != right && (!findLeftBracket || !findRightBracket)) {
val needBreak = left == null || left.nextSibling == right
if (left is LeafPsiElement && checkLeft(left)) {
findLeftBracket = true
}
else {
left = left?.nextSibling
}
if (right is LeafPsiElement && checkRight(right)) {
findRightBracket = true
}
else {
right = right?.prevSibling
}
if (needBreak) {
break
}
}
//For https://github.com/izhangzhihao/intellij-rainbow-brackets/issues/830
if (RainbowSettings.instance.doNOTRainbowifyTemplateString) {
if (left?.prevSibling?.textMatches("$") == true) return false
}
return findLeftBracket && findRightBracket
}
private fun PsiElement.elementType(): IElementType? {
return (this as? LeafPsiElement)?.elementType
}
private fun LeafPsiElement.isValidBracket(pair: BracePair): Boolean {
val pairType = when (elementType) {
pair.leftBraceType -> pair.rightBraceType
pair.rightBraceType -> pair.leftBraceType
else -> return false
}
return if (pairType == pair.leftBraceType) {
checkBracePair(this, parent.firstChild, pairType, PsiElement::getNextSibling)
}
else {
checkBracePair(this, parent.lastChild, pairType, PsiElement::getPrevSibling)
}
}
private fun checkBracePair(
brace: PsiElement,
start: PsiElement,
type: IElementType,
next: PsiElement.() -> PsiElement?,
): Boolean {
var element: PsiElement? = start
while (element != null && element != brace) {
if (element is LeafPsiElement && element.elementType == type) {
return true
}
element = element.next()
}
return false
}
private fun filterPairs(type: IElementType, element: LeafPsiElement): List<BracePair>? {
val pairs = element.language.bracePairs ?: return null
val filterBraceType = pairs[type.toString()]
return when {
filterBraceType.isNullOrEmpty() -> {
null
}
// https://github.com/izhangzhihao/intellij-rainbow-brackets/issues/198
element.javaClass.simpleName == "OCMacroForeignLeafElement" -> {
null
}
RainbowSettings.instance.isDoNOTRainbowifyBracketsWithoutContent -> {
filterBraceType
.filterNot { it.leftBraceType == type && element.nextSibling?.elementType() == it.rightBraceType }
.filterNot { it.rightBraceType == type && element.prevSibling?.elementType() == it.leftBraceType }
}
else -> {
filterBraceType
}
}
}
}
}
@@ -1,8 +1,8 @@
package com.chylex.intellij.coloredbrackets.visitor package com.github.izhangzhihao.rainbow.brackets.visitor
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.chylex.intellij.coloredbrackets.visitor.XmlRainbowVisitor.Companion.iterateXmlTagParents import com.github.izhangzhihao.rainbow.brackets.visitor.XmlRainbowVisitor.Companion.iterateXmlTagParents
import com.chylex.intellij.coloredbrackets.visitor.XmlRainbowVisitor.Companion.xmlParent import com.github.izhangzhihao.rainbow.brackets.visitor.XmlRainbowVisitor.Companion.xmlParent
import com.intellij.codeInsight.daemon.impl.HighlightVisitor import com.intellij.codeInsight.daemon.impl.HighlightVisitor
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
@@ -10,6 +10,7 @@ import com.intellij.psi.xml.XmlTag
import com.intellij.psi.xml.XmlToken import com.intellij.psi.xml.XmlToken
import com.intellij.psi.xml.XmlTokenType import com.intellij.psi.xml.XmlTokenType
class PugRainbowVisitor : RainbowHighlightVisitor() { class PugRainbowVisitor : RainbowHighlightVisitor() {
override fun suitableForFile(file: PsiFile) override fun suitableForFile(file: PsiFile)
@@ -1,6 +1,6 @@
package com.chylex.intellij.coloredbrackets.visitor package com.github.izhangzhihao.rainbow.brackets.visitor
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.intellij.codeInsight.daemon.impl.HighlightVisitor import com.intellij.codeInsight.daemon.impl.HighlightVisitor
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
@@ -23,6 +23,7 @@ import com.jetbrains.python.PyTokenTypes.WITH_KEYWORD
import com.jetbrains.python.PyTokenTypes.YIELD_KEYWORD import com.jetbrains.python.PyTokenTypes.YIELD_KEYWORD
import com.jetbrains.python.psi.PyStatement import com.jetbrains.python.psi.PyStatement
class PythonRainbowVisitor : RainbowHighlightVisitor() { class PythonRainbowVisitor : RainbowHighlightVisitor() {
override fun suitableForFile(file: PsiFile) override fun suitableForFile(file: PsiFile)
@@ -1,12 +1,14 @@
package com.chylex.intellij.coloredbrackets.visitor package com.github.izhangzhihao.rainbow.brackets.visitor
import com.chylex.intellij.coloredbrackets.RainbowHighlighter.getHighlightInfo import com.github.izhangzhihao.rainbow.brackets.RainbowHighlighter.getHighlightInfo
import com.chylex.intellij.coloredbrackets.RainbowInfo import com.github.izhangzhihao.rainbow.brackets.RainbowInfo
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.chylex.intellij.coloredbrackets.util.memoizedFileExtension import com.github.izhangzhihao.rainbow.brackets.util.memoizedFileExtension
import com.intellij.codeInsight.daemon.impl.HighlightVisitor import com.intellij.codeInsight.daemon.impl.HighlightVisitor
import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.openapi.editor.colors.EditorColorsManager import com.intellij.openapi.editor.colors.EditorColorsManager
import com.intellij.openapi.extensions.PluginId
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiDocumentManager
@@ -14,17 +16,17 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import java.awt.Color import java.awt.Color
abstract class RainbowHighlightVisitor : HighlightVisitor { abstract class RainbowHighlightVisitor : HighlightVisitor {
private var highlightInfoHolder: HighlightInfoHolder? = null private var highlightInfoHolder: HighlightInfoHolder? = null
override fun suitableForFile(file: PsiFile): Boolean { override fun suitableForFile(file: PsiFile): Boolean {
val settings = RainbowSettings.instance return RainbowSettings.instance.isRainbowEnabled &&
return settings.isRainbowEnabled &&
checkForBigFile(file) && checkForBigFile(file) &&
!settings.languageBlacklist.contains(file.fileType.name) && !RainbowSettings.instance.languageBlacklist.contains(file.fileType.name) &&
!settings.languageBlacklist.contains(memoizedFileExtension(file.name)) !RainbowSettings.instance.languageBlacklist.contains(memoizedFileExtension(file.name)) &&
fileIsNotHaskellOrIntelliJHaskellPluginNotEnabled(file.fileType.name)
} }
final override fun analyze(file: PsiFile, updateWholeFile: Boolean, holder: HighlightInfoHolder, action: Runnable): Boolean { final override fun analyze(file: PsiFile, updateWholeFile: Boolean, holder: HighlightInfoHolder, action: Runnable): Boolean {
@@ -32,6 +34,7 @@ abstract class RainbowHighlightVisitor : HighlightVisitor {
onBeforeAnalyze(file, updateWholeFile) onBeforeAnalyze(file, updateWholeFile)
try { try {
action.run() action.run()
} catch (e: Throwable) {
} finally { } finally {
onAfterAnalyze() onAfterAnalyze()
} }
@@ -81,28 +84,36 @@ abstract class RainbowHighlightVisitor : HighlightVisitor {
} }
companion object { companion object {
private val isIntelliJHaskellEnabled: Boolean by lazy {
PluginManagerCore.getPlugin(
PluginId.getId("intellij.haskell")
)?.isEnabled ?: false
}
fun checkForBigFile(file: PsiFile): Boolean = fun checkForBigFile(file: PsiFile): Boolean =
!(RainbowSettings.instance.doNOTRainbowifyBigFiles && !(RainbowSettings.instance.doNOTRainbowifyBigFiles &&
file.getLineCount() > RainbowSettings.instance.bigFilesLinesThreshold) file.getLineCount() > RainbowSettings.instance.bigFilesLinesThreshold)
private fun PsiElement.getLineCount(): Int { private fun fileIsNotHaskellOrIntelliJHaskellPluginNotEnabled(fileType: String) =
try { fileType != "Haskell" || !isIntelliJHaskellEnabled
val doc = containingFile?.let { PsiDocumentManager.getInstance(project).getDocument(it) } }
if (doc != null) { }
val spaceRange = textRange ?: TextRange.EMPTY_RANGE
fun PsiElement.getLineCount(): Int {
if (spaceRange.endOffset <= doc.textLength && spaceRange.startOffset < spaceRange.endOffset) { try {
val startLine = doc.getLineNumber(spaceRange.startOffset) val doc = containingFile?.let { PsiDocumentManager.getInstance(project).getDocument(it) }
val endLine = doc.getLineNumber(spaceRange.endOffset - 1) if (doc != null) {
val spaceRange = textRange ?: TextRange.EMPTY_RANGE
return endLine - startLine + 1
} if (spaceRange.endOffset <= doc.textLength && spaceRange.startOffset < spaceRange.endOffset) {
} val startLine = doc.getLineNumber(spaceRange.startOffset)
return StringUtil.getLineBreakCount(text ?: "") + 1 val endLine = doc.getLineNumber(spaceRange.endOffset - 1)
} catch (e: Throwable) {
return 0 return endLine - startLine + 1
} }
} }
return StringUtil.getLineBreakCount(text ?: "") + 1
} catch (e: Throwable) {
return 0
} }
} }
@@ -1,4 +1,4 @@
package com.chylex.intellij.coloredbrackets.visitor package com.github.izhangzhihao.rainbow.brackets.visitor
import com.intellij.codeInsight.daemon.impl.HighlightVisitor import com.intellij.codeInsight.daemon.impl.HighlightVisitor
import com.intellij.lang.javascript.DialectDetector import com.intellij.lang.javascript.DialectDetector
@@ -1,6 +1,6 @@
package com.chylex.intellij.coloredbrackets.visitor package com.github.izhangzhihao.rainbow.brackets.visitor
import com.chylex.intellij.coloredbrackets.settings.RainbowSettings import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
import com.intellij.codeInsight.daemon.impl.HighlightVisitor import com.intellij.codeInsight.daemon.impl.HighlightVisitor
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
@@ -9,6 +9,7 @@ import com.intellij.psi.xml.XmlTag
import com.intellij.psi.xml.XmlToken import com.intellij.psi.xml.XmlToken
import com.intellij.psi.xml.XmlTokenType import com.intellij.psi.xml.XmlTokenType
open class XmlRainbowVisitor : RainbowHighlightVisitor() { open class XmlRainbowVisitor : RainbowHighlightVisitor() {
override fun suitableForFile(file: PsiFile) override fun suitableForFile(file: PsiFile)
+9
View File
@@ -0,0 +1,9 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<highlightVisitor implementation="com.github.izhangzhihao.rainbow.brackets.visitor.ReactJSXRainbowVisitor" />
</extensions>
<extensions defaultExtensionNs="com.chylex.coloredbrackets">
<bracePairProvider language="JavaScript"
implementationClass="com.github.izhangzhihao.rainbow.brackets.provider.TSBracePairProvider" />
</extensions>
</idea-plugin>
@@ -0,0 +1,5 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<annotator language="C#" implementationClass="com.github.izhangzhihao.rainbow.brackets.annotator.RainbowAnnotator" />
</extensions>
</idea-plugin>
@@ -0,0 +1,10 @@
<idea-plugin>
<extensions defaultExtensionNs="com.chylex.coloredbrackets">
<bracePairProvider language="C#"
implementationClass="com.github.izhangzhihao.rainbow.brackets.provider.CSharpBracePairProvider" />
</extensions>
<extensions defaultExtensionNs="com.intellij">
<highlightVisitor implementation="com.github.izhangzhihao.rainbow.brackets.visitor.CSharpRainbowVisitor" />
</extensions>
</idea-plugin>
@@ -1,6 +1,6 @@
<idea-plugin> <idea-plugin>
<extensions defaultExtensionNs="com.chylex.coloredbrackets"> <extensions defaultExtensionNs="com.chylex.coloredbrackets">
<bracePairProvider language="Dart" <bracePairProvider language="Dart"
implementationClass="com.chylex.intellij.coloredbrackets.provider.DartBracePairProvider" /> implementationClass="com.github.izhangzhihao.rainbow.brackets.provider.DartBracePairProvider" />
</extensions> </extensions>
</idea-plugin> </idea-plugin>
@@ -1,6 +1,6 @@
<idea-plugin> <idea-plugin>
<extensions defaultExtensionNs="com.chylex.coloredbrackets"> <extensions defaultExtensionNs="com.chylex.coloredbrackets">
<bracePairProvider language="GoTemplate" <bracePairProvider language="GoTemplate"
implementationClass="com.chylex.intellij.coloredbrackets.provider.GoTemplateProvider" /> implementationClass="com.github.izhangzhihao.rainbow.brackets.provider.GoTemplateProvider" />
</extensions> </extensions>
</idea-plugin> </idea-plugin>
@@ -1,6 +1,6 @@
<idea-plugin> <idea-plugin>
<extensions defaultExtensionNs="com.chylex.coloredbrackets"> <extensions defaultExtensionNs="com.chylex.coloredbrackets">
<bracePairProvider language="Groovy" <bracePairProvider language="Groovy"
implementationClass="com.chylex.intellij.coloredbrackets.provider.GroovyBracePairProvider" /> implementationClass="com.github.izhangzhihao.rainbow.brackets.provider.GroovyBracePairProvider" />
</extensions> </extensions>
</idea-plugin> </idea-plugin>
@@ -0,0 +1,5 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<annotator language="Haskell" implementationClass="com.github.izhangzhihao.rainbow.brackets.annotator.RainbowAnnotator" />
</extensions>
</idea-plugin>
@@ -0,0 +1,5 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<highlightVisitor implementation="com.github.izhangzhihao.rainbow.brackets.visitor.PugRainbowVisitor" />
</extensions>
</idea-plugin>

Some files were not shown because too many files have changed in this diff Show More