Skip to content

Commit

Permalink
bugfix: Semantic tokens for multiline strings in Scala3 worksheets
Browse files Browse the repository at this point in the history
For multiline strings, we highlight the entire line, so we need to adjust the length by removing additional indent
  • Loading branch information
jkciesluk committed Oct 2, 2023
1 parent 0c5b90e commit e61f522
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 23 deletions.
38 changes: 30 additions & 8 deletions metals/src/main/scala/scala/meta/internal/metals/Compilers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import java.util.Collections
import java.util.concurrent.ScheduledExecutorService
import java.{util => ju}

import scala.annotation.nowarn
import scala.annotation.tailrec
import scala.collection.concurrent.TrieMap
import scala.concurrent.ExecutionContextExecutorService
Expand Down Expand Up @@ -472,26 +473,47 @@ class Compilers(
}

@tailrec
@nowarn
def adjustForScala3Worksheet(
remaining: List[Integer],
acc: List[List[Integer]] = List.empty,
adjustColumnDelta: Int =
0, // after multiline string we need to adjust column delta of the next token in line
): List[Integer] = {
remaining match {
case Nil => acc.reverse.flatten
case deltaLine :: deltaColumn :: next if deltaLine != 0 =>
// we need to remove additional indent
val adjustedColumn: Integer = (Math.max(0, deltaColumn - 2))
// we need to remove additional indent
case deltaLine :: deltaColumn :: len :: next if deltaLine != 0 =>
if (deltaColumn - 2 >= 0) {
val adjustedColumn: Integer = deltaColumn - 2
val adjusted: List[Integer] =
List(deltaLine, adjustedColumn, len) ++ next.take(2)
adjustForScala3Worksheet(
next.drop(2),
adjusted :: acc,
)
}
// for multiline strings, we highlight the entire line inluding leading whitespace
// so we need to adjust the length after removing additional indent
else {
val deltaLen = deltaColumn - 2
val adjustedLen: Integer = Math.max(0, len + deltaLen)
val adjusted: List[Integer] =
List(deltaLine, deltaColumn, adjustedLen) ++ next.take(2)
adjustForScala3Worksheet(
next.drop(2),
adjusted :: acc,
deltaLen,
)
}
case deltaLine :: deltaColumn :: next =>
val adjustedColumn: Integer = deltaColumn + adjustColumnDelta
val adjusted: List[Integer] =
List(deltaLine, adjustedColumn) ++ next.take(3)
adjustForScala3Worksheet(
next.drop(3),
adjusted :: acc,
)
case _ =>
adjustForScala3Worksheet(
remaining.drop(5),
remaining.take(5) :: acc,
)
}
}

Expand Down
36 changes: 21 additions & 15 deletions tests/unit/src/main/scala/tests/BaseWorksheetLspSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -903,24 +903,30 @@ abstract class BaseWorksheetLspSuite(
}

test("semantic-highlighting") {

val tripleQ = "\"\"\""
val expected =
if (scalaVersion == V.scala212)
"""|<<case>>/*keyword*/ <<class>>/*keyword*/ <<Hi>>/*class*/(<<a>>/*variable,declaration,readonly*/: <<Int>>/*class,abstract*/, <<b>>/*variable,declaration,readonly*/: <<Int>>/*class,abstract*/, <<c>>/*variable,declaration,readonly*/: <<Int>>/*class,abstract*/)
|<<val>>/*keyword*/ <<hi1>>/*variable,definition,readonly*/ =
| <<Hi>>/*class*/(<<1>>/*number*/, <<2>>/*number*/, <<3>>/*number*/)
|<<val>>/*keyword*/ <<hi2>>/*variable,definition,readonly*/ = <<Hi>>/*class*/(<<4>>/*number*/, <<5>>/*number*/, <<6>>/*number*/)
|
|<<val>>/*keyword*/ <<hellos>>/*variable,definition,readonly*/ = <<List>>/*class*/(<<hi1>>/*variable,readonly*/, <<hi2>>/*variable,readonly*/)
|""".stripMargin
s"""|<<case>>/*keyword*/ <<class>>/*keyword*/ <<Hi>>/*class*/(<<a>>/*variable,declaration,readonly*/: <<Int>>/*class,abstract*/, <<b>>/*variable,declaration,readonly*/: <<Int>>/*class,abstract*/, <<c>>/*variable,declaration,readonly*/: <<Int>>/*class,abstract*/)
|<<val>>/*keyword*/ <<hi1>>/*variable,definition,readonly*/ =
| <<Hi>>/*class*/(<<1>>/*number*/, <<2>>/*number*/, <<3>>/*number*/)
|<<val>>/*keyword*/ <<hi2>>/*variable,definition,readonly*/ = <<Hi>>/*class*/(<<4>>/*number*/, <<5>>/*number*/, <<6>>/*number*/)
|
|<<val>>/*keyword*/ <<hellos>>/*variable,definition,readonly*/ = <<List>>/*class*/(<<hi1>>/*variable,readonly*/, <<hi2>>/*variable,readonly*/)
|<<val>>/*keyword*/ <<str>>/*variable,definition,readonly*/ = <<$tripleQ>>/*string*/
|<< hello>>/*string*/
|<< world$tripleQ>>/*string*/.<<stripMargin>>/*method*/
|""".stripMargin
else
"""|<<case>>/*keyword*/ <<class>>/*keyword*/ <<Hi>>/*class*/(<<a>>/*variable,declaration,readonly*/: <<Int>>/*class,abstract*/, <<b>>/*variable,declaration,readonly*/: <<Int>>/*class,abstract*/, <<c>>/*variable,declaration,readonly*/: <<Int>>/*class,abstract*/)
|<<val>>/*keyword*/ <<hi1>>/*variable,definition,readonly*/ =
| <<Hi>>/*class*/(<<1>>/*number*/, <<2>>/*number*/, <<3>>/*number*/)
|<<val>>/*keyword*/ <<hi2>>/*variable,definition,readonly*/ = <<Hi>>/*class*/(<<4>>/*number*/, <<5>>/*number*/, <<6>>/*number*/)
|
|<<val>>/*keyword*/ <<hellos>>/*variable,definition,readonly*/ = <<List>>/*class*/(<<hi1>>/*variable,readonly*/, <<hi2>>/*variable,readonly*/)
|""".stripMargin
s"""|<<case>>/*keyword*/ <<class>>/*keyword*/ <<Hi>>/*class*/(<<a>>/*variable,declaration,readonly*/: <<Int>>/*class,abstract*/, <<b>>/*variable,declaration,readonly*/: <<Int>>/*class,abstract*/, <<c>>/*variable,declaration,readonly*/: <<Int>>/*class,abstract*/)
|<<val>>/*keyword*/ <<hi1>>/*variable,definition,readonly*/ =
| <<Hi>>/*class*/(<<1>>/*number*/, <<2>>/*number*/, <<3>>/*number*/)
|<<val>>/*keyword*/ <<hi2>>/*variable,definition,readonly*/ = <<Hi>>/*class*/(<<4>>/*number*/, <<5>>/*number*/, <<6>>/*number*/)
|
|<<val>>/*keyword*/ <<hellos>>/*variable,definition,readonly*/ = <<List>>/*class*/(<<hi1>>/*variable,readonly*/, <<hi2>>/*variable,readonly*/)
|<<val>>/*keyword*/ <<str>>/*variable,definition,readonly*/ = <<$tripleQ>>/*string*/
|<< hello>>/*string*/
|<< world$tripleQ>>/*string*/.<<stripMargin>>/*method*/
|""".stripMargin

val fileContent =
TestSemanticTokens.removeSemanticHighlightDecorations(expected)
Expand Down

0 comments on commit e61f522

Please sign in to comment.