Skip to content

Commit

Permalink
bugfix: don't show inferred type for val def bind (#5891)
Browse files Browse the repository at this point in the history
  • Loading branch information
kasiaMarek authored Dec 1, 2023
1 parent d5889c8 commit 02ab6b7
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ final class PcSyntheticDecorationsProvider(
if hasMissingTypeAnnot(vd, tpt) &&
!primaryConstructorParam(vd.symbol) &&
isNotInUnapply(vd) &&
!isCompilerGeneratedSymbol(vd.symbol) =>
!isCompilerGeneratedSymbol(vd.symbol) &&
!isValDefBind(vd) =>
Some(vd.symbol.tpe.widen.finalResultType, vd.namePosition)
case dd @ DefDef(_, _, _, _, tpt, _)
if hasMissingTypeAnnot(dd, tpt) &&
Expand Down Expand Up @@ -191,6 +192,15 @@ final class PcSyntheticDecorationsProvider(

private def isNotInUnapply(vd: ValDef) =
!vd.rhs.pos.isRange || vd.rhs.pos.start > vd.namePosition.end

/* If is left part of val definition bind:
* val <<t>> @ ... =
*/
private def isValDefBind(vd: ValDef) = {
val afterDef = text.drop(vd.namePosition.end)
val index = indexAfterSpacesAndComments(afterDef)
index >= 0 && index < afterDef.size && afterDef(index) == '@'
}
}

private def syntheticTupleApply(sel: Select): Boolean = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class PcSyntheticDecorationsProvider(
driver.run(uri, source)
given ctx: Context = driver.currentCtx
val unit = driver.currentCtx.run.units.head
given InferredType.Text = InferredType.Text(text)

def tpdTree = unit.tpdTree
def provide(): List[SyntheticDecoration] =
Expand Down Expand Up @@ -217,11 +218,16 @@ object TypeParameters:
end TypeParameters

object InferredType:
def unapply(tree: Tree)(using Context) =
opaque type Text = Array[Char]
object Text:
def apply(text: Array[Char]): Text = text

def unapply(tree: Tree)(using text: Text, cxt: Context) =
tree match
case vd @ ValDef(_, tpe, _)
if isValidSpan(tpe.span, vd.nameSpan) &&
!vd.symbol.is(Flags.Enum) =>
!vd.symbol.is(Flags.Enum) &&
!isValDefBind(text, vd) =>
if vd.symbol == vd.symbol.sourceSymbol then
Some(tpe.tpe, tpe.sourcePos.withSpan(vd.nameSpan), vd)
else None
Expand All @@ -245,6 +251,14 @@ object InferredType:
nameSpan.exists &&
!nameSpan.isZeroExtent

/* If is left part of val definition bind:
* val <<t>> @ ... =
*/
def isValDefBind(text: Text, vd: ValDef)(using Context) =
val afterDef = text.drop(vd.nameSpan.end)
val index = indexAfterSpacesAndComments(afterDef)
index >= 0 && index < afterDef.size && afterDef(index) == '@'

end InferredType

case class Synthetics(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,33 @@ import org.eclipse.{lsp4j => l}
object ScalametaCommonEnrichments extends ScalametaCommonEnrichments {}
trait ScalametaCommonEnrichments extends CommonMtagsEnrichments {

def indexAfterSpacesAndComments(text: Array[Char]): Int = {
var isInComment = false
var startedStateChange = false
val index = text.indexWhere {
case '/' if !isInComment && !startedStateChange =>
startedStateChange = true
false
case '*' if !isInComment && startedStateChange =>
startedStateChange = false
isInComment = true
false
case '/' if isInComment && startedStateChange =>
startedStateChange = false
isInComment = false
false
case '*' if isInComment && !startedStateChange =>
startedStateChange = true
false
case c if isInComment || c.isSpaceChar || c == '\t' =>
startedStateChange = false
false
case _ => true
}
if (startedStateChange) index - 1
else index
}

private def logger: Logger =
Logger.getLogger(classOf[ScalametaCommonEnrichments].getName)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -566,4 +566,28 @@ class SyntheticDecorationsSuite extends BaseSyntheticDecorationsSuite {
|}
|""".stripMargin
)

check(
"val-def-with-bind",
"""|object O {
| val tupleBound @ (one, two) = ("1", "2")
|}
|""".stripMargin,
"""|object O {
| val tupleBound @ (one: String, two: String) = ("1", "2")
|}
|""".stripMargin
)

check(
"val-def-with-bind-and-comment",
"""|object O {
| val tupleBound /* comment */ @ (one, two) = ("1", "2")
|}
|""".stripMargin,
"""|object O {
| val tupleBound /* comment */ @ (one: String, two: String) = ("1", "2")
|}
|""".stripMargin
)
}
46 changes: 46 additions & 0 deletions tests/unit/src/test/scala/tests/SkipCommentsSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package tests

import scala.meta.internal.metals.MetalsEnrichments._

import munit.TestOptions

class SkipCommentsSuite extends munit.FunSuite with Assertions {

check(
"drop-all",
" /* bhjv */ /* bhjbi */",
)

check(
"between-comments",
" /* bhjv */ @ /* bhjbi */",
Some('@'),
)

check(
"not-comment",
" /@",
Some('/'),
)

check(
"tab",
"\t /*cbu * whec*/",
)

def check(
name: TestOptions,
text: String,
nextChar: Option[Char] = None,
): Unit =
test(name) {
val index = indexAfterSpacesAndComments(text.toCharArray())
def clue = s"text: $text, index: $index"
nextChar match {
case None => assert(index < 0 || index >= text.size, clue)
case Some(c) =>
assertEquals(text.charAt(index), c, clue)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ class SyntheticDecorationsLspSuite extends BaseLspSuite("implicits") {
| val List[Int](l1: Int, l2: Int) = List[Int](12, 13)
| println("Hello!")
| val abc: Int = 123
| val tupleBound: (String, String) @ (one: String, two: String) = ("1", "2")
| val tupleBound @ (one: String, two: String) = ("1", "2")
| val tupleExplicit: (String, String) = Tuple2[String, String]("1", "2")
| val tupleExplicitApply: (String, String) = Tuple2.apply[String, String]("1", "2")
| var variable: Int = 123
Expand Down

0 comments on commit 02ab6b7

Please sign in to comment.