diff --git a/metals/src/main/scala/scala/meta/internal/metals/Compilers.scala b/metals/src/main/scala/scala/meta/internal/metals/Compilers.scala index ff276e43306..9cb094065ab 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/Compilers.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/Compilers.scala @@ -472,49 +472,55 @@ 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 - // 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) + def adjustForScala3Worksheet(tokens: List[Integer]): List[Integer] = { + @tailrec + @nowarn + def loop( + remaining: List[Integer], + acc: List[List[Integer]], + 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 + // 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) + loop( + 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) + loop( + next.drop(2), + adjusted :: acc, + deltaLen, + ) + } + case deltaLine :: deltaColumn :: next => + val adjustedColumn: Integer = deltaColumn + adjustColumnDelta val adjusted: List[Integer] = - List(deltaLine, deltaColumn, adjustedLen) ++ next.take(2) - adjustForScala3Worksheet( - next.drop(2), + List(deltaLine, adjustedColumn) ++ next.take(3) + loop( + next.drop(3), 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, - ) + } } + + // Delta for first token was already adjusted in `findCorrectStart` + loop(tokens.drop(5), List(tokens.take(5))) } val vFile = diff --git a/tests/unit/src/main/scala/tests/BaseWorksheetLspSuite.scala b/tests/unit/src/main/scala/tests/BaseWorksheetLspSuite.scala index 716ee0095c4..fb8b87d9c61 100644 --- a/tests/unit/src/main/scala/tests/BaseWorksheetLspSuite.scala +++ b/tests/unit/src/main/scala/tests/BaseWorksheetLspSuite.scala @@ -960,4 +960,41 @@ abstract class BaseWorksheetLspSuite( ) } yield () } + + test("semantic-highlighting2") { + val expected = + s"""| + |<>/*keyword*/ <>/*variable,definition,readonly*/ = <>/*class*/(<>/*variable,readonly*/, <>/*variable,readonly*/) + |""".stripMargin + + val fileContent = + TestSemanticTokens.removeSemanticHighlightDecorations(expected) + for { + _ <- initialize( + s""" + |/metals.json + |{ + | "a": { + | "scalaVersion": "$scalaVersion" + | } + |} + |/a/src/main/scala/foo/Main.worksheet.sc + |$fileContent + |""".stripMargin + ) + _ <- server.didChangeConfiguration( + """{ + | "enable-semantic-highlighting": true + |} + |""".stripMargin + ) + _ <- server.didOpen("a/src/main/scala/foo/Main.worksheet.sc") + _ <- server.didSave("a/src/main/scala/foo/Main.worksheet.sc")(identity) + _ <- server.assertSemanticHighlight( + "a/src/main/scala/foo/Main.worksheet.sc", + expected, + fileContent, + ) + } yield () + } }