Skip to content

Commit

Permalink
Merge pull request #324 from johannescoetzee/fix/string-interpolation
Browse files Browse the repository at this point in the history
fix: handle interpolations without spaces and $$ in interpolated strings
  • Loading branch information
eed3si9n authored Jul 23, 2023
2 parents 8062487 + 6f9683b commit 8cdd8bd
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 4 deletions.
47 changes: 46 additions & 1 deletion corpus/literals.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ val string3 = raw"Not a new line \n${ha}"
val string4 = s"""
works even in multiline strings, ${name}
"""

val string5 = s"$works${without}$spaces"

val string6 = s"$a$b"

val string7 = s"$$ $a"

val string8 = s"$"$a"

--------------------------------------------------------------------------------

(compilation_unit
Expand Down Expand Up @@ -73,7 +82,43 @@ works even in multiline strings, ${name}
(interpolated_string
(interpolation
(block
(identifier)))))))
(identifier))))))
(val_definition
(identifier)
(interpolated_string_expression
(identifier)
(interpolated_string
(interpolation
(identifier))
(interpolation
(block
(identifier)))
(interpolation
(identifier)))))
(val_definition
(identifier)
(interpolated_string_expression
(identifier)
(interpolated_string
(interpolation
(identifier))
(interpolation
(identifier)))))
(val_definition
(identifier)
(interpolated_string_expression
(identifier)
(interpolated_string
(interpolation
(identifier)))))
(val_definition
(identifier)
(interpolated_string_expression
(identifier)
(interpolated_string
(interpolation
(identifier))))))


================================================================================
Integer literals
Expand Down
30 changes: 27 additions & 3 deletions grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -1388,6 +1388,26 @@ module.exports = grammar({
_alpha_identifier: $ =>
/[\p{Lu}\p{Lt}\p{Nl}\p{Lo}\p{Lm}\$\p{Ll}_\u00AA\u00BB\u02B0-\u02B8\u02C0-\u02C1\u02E0-\u02E4\u037A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\uA69C-\uA69D\uA770\uA7F8-\uA7F9\uAB5C-\uAB5F\$][\p{Lu}\p{Lt}\p{Nl}\p{Lo}\p{Lm}\$\p{Ll}_\u00AA\u00BB\u02B0-\u02B8\u02C0-\u02C1\u02E0-\u02E4\u037A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\uA69C-\uA69D\uA770\uA7F8-\uA7F9\uAB5C-\uAB5F0-9\$_\p{Ll}]*(_[\-!#%&*+\/\\:<=>?@\u005e\u007c~\p{Sm}\p{So}]+)?/,

/**
* Despite what the lexical syntax suggests, the alphaid rule doesn't apply
* to identifiers that aren't in blocks in interpolated strings (e.g. $foo).
* A more accurate description is given in
* https://www.scala-lang.org/files/archive/spec/2.13/01-lexical-syntax.html
* where it states (regarding dollar sign escapes in interpolated strings) that
* """
* The simpler form consists of a ‘$’-sign followed by an identifier starting
* with a letter and followed only by letters, digits, and underscore characters
* """
* where "letters" does not include the $ character.
*
* This rule is similar to the _alpha_identifier rule, with the differences
* being that the $ character is excluded, along with the _(operator_chars)
* suffix and can be approximated as
* /[A-Za-z_][A-Z_a-z0-9]/;
*/
_interpolation_identifier: $ =>
/[\p{Lu}\p{Lt}\p{Nl}\p{Lo}\p{Lm}\p{Ll}_\u00AA\u00BB\u02B0-\u02B8\u02C0-\u02C1\u02E0-\u02E4\u037A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\uA69C-\uA69D\uA770\uA7F8-\uA7F9\uAB5C-\uAB5F][\p{Lu}\p{Lt}\p{Nl}\p{Lo}\p{Lm}\p{Ll}_\u00AA\u00BB\u02B0-\u02B8\u02C0-\u02C1\u02E0-\u02E4\u037A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\uA69C-\uA69D\uA770\uA7F8-\uA7F9\uAB5C-\uAB5F0-9_\p{Ll}]*/,

_backquoted_id: $ => /`[^\n`]+`/,

_identifier: $ => choice($.identifier, $.operator_identifier),
Expand Down Expand Up @@ -1492,18 +1512,22 @@ module.exports = grammar({

_interpolated_multiline_string_start: $ => '"""',

interpolation: $ => seq("$", choice($.identifier, $.block)),
_dollar_escape: $ => seq('$', choice('$', '"')),

_aliased_interpolation_identifier: $ => alias($._interpolation_identifier, $.identifier),

interpolation: $ => seq("$", choice($._aliased_interpolation_identifier, $.block)),

interpolated_string: $ =>
choice(
seq(
$._interpolated_string_start,
repeat(seq($._interpolated_string_middle, $.interpolation)),
repeat(seq($._interpolated_string_middle, choice($._dollar_escape, $.interpolation))),
$._interpolated_string_end,
),
seq(
$._interpolated_multiline_string_start,
repeat(seq($._interpolated_multiline_string_middle, $.interpolation)),
repeat(seq($._interpolated_multiline_string_middle, choice($._dollar_escape, $.interpolation))),
$._interpolated_multiline_string_end,
),
),
Expand Down
1 change: 1 addition & 0 deletions queries/scala/locals.scm
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@
name: (identifier) @local.definition)

(identifier) @local.reference

11 changes: 11 additions & 0 deletions test/highlight/basics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,16 @@ object Hello {
// ^method
val hello2 = c"some $meth"
// ^method
val hello3 = s"$$$meth$hello2%"
// ^string
// ^punctuation.special
// ^method
// ^punctuation.special
// ^variable
// ^string
val hello4 = s"$"$hello3"
// ^string
// ^punctuation.special
// ^variable
}

0 comments on commit 8cdd8bd

Please sign in to comment.