string stuff cleanup and bugfixes
This commit is contained in:
parent
cd474221a6
commit
431e09830f
4 changed files with 67 additions and 65 deletions
|
@ -1,8 +1,6 @@
|
|||
package com.falsepattern.zigbrains.zig.intentions
|
||||
|
||||
import com.falsepattern.zigbrains.zig.psi.ZigStringLiteral
|
||||
import com.falsepattern.zigbrains.zig.psi.component1
|
||||
import com.falsepattern.zigbrains.zig.psi.component2
|
||||
import com.falsepattern.zigbrains.zig.util.escape
|
||||
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
|
@ -29,8 +27,12 @@ class MakeStringQuoted: PsiElementBaseIntentionAction() {
|
|||
if (!str.isMultiline)
|
||||
return
|
||||
val escaper = str.createLiteralTextEscaper()
|
||||
val (contentStart, contentEnd) = escaper.relevantTextRange
|
||||
val (fullStart, fullEnd) = str.textRange
|
||||
val contentRange = escaper.relevantTextRange
|
||||
val contentStart = contentRange.startOffset
|
||||
val contentEnd = contentRange.endOffset
|
||||
val fullRange = str.textRange
|
||||
val fullStart = fullRange.startOffset
|
||||
val fullEnd = fullRange.endOffset
|
||||
var caretOffset = editor.caretModel.offset
|
||||
val prefix = TextRange(contentStart, max(contentStart, caretOffset - fullStart))
|
||||
val suffix = TextRange(min(contentEnd, caretOffset - fullStart), contentEnd)
|
||||
|
|
|
@ -13,48 +13,58 @@ import com.intellij.psi.StringEscapesTokenTypes
|
|||
import com.intellij.util.MathUtil
|
||||
import kotlin.math.max
|
||||
|
||||
|
||||
fun getTextRangeBounds(contentRanges: List<TextRange>): TextRange =
|
||||
if (contentRanges.isEmpty())
|
||||
TextRange.EMPTY_RANGE
|
||||
else
|
||||
TextRange.create(contentRanges.first().startOffset, contentRanges.last().endOffset)
|
||||
|
||||
fun CharSequence.getMultiLineContent(startMark: String): List<TextRange> {
|
||||
fun CharSequence.getMultilineContent(startMark: String): List<TextRange> {
|
||||
val result = ArrayList<TextRange>()
|
||||
val textLength = this.length
|
||||
val markLength = startMark.length
|
||||
var offset = 0
|
||||
|
||||
while (offset < textLength) {
|
||||
val markIndex = this.indexOf(startMark, offset)
|
||||
if (markIndex < 0)
|
||||
break
|
||||
val stringStart = markIndex + markLength
|
||||
|
||||
var found: Int? = null
|
||||
findEnd@ for (end in stringStart until textLength) {
|
||||
val cI = this[end]
|
||||
when (cI) {
|
||||
'\r' -> {
|
||||
if (end + 1 < textLength && this[end + 1] == '\n') {
|
||||
found = end + 2
|
||||
break@findEnd
|
||||
var stringStart = 0
|
||||
var inBody = false
|
||||
val textLength = length
|
||||
val firstChar = startMark[0]
|
||||
val extraChars = startMark.substring(1)
|
||||
var i = 0
|
||||
loop@ while (i < textLength) {
|
||||
val cI = this[i]
|
||||
if (!inBody) {
|
||||
if (cI == firstChar &&
|
||||
i + extraChars.length < textLength
|
||||
) {
|
||||
for (j in extraChars.indices) {
|
||||
if (this[i + j + 1] != startMark[j]) {
|
||||
i++
|
||||
continue@loop
|
||||
}
|
||||
found = end + 1
|
||||
break@findEnd
|
||||
}
|
||||
|
||||
'\n' -> {
|
||||
found = end + 1
|
||||
break@findEnd
|
||||
}
|
||||
i += extraChars.length
|
||||
inBody = true
|
||||
stringStart = i + 1
|
||||
}
|
||||
} else if (cI == '\r') {
|
||||
if (i + 1 < length && this[i + 1] == '\n') {
|
||||
i++
|
||||
}
|
||||
inBody = false
|
||||
result.add(
|
||||
TextRange(
|
||||
stringStart,
|
||||
kotlin.math.min((textLength - 1), (i + 1))
|
||||
)
|
||||
)
|
||||
} else if (cI == '\n') {
|
||||
inBody = false
|
||||
result.add(
|
||||
TextRange(
|
||||
stringStart,
|
||||
kotlin.math.min((textLength - 1), (i + 1))
|
||||
)
|
||||
)
|
||||
}
|
||||
if (found == null)
|
||||
break
|
||||
|
||||
result.add(TextRange(stringStart, kotlin.math.min(textLength - 1, found)))
|
||||
offset = found
|
||||
i++
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
@ -73,7 +83,9 @@ fun splitString(
|
|||
val token = psiAtOffset.node
|
||||
val text = document.charsSequence
|
||||
|
||||
val (rangeStart, rangeEnd) = token.textRange
|
||||
val range = token.textRange
|
||||
val rangeStart = range.startOffset
|
||||
val rangeEnd = range.endOffset
|
||||
val lexer = ZigLexerStringAdapter()
|
||||
lexer.start(text, rangeStart, rangeEnd)
|
||||
caretOffset = lexer.skipStringLiteralEscapes(caretOffset)
|
||||
|
@ -141,12 +153,3 @@ private fun Lexer.skipStringLiteralEscapes(caretOffset: Int): Int {
|
|||
}
|
||||
return caretOffset
|
||||
}
|
||||
|
||||
|
||||
operator fun Segment.component1(): Int {
|
||||
return startOffset
|
||||
}
|
||||
|
||||
operator fun Segment.component2(): Int {
|
||||
return endOffset
|
||||
}
|
|
@ -8,7 +8,6 @@ import com.intellij.lang.ASTNode
|
|||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.LiteralTextEscaper
|
||||
import com.intellij.psi.impl.source.tree.LeafElement
|
||||
import java.lang.StringBuilder
|
||||
|
||||
abstract class ZigStringLiteralMixinImpl(node: ASTNode): ASTWrapperPsiElement(node), ZigStringLiteral {
|
||||
override fun isValidHost() = true
|
||||
|
@ -20,7 +19,7 @@ abstract class ZigStringLiteralMixinImpl(node: ASTNode): ASTWrapperPsiElement(no
|
|||
get() = if (!isMultiline) {
|
||||
listOf(TextRange(1, textLength - 1))
|
||||
} else {
|
||||
text.getMultiLineContent("\\\\")
|
||||
text.getMultilineContent("\\\\")
|
||||
}
|
||||
|
||||
override fun updateText(text: String): ZigStringLiteral {
|
||||
|
@ -60,33 +59,30 @@ abstract class ZigStringLiteralMixinImpl(node: ASTNode): ASTWrapperPsiElement(no
|
|||
var currentOffsetInDecoded = 0
|
||||
|
||||
var last: TextRange? = null
|
||||
val isMultiline = myHost.isMultiline
|
||||
for (range in contentRanges) {
|
||||
for (i in contentRanges.indices) {
|
||||
val range = rangeInsideHost.intersection(contentRanges[i]) ?: continue
|
||||
last = range
|
||||
|
||||
val (rangeStart, _) = range
|
||||
val curString = range.substring(text)
|
||||
|
||||
val curString = range.subSequence(text)
|
||||
|
||||
val replacementsForThisLine = curString.decodeReplacements(isMultiline)
|
||||
val replacementsForThisLine = curString.decodeReplacements(myHost.isMultiline)
|
||||
var encodedOffsetInCurrentLine = 0
|
||||
for ((thisRange, replacement) in replacementsForThisLine) {
|
||||
val (thisStart, _) = thisRange
|
||||
val deltaLength = thisStart - encodedOffsetInCurrentLine
|
||||
for (replacement in replacementsForThisLine) {
|
||||
val deltaLength = replacement.first.startOffset - encodedOffsetInCurrentLine
|
||||
val currentOffsetBeforeReplacement = currentOffsetInDecoded + deltaLength
|
||||
if (currentOffsetBeforeReplacement > offsetInDecoded) {
|
||||
return thisStart + encodedOffsetInCurrentLine + (offsetInDecoded - currentOffsetInDecoded)
|
||||
return range.startOffset + encodedOffsetInCurrentLine + (offsetInDecoded - currentOffsetInDecoded)
|
||||
}
|
||||
if (currentOffsetBeforeReplacement == offsetInDecoded && replacement.isNotEmpty()) {
|
||||
return thisStart + encodedOffsetInCurrentLine + (offsetInDecoded - currentOffsetInDecoded)
|
||||
if (currentOffsetBeforeReplacement == offsetInDecoded && replacement.second.isNotEmpty()) {
|
||||
return range.startOffset + encodedOffsetInCurrentLine + (offsetInDecoded - currentOffsetInDecoded)
|
||||
}
|
||||
currentOffsetInDecoded += deltaLength + replacement.length
|
||||
encodedOffsetInCurrentLine += deltaLength + range.length
|
||||
currentOffsetInDecoded += deltaLength + replacement.second.length
|
||||
encodedOffsetInCurrentLine += deltaLength + replacement.first.length
|
||||
}
|
||||
|
||||
val deltaLength = curString.length - encodedOffsetInCurrentLine
|
||||
if (currentOffsetInDecoded + deltaLength > offsetInDecoded) {
|
||||
return rangeStart + encodedOffsetInCurrentLine + (offsetInDecoded - currentOffsetInDecoded)
|
||||
return range.startOffset + encodedOffsetInCurrentLine + (offsetInDecoded - currentOffsetInDecoded)
|
||||
}
|
||||
currentOffsetInDecoded += deltaLength
|
||||
}
|
||||
|
|
|
@ -68,8 +68,9 @@ fun CharSequence.prefixWithTextBlockEscape(
|
|||
marker: CharSequence,
|
||||
indentFirst: Boolean,
|
||||
prefixFirst: Boolean,
|
||||
newLineAfter: Boolean
|
||||
): CharSequence {
|
||||
newLineAfter: Boolean,
|
||||
sbFactory: (Int) -> StringBuilder = {StringBuilder(it)},
|
||||
): StringBuilder {
|
||||
val indentStr = if (indent >= 0) {
|
||||
if (indent < COMMON_INDENT_COUNT)
|
||||
COMMON_INDENTS[indent]
|
||||
|
@ -79,7 +80,7 @@ fun CharSequence.prefixWithTextBlockEscape(
|
|||
""
|
||||
}
|
||||
val parts = NL_MATCHER.split(this, -1)
|
||||
val result = StringBuilder(length + (indentStr.length + marker.length) * parts.size + 1)
|
||||
val result = sbFactory(length + (indentStr.length + marker.length) * parts.size + 1)
|
||||
if (indentFirst) {
|
||||
result.append('\n').append(indentStr)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue