Skip to content

Commit

Permalink
add test case for $ escapings
Browse files Browse the repository at this point in the history
  • Loading branch information
cottand committed Jul 7, 2024
1 parent 82d8b4c commit 6d88fd6
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 35 deletions.
33 changes: 7 additions & 26 deletions src/main/java/org/nixos/idea/psi/NixStringLiteralEscaper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,28 @@ class NixStringLiteralEscaper(host: AbstractNixString) : LiteralTextEscaper<PsiL
}

override fun decode(rangeInsideHost: TextRange, outChars: StringBuilder): Boolean {
// only indented strings supported for now
// TODO only indented strings supported for now
// single line strings require a new decode function because
// it uses different escaping mechanisms
if (myHost !is NixIndString) return false

val subText: String = rangeInsideHost.substring(myHost.text)


val array = IntArray(subText.length + 1)
val success = unescapeAndDecode(subText, outChars, array, interpolations = false)
val success = unescapeAndDecode(subText, outChars, array)
outSourceOffsets = array
return success
}

override fun getOffsetInHost(offsetInDecoded: Int, rangeInsideHost: TextRange): Int {
val offsets = outSourceOffsets ?: throw IllegalStateException("#decode was not called")
val result = if (offsetInDecoded < offsets.size) offsets[offsetInDecoded] else -1
println("gotOffsetInHost decoded=${offsetInDecoded} rangeInsideHost=${rangeInsideHost} result=$result")
return result.coerceIn(2..rangeInsideHost.length) + rangeInsideHost.startOffset
}

companion object {
fun unescapeAndDecode(
chars: String,
outChars: StringBuilder,
sourceOffsets: IntArray?,
interpolations: Boolean
): Boolean {
// this function does not consider interpolations so that
// they do appear in the guest language and remain when we end up converting back to Nix
fun unescapeAndDecode(chars: String, outChars: StringBuilder, sourceOffsets: IntArray?): Boolean {
assert(sourceOffsets == null || sourceOffsets.size == chars.length + 1)

var index = 0
Expand Down Expand Up @@ -118,21 +114,6 @@ class NixStringLiteralEscaper(host: AbstractNixString) : LiteralTextEscaper<PsiL
continue
}

// // $ removes any special meaning from the following $.
// if (c == '$') {
// if (index == chars.length) return false
// c = chars[index++]
// if (c != '$') {
// // if what follows isn't another ' then we are not escaping anything,
// // so we can continue
// outChars.append('$')
// updateOffsets(index - 1)
// outChars.append(c)
// continue
// }
// // what here??
// }

outChars.append(c)
}
return true
Expand Down
22 changes: 16 additions & 6 deletions src/main/java/org/nixos/idea/psi/impl/AbstractNixString.kt
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
package org.nixos.idea.psi.impl

import com.intellij.lang.ASTNode
import com.intellij.openapi.diagnostic.Logger
import com.intellij.psi.PsiLanguageInjectionHost
import com.intellij.psi.impl.source.tree.LeafElement
import com.intellij.util.IncorrectOperationException
import org.nixos.idea.psi.NixIndString
import org.nixos.idea.psi.NixString
import org.nixos.idea.psi.NixStringLiteralEscaper


abstract class AbstractNixString(node: ASTNode) : PsiLanguageInjectionHost, AbstractNixPsiElement(node), NixString {
abstract class AbstractNixString(private val astNode: ASTNode) : PsiLanguageInjectionHost, AbstractNixPsiElement(astNode),NixString {

override fun isValidHost() = true

override fun updateText(text: String): NixString {
// TODO implement. This is called when you edit the injected file in
// order for the final Nix string to get updated
// It is not necessary for syntax highlighting in injections
// but is a nice to have
override fun updateText(s: String): NixString {
// TODO also support single-line strings
if (this !is NixIndString) {
LOG.info("not a nix ind string")
return this
}
(astNode.firstChildNode as LeafElement).replaceWithText(s)
return this
}

override fun createLiteralTextEscaper() = NixStringLiteralEscaper(this)

companion object {
val LOG = Logger.getInstance(AbstractNixString::class.java)
}
}

10 changes: 7 additions & 3 deletions src/test/java/org/nixos/idea/util/NixIndStringUtilTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.nixos.idea.psi.NixStringLiteralEscaper;

import static org.junit.jupiter.api.Assertions.assertEquals;

Expand All @@ -21,13 +22,16 @@ final class NixIndStringUtilTest {
|''\\r| , |\r|
|''\\n| , |\n|
|'''| , |''|
$$ , $
$$ , $$
''$ , $
# supplementary character, i.e. character form a supplementary plane,
# which needs a surrogate pair to be represented in UTF-16
\uD83C\uDF09 , \uD83C\uDF09
""")
void unescape(String unescaped, String expectedResult) {
var str = NixIndStringUtil.unescape(unescaped);
void unescape(String escaped, String expectedResult) {
var sb = new StringBuilder();
NixStringLiteralEscaper.Companion.unescapeAndDecode(escaped, sb, null);
var str = sb.toString();
assertEquals(expectedResult, str);
}
}

0 comments on commit 6d88fd6

Please sign in to comment.