@@ -10,6 +10,7 @@ import com.intellij.psi.LiteralTextEscaper
10
10
import com.intellij.psi.PsiElement
11
11
import com.intellij.psi.PsiLanguageInjectionHost
12
12
import com.intellij.psi.impl.source.tree.injected.InjectionBackgroundSuppressor
13
+ import com.intellij.psi.templateLanguages.OuterLanguageElement
13
14
import com.intellij.psi.tree.IElementType
14
15
import com.intellij.psi.util.*
15
16
@@ -32,36 +33,43 @@ class CodeBlockElement(node: ASTNode) : ASTWrapperPsiElement(node), PsiLanguageI
32
33
return findChildByType(DevInTypes .LANGUAGE_ID )
33
34
}
34
35
35
- fun getContents (): List < PsiElement > {
36
- return obtainFenceContent( this , withWhitespaces = false ) ? : return emptyList( )
36
+ fun getContents (): PsiElement ? {
37
+ return findChildByType( DevInTypes . CODE_CONTENTS )
37
38
}
38
39
39
40
companion object {
40
- fun obtainFenceContent (element : CodeBlockElement , withWhitespaces : Boolean ): List <PsiElement >? {
41
- return when {
42
- withWhitespaces -> CachedValuesManager .getCachedValue(element) {
43
- CachedValueProvider .Result .create(getContent(element, true ), element)
44
- }
45
- else -> CachedValuesManager .getCachedValue(element) {
46
- CachedValueProvider .Result .create(getContent(element, false ), element)
47
- }
41
+ fun obtainFenceContent (element : CodeBlockElement ): List <PsiElement >? {
42
+ return CachedValuesManager .getCachedValue(element) {
43
+ CachedValueProvider .Result .create(getContent(element), element)
48
44
}
49
45
}
50
46
51
- private fun getContent (element : CodeBlockElement , withWhitespaces : Boolean ): List <PsiElement >? {
52
- val codeContents = element.children.firstOrNull { it.elementType == DevInTypes .CODE_CONTENTS } ? : return null
47
+ private fun getContent (host : CodeBlockElement ): List <PsiElement >? {
48
+ val children = host.firstChild
49
+ ?.siblings(forward = true , withSelf = true ) ? : return null
50
+
51
+ val elements =
52
+ children.filter {
53
+ it !is OuterLanguageElement
54
+ && (it.node.elementType == DevInTypes .CODE_CONTENTS || it == DevInTypes .NEWLINE )
55
+ }
56
+ .toList()
53
57
54
- val psiElements = PsiTreeUtil .collectElements(codeContents) {
55
- it.elementType == DevInTypes .CODE_CONTENT
56
- }.toMutableList()
58
+ if (elements.isNotEmpty() && elements.first() == DevInTypes .NEWLINE ) {
59
+ elements.drop(1 )
60
+ }
61
+ if (elements.isNotEmpty() && elements.last() == DevInTypes .NEWLINE ) {
62
+ elements.dropLast(1 )
63
+ }
57
64
58
- return psiElements.toList()
65
+ return elements. takeIf { it.isNotEmpty() }
59
66
}
60
67
61
68
fun obtainRelevantTextRange (element : CodeBlockElement ): TextRange {
62
- val elements = obtainFenceContent(element, withWhitespaces = true ) ? : return getEmptyRange(element)
69
+ val elements = obtainFenceContent(element) ? : return getEmptyRange(element)
63
70
val first = elements.first()
64
71
val last = elements.last()
72
+
65
73
return TextRange .create(first.startOffsetInParent, last.startOffsetInParent + last.textLength)
66
74
}
67
75
@@ -82,27 +90,26 @@ class CodeBlockLiteralTextEscaper(host: CodeBlockElement) : LiteralTextEscaper<C
82
90
override fun isOneLine (): Boolean = false ;
83
91
84
92
override fun decode (rangeInsideHost : TextRange , outChars : StringBuilder ): Boolean {
85
- val elements = CodeBlockElement .obtainFenceContent(myHost, withWhitespaces = false ) ? : return true
93
+ val elements = CodeBlockElement .obtainFenceContent(myHost) ? : return true
86
94
for (element in elements) {
87
95
val intersected = rangeInsideHost.intersection(element.textRangeInParent) ? : continue
88
96
outChars.append(intersected.substring(myHost.text))
89
97
}
98
+
90
99
return true
91
100
}
92
101
93
102
override fun getOffsetInHost (offsetInDecoded : Int , rangeInsideHost : TextRange ): Int {
94
- val elements = CodeBlockElement .obtainFenceContent(myHost, withWhitespaces = false ) ? : return - 1
103
+ val elements = CodeBlockElement .obtainFenceContent(myHost) ? : return - 1
95
104
var cur = 0
96
105
for (element in elements) {
97
106
val intersected = rangeInsideHost.intersection(element.textRangeInParent)
98
107
if (intersected == null || intersected.isEmpty) continue
99
108
if (cur + intersected.length == offsetInDecoded) {
100
109
return intersected.startOffset + intersected.length
101
- }
102
- else if (cur == offsetInDecoded) {
110
+ } else if (cur == offsetInDecoded) {
103
111
return intersected.startOffset
104
- }
105
- else if (cur < offsetInDecoded && cur + intersected.length > offsetInDecoded) {
112
+ } else if (cur < offsetInDecoded && cur + intersected.length > offsetInDecoded) {
106
113
return intersected.startOffset + (offsetInDecoded - cur)
107
114
}
108
115
cur + = intersected.length
@@ -114,8 +121,7 @@ class CodeBlockLiteralTextEscaper(host: CodeBlockElement) : LiteralTextEscaper<C
114
121
val result = intersected.startOffset + (offsetInDecoded - (cur - intersected.length))
115
122
return if (rangeInsideHost.startOffset <= result && result <= rangeInsideHost.endOffset) {
116
123
result
117
- }
118
- else - 1
124
+ } else - 1
119
125
}
120
126
121
127
override fun getRelevantTextRange (): TextRange {
0 commit comments