11package dev.zbinski.htmlattributefolder
22
33import com.intellij.psi.PsiElement
4- import kotlinx.coroutines.runBlocking
54
65import com.intellij.openapi.util.TextRange
76import com.intellij.openapi.editor.Document
@@ -12,12 +11,20 @@ import com.intellij.lang.ASTNode
1211import com.intellij.lang.folding.FoldingBuilderEx
1312import com.intellij.lang.folding.FoldingDescriptor
1413
14+ private data class AttributePrefix (val name : String , val doubleQuote : String , val singleQuote : String , val brace : String )
15+
1516class AttributeFolder : FoldingBuilderEx (), DumbAware {
1617 private val settings = AttributeFolderState .instance
1718
18- override fun buildFoldRegions (root : PsiElement , document : Document , quick : Boolean ): Array <FoldingDescriptor > = runBlocking {
19+ override fun buildFoldRegions (root : PsiElement , document : Document , quick : Boolean ): Array <FoldingDescriptor > {
20+ val attributes = settings.attributes
21+ val prefixes = attributes.map { name ->
22+ AttributePrefix (name, " $name =\" " , " $name ='" , " $name ={" )
23+ }
24+ val minPrefixLen = prefixes.minOfOrNull { minOf(it.doubleQuote.length, it.singleQuote.length, it.brace.length) } ? : return emptyArray()
25+
1926 val descriptors = ArrayList <FoldingDescriptor >()
20- for (item in getAttributes(Array (1 ) { root })) {
27+ for (item in getAttributes(Array (1 ) { root }, prefixes, minPrefixLen )) {
2128 var end: Int
2229 var start: Int
2330
@@ -80,7 +87,7 @@ class AttributeFolder: FoldingBuilderEx(), DumbAware {
8087 }
8188 }
8289
83- return @runBlocking descriptors.toTypedArray()
90+ return descriptors.toTypedArray()
8491 }
8592
8693 override fun getPlaceholderText (node : ASTNode ): String {
@@ -116,28 +123,28 @@ class AttributeFolder: FoldingBuilderEx(), DumbAware {
116123
117124 private fun getAttributes (
118125 elements : Array <PsiElement >,
119- attributes : ArrayList <String > = settings.attributes
126+ prefixes : List <AttributePrefix >,
127+ minPrefixLen : Int
120128 ): Sequence <Attribute > = sequence {
121129 for (child in elements) {
122- val t = child.text
123- for (attributeName in attributes) {
124- val startsLikeAttribute =
125- t.startsWith(" $attributeName =\" " ) ||
126- t.startsWith(" $attributeName ='" ) ||
127- t.startsWith(" $attributeName ={" )
128-
129- if (startsLikeAttribute) {
130- yield (object : Attribute {
131- override val attribute = child
132- override val attributeName = attributeName
133- })
130+ if (child.textLength >= minPrefixLen) {
131+ val t = child.text
132+ for (prefix in prefixes) {
133+ val startsLikeAttribute =
134+ t.startsWith(prefix.doubleQuote) ||
135+ t.startsWith(prefix.singleQuote) ||
136+ t.startsWith(prefix.brace)
137+
138+ if (startsLikeAttribute) {
139+ yield (object : Attribute {
140+ override val attribute = child
141+ override val attributeName = prefix.name
142+ })
143+ }
134144 }
135145 }
136146
137- val items = getAttributes(child.children, attributes).iterator()
138- while (items.hasNext()) {
139- yield (items.next())
140- }
147+ yieldAll(getAttributes(child.children, prefixes, minPrefixLen))
141148 }
142149 }
143- }
150+ }
0 commit comments