From 6e6b567f8eac007b0e50fc6e2eb4e4918663016e Mon Sep 17 00:00:00 2001 From: Dima Date: Thu, 2 Nov 2023 19:38:19 +0700 Subject: [PATCH] fix(compiler): Incorrect focus on error [LNG-274] (#959) --- .scalafmt.conf | 10 +++--- aqua-src/antithesis.aqua | 8 ++--- io/src/main/scala/aqua/Rendering.scala | 7 ++-- io/src/test/scala/aqua/RenderingSpec.scala | 35 +++++++++++++++++++ .../src/main/scala/aqua/parser/Parser.scala | 16 ++++----- .../main/scala/aqua/parser/lift/Span.scala | 18 +++++----- .../test/scala/aqua/parser/FuncExprSpec.scala | 14 +++----- 7 files changed, 65 insertions(+), 43 deletions(-) create mode 100644 io/src/test/scala/aqua/RenderingSpec.scala diff --git a/.scalafmt.conf b/.scalafmt.conf index 16e4dbac..a89b2727 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -62,9 +62,9 @@ runner { } } -rewrite { - rules = [ - SortImports - ] -} +rewrite.rules = [Imports] +rewrite.imports.sort = ascii +rewrite.imports.groups = [ + ["aqua\\..*"] +] #runner.dialect = scala3 diff --git a/aqua-src/antithesis.aqua b/aqua-src/antithesis.aqua index 731efd5b..bb9364ec 100644 --- a/aqua-src/antithesis.aqua +++ b/aqua-src/antithesis.aqua @@ -1,6 +1,2 @@ -alias Troll: u32 - -func test() -> i8: - MyAbility = Troll(f = "sf") - - <- 42 \ No newline at end of file +func arr(strs: []string) -> []string + <- strs \ No newline at end of file diff --git a/io/src/main/scala/aqua/Rendering.scala b/io/src/main/scala/aqua/Rendering.scala index 9138746f..3fabcd94 100644 --- a/io/src/main/scala/aqua/Rendering.scala +++ b/io/src/main/scala/aqua/Rendering.scala @@ -1,17 +1,14 @@ package aqua -import aqua.compiler.AquaError.{ParserError as AquaParserError, *} import aqua.compiler.* +import aqua.compiler.AquaError.{ParserError as AquaParserError, *} import aqua.files.FileModuleId import aqua.io.AquaFileError import aqua.parser.lift.{FileSpan, Span} import aqua.parser.{ArrowReturnError, BlockIndentError, LexerError, ParserError} import aqua.semantics.{HeaderError, RulesViolated, SemanticWarning, WrongAST} -import cats.parse.LocationMap -import cats.parse.Parser.Expectation -import cats.parse.Parser.Expectation.* -import cats.{Eval, Show} +import cats.Show object Rendering { diff --git a/io/src/test/scala/aqua/RenderingSpec.scala b/io/src/test/scala/aqua/RenderingSpec.scala new file mode 100644 index 00000000..ccc3463c --- /dev/null +++ b/io/src/test/scala/aqua/RenderingSpec.scala @@ -0,0 +1,35 @@ +package aqua + +import aqua.Rendering.given +import aqua.compiler.AquaError +import aqua.files.FileModuleId +import aqua.io.AquaFileError +import aqua.parser.LexerError +import aqua.parser.lift.{FileSpan, Span} + +import cats.Eval +import cats.data.NonEmptyList +import cats.parse.Parser.Expectation.InRange +import cats.parse.{LocationMap, Parser} +import cats.syntax.show.* +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers +import org.scalatest.{Inside, Inspectors} + +class RenderingSpec extends AnyFlatSpec with Matchers with Inside with Inspectors { + + it should "render end of a string properly" in { + val script = + """func arr(strs: []string) -> []string + | <- strs""".stripMargin + + val error = Parser.Error(8, NonEmptyList.one(InRange(36, ':', ':'))) + val fileSpan = FileSpan("file", Eval.now(LocationMap(script)), Span(8, 9)) + + + val result: AquaError[FileModuleId, AquaFileError, FileSpan.F] = + AquaError.ParserError(LexerError((fileSpan, error))) + + result.show should include("Syntax error: file:1:37") + } +} diff --git a/parser/src/main/scala/aqua/parser/Parser.scala b/parser/src/main/scala/aqua/parser/Parser.scala index 40c74446..057833c1 100644 --- a/parser/src/main/scala/aqua/parser/Parser.scala +++ b/parser/src/main/scala/aqua/parser/Parser.scala @@ -1,21 +1,17 @@ package aqua.parser -import aqua.parser.Ast.Tree -import aqua.parser.{Ast, LexerError, ParserError} import aqua.parser.expr.RootExpr import aqua.parser.head.HeadExpr -import aqua.parser.lexer.Token import aqua.parser.lift.LiftParser.LiftErrorOps -import aqua.parser.lift.{FileSpan, LiftParser, Span} +import aqua.parser.lift.Span.S +import aqua.parser.lift.{LiftParser, Span} + import cats.data.{Validated, ValidatedNec} -import cats.parse.{LocationMap, Parser as P, Parser0 as P0} -import cats.{~>, Comonad, Eval, Id} +import cats.parse.{Parser as P, Parser0 as P0} +import cats.{Comonad, ~>} object Parser extends scribe.Logging { - - import Span.spanLiftParser - lazy val spanParser = parserSchema - import LiftParser.Implicits.idLiftParser + lazy val spanParser: P0[ValidatedNec[ParserError[S], Ast[S]]] = parserSchema def parserSchema: P0[ValidatedNec[ParserError[Span.S], Ast[Span.S]]] = { logger.trace("creating schema...") diff --git a/parser/src/main/scala/aqua/parser/lift/Span.scala b/parser/src/main/scala/aqua/parser/lift/Span.scala index feb0c188..090603e2 100644 --- a/parser/src/main/scala/aqua/parser/lift/Span.scala +++ b/parser/src/main/scala/aqua/parser/lift/Span.scala @@ -1,8 +1,7 @@ package aqua.parser.lift -import cats.data.NonEmptyList -import cats.parse.{LocationMap, Parser as P, Parser0} -import cats.{Comonad, Eval} +import cats.Comonad +import cats.parse.{LocationMap, Parser0, Parser as P} import scala.language.implicitConversions @@ -51,11 +50,14 @@ object Span { str: String, idx: Int, len: Int - ): FocusedLine = FocusedLine( - str.substring(0, idx), - str.substring(idx, idx + len), - str.substring(idx + len) - ) + ): FocusedLine = { + val end = idx + len + FocusedLine( + str.slice(0, idx), + str.slice(idx, end), + str.slice(end, str.length) + ) + } final case class NumberedLine[T]( number: Int, diff --git a/parser/src/test/scala/aqua/parser/FuncExprSpec.scala b/parser/src/test/scala/aqua/parser/FuncExprSpec.scala index 72db95e9..331ece51 100644 --- a/parser/src/test/scala/aqua/parser/FuncExprSpec.scala +++ b/parser/src/test/scala/aqua/parser/FuncExprSpec.scala @@ -4,28 +4,24 @@ import aqua.AquaSpec import aqua.parser.expr.* import aqua.parser.expr.func.* import aqua.parser.lexer.* -import aqua.parser.lift.LiftParser.Implicits.idLiftParser import aqua.parser.lift.Span -import aqua.parser.lift.Span.{P0ToSpan, PToSpan} import aqua.types.ScalarType.* -import cats.Id -import cats.data.{Chain, NonEmptyList} +import cats.{Eval, Id} import cats.data.Chain.* +import cats.data.Validated.{Invalid, Valid} +import cats.data.{Chain, NonEmptyList} import cats.free.Cofree import cats.syntax.foldable.* -import cats.data.Validated.{Invalid, Valid} import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.{Inside, Inspectors} import org.scalatest.matchers.should.Matchers -import cats.~> -import cats.Eval +import org.scalatest.{Inside, Inspectors} import scala.collection.mutable import scala.language.implicitConversions class FuncExprSpec extends AnyFlatSpec with Matchers with Inside with Inspectors with AquaSpec { - import AquaSpec.{given, *} + import AquaSpec.{*, given} private val parser = Parser.spanParser