fix(lsp): Fix go-to-definition for abilities as arguments in functions [LNG-343] (#1116)

This commit is contained in:
Dima 2024-04-08 15:43:30 +03:00 committed by GitHub
parent 49729ac40a
commit 07bea1a909
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 44 additions and 6 deletions

View File

@ -3,6 +3,7 @@ package aqua.lsp
import aqua.parser.lexer.Token import aqua.parser.lexer.Token
import aqua.semantics.rules.locations.{DefinitionInfo, LocationsAlgebra, LocationsState} import aqua.semantics.rules.locations.{DefinitionInfo, LocationsAlgebra, LocationsState}
import aqua.types.AbilityType import aqua.types.AbilityType
import cats.data.State import cats.data.State
import monocle.Lens import monocle.Lens
import scribe.Logging import scribe.Logging
@ -13,9 +14,13 @@ class LocationsInterpreter[S[_], X](using
type SX[A] = State[X, A] type SX[A] = State[X, A]
override def addDefinition(definition: DefinitionInfo[S]): State[X, Unit] = modify { st => override def addDefinition(definition: DefinitionInfo[S]): State[X, Unit] =
st.addDefinition(definition) definition.`type` match {
} // case where ability is an {Argument} in a function
case t: AbilityType if definition.name == t.name =>
pointLocation(definition.name, definition.token)
case _ => modify { st => st.addDefinition(definition) }
}
override def addDefinitionWithFields( override def addDefinitionWithFields(
definition: DefinitionInfo[S], definition: DefinitionInfo[S],

View File

@ -448,7 +448,7 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
// from {SomeAbility} to 'ability SomeAbility' // from {SomeAbility} to 'ability SomeAbility'
res.checkLocations("SomeAbility", 0, 1, main) shouldBe true res.checkLocations("SomeAbility", 0, 1, main) shouldBe true
// from 'SomeAbility.someStr' to {SomeAbility} // from 'SomeAbility.someStr' to {SomeAbility}
res.checkLocations("SomeAbility", 1, 2, main) shouldBe true res.checkLocations("SomeAbility", 0, 2, main) shouldBe true
res.checkTokenLoc(main, "Srv", 0, srvType) shouldBe true res.checkTokenLoc(main, "Srv", 0, srvType) shouldBe true
Range.inclusive(1, 3).foreach { n => Range.inclusive(1, 3).foreach { n =>
@ -503,4 +503,39 @@ class AquaLSPSpec extends AnyFlatSpec with Matchers with Inside {
res.checkLocations("someString", 1, 2, firstImport, Some(main)) shouldBe true res.checkLocations("someString", 1, 2, firstImport, Some(main)) shouldBe true
res.checkLocations("someString", 1, 3, firstImport, Some(main)) shouldBe true res.checkLocations("someString", 1, 3, firstImport, Some(main)) shouldBe true
} }
it should "return right tokens for multiple abilities" in {
val main =
"""aqua Import declares *
|
|export main
|
|ability Abilyy:
| field: string
|
|func firstFunc{Abilyy}() -> string:
| <- "str"
|
|func secondFunc{Abilyy}() -> string:
| <- "str"
|
|func main() -> string:
| ab = Abilyy(field = "123")
| res <- firstFunc{ab}()
| secondFunc{ab}()
| <- res
|""".stripMargin
val src = Map(
"index.aqua" -> main
)
val imports = Map.empty[String, String]
val res = compile(src, imports).toOption.get.values.head
res.errors shouldBe empty
res.checkLocations("Abilyy", 0, 1, main) shouldBe true
res.checkLocations("Abilyy", 0, 2, main) shouldBe true
res.checkLocations("Abilyy", 0, 3, main) shouldBe true
}
} }

View File

@ -33,8 +33,6 @@ class ArrowSem[S[_]](val expr: ArrowExpr[S]) extends AnyVal {
L: LocationsAlgebra[S, Alg] L: LocationsAlgebra[S, Alg]
): Alg[ArrowType] = for { ): Alg[ArrowType] = for {
arrowType <- T.beginArrowScope(arrowTypeExpr) arrowType <- T.beginArrowScope(arrowTypeExpr)
// add locations before ability will be defined as new variable definition
_ <- L.pointLocations(arrowTypeExpr.abilities.map(n => n.value -> n))
absAsArgs = arrowTypeExpr.abilities.map(_.asName) absAsArgs = arrowTypeExpr.abilities.map(_.asName)
// Create local variables // Create local variables
_ <- arrowTypeExpr.absWithArgs.flatMap { case (name, _) => name } _ <- arrowTypeExpr.absWithArgs.flatMap { case (name, _) => name }