scalameta / scalameta

Library to read, analyze, transform and generate Scala programs
http://scalameta.org/
BSD 3-Clause "New" or "Revised" License
1.11k stars 224 forks source link

A compendium of parser bugs #312

Open olafurpg opened 8 years ago

olafurpg commented 8 years ago

I ran the following test on a few open source Scala projects and collected statistics on examples when the scala.meta parser throws a ParseException while scalac is happy.

https://github.com/olafurpg/scalafmt/blob/master/src/test/scala/scala/fmt/ProjectTest.scala

Here is the result:

Summary:

Successes: 27722, avg time to parse a single file 5.26 ms Skipped: 1334 (scalac not happy) Unknown failures: 1 Parse exceptions: 197

right arrow expected but ( found

xeno-by commented 8 years ago

Amazing! Thank you.

olafurpg commented 8 years ago

Here's more info on the running time (in nanoseconds):

+------+------+------+-----+------+------+------+
|   Max|   Min|   Sum| Mean|    Q1|    Q2|    Q3|
+------+------+------+-----+------+------+------+
|5.04E8|7.71E5|9.88E9|4.8E7|5.33E6|1.18E7|3.83E7|
+------+------+------+-----+------+------+------+

Unless there's a bug in my implementation (not unlikely), the 75th percentile of files are parsed in under 48ms and the median parse time is ~12ms.

Disclaimer: I am no means a profiling expert, I suspect a library like JMH is suited to give more accurate numbers.

olafurpg commented 8 years ago

Minimal examples for some of the most common bugs: https://gist.github.com/olafurpg/5c4055932ee2e3403275

xeno-by commented 8 years ago

Everything in the minimal examples gist is now fixed and merged. Trying to publish SNAPSHOT before the plane takes off.

olafurpg commented 8 years ago

Remaining bugs: https://gist.github.com/olafurpg/203ffbd16cd740acb996

xeno-by commented 8 years ago

I think that by now I've picked all the low-hanging fruit. The rest is either \n madness or (expr)... problems.

xeno-by commented 8 years ago

https://oss.sonatype.org/content/repositories/releases/org/scalameta/scalameta_2.11/0.0.5-M4/

olafurpg commented 8 years ago

Another false parse error from this file

"""!(arr.cast[Ptr[Byte]] + sizeof[Ptr[_]]).cast[Ptr[Int]] = length
              """.parse[Stat].get
<input>:1: error: end of file expected but = found
!(arr.cast[Ptr[Byte]] + sizeof[Ptr[_]]).cast[Ptr[Int]] = length
                                                       ^
  scala.meta.internal.parsers.Reporter$class.syntaxError(Reporter.scala:17)
  scala.meta.internal.parsers.Reporter$$anon$1.syntaxError(Reporter.scala:23)
  scala.meta.internal.parsers.Reporter$class.syntaxError(Reporter.scala:18)
  scala.meta.internal.parsers.Reporter$$anon$1.syntaxError(Reporter.scala:23)
  scala.meta.internal.parsers.ScalametaParser.syntaxErrorExpected(ScalametaParser.scala:413)
  scala.meta.internal.parsers.ScalametaParser.accept(ScalametaParser.scala:419)
  scala.meta.internal.parsers.ScalametaParser$$anonfun$parseStat$1.skipStatementSeparators$1(ScalametaParser.scala:70)
  scala.meta.internal.parsers.ScalametaParser$$anonfun$parseStat$1.apply(ScalametaParser.scala:76)
  scala.meta.internal.parsers.ScalametaParser$$anonfun$parseStat$1.apply(ScalametaParser.scala:67)
  scala.meta.internal.parsers.ScalametaParser.parseRule(ScalametaParser.scala:45)
  scala.meta.internal.parsers.ScalametaParser.parseStat(ScalametaParser.scala:67)
  scala.meta.parsers.Parse$$anonfun$parseStat$1.apply(Parse.scala:14)
  scala.meta.parsers.Parse$$anonfun$parseStat$1.apply(Parse.scala:14)
  scala.meta.internal.parsers.ScalametaParser$$anon$190.apply(ScalametaParser.scala:3597)
  scala.meta.parsers.Api$XtensionParseDialectInput.parse(Api.scala:21)
  scala.meta.parsers.Api$XtensionParseInputLike.parse(Api.scala:10)
  cmd5$.<init>(Main.scala:281)

Edit. Reported in https://github.com/olafurpg/scalafmt/issues/346

olafurpg commented 7 years ago

The remaining remnants to close this issue

URL details
sbt/A.scala#L2 A.scala:3: error: { expected but \n found
package b
^
akka/Logging.scala#L1071 Logging.scala:1072: error: ) expected but identifier found
case a: Array[] ⇒ format(t, (a map (.asInstanceOf[AnyRef]): _*))
^
finagle/StackTest.scala#L171 StackTest.scala:172: error: ) expected but [ found
assert((params ++ params2)[TestParam] == TestParam(999))
^
breeze/package.scala#L43 package.scala:44: error: { expected but \n found
package debug
^
lila/projection.scala#L30 projection.scala:31: error: ; expected but identifier found
(fields map ( -> Json.toJsFieldJsValueWrapper(1))): *
^
scala/t1785.scala#L5 t1785.scala:6: error: ; expected but [ found
(new t1785)Int
^
scala/t2080.scala#L11 t2080.scala:12: error: illegal combination of modifiers: override and abstract for: trait T
override trait T {
^
scala/t3368.scala#L3 t3368.scala:4: error: ; expected but xml start found
def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]>
^
scala/t430-feb09.scala#L32 t430-feb09.scala:33: error: `val' parameters may not be call-by-name
case class H(s: String)(t: =>String)
^
xeno-by commented 7 years ago

Running the parser and the prettyprinter on millions lines of code was an amazing idea!

tgodzik commented 7 years ago

I think I've got a 3 more parser errors after running scalafmt on our codebase. I hope they're relevant. Otherwise ignore me.

<input>:80: error: => expected but : found
implicit def query[T <: (_, _): TypeInfo](implicit tab: Tabulator[Iterable[T]]): Tabulator[Query[T]] = new Tabulator[Query[T]] { 

<input>:99: error: malformed xml literal
case <tr>{ cells @ _* }</tr> =>

<input>:18: error: `val' parameters may not be call-by-name
case class Dao(override val profile: JdbcProfile, db: Database)(shutdown: => Unit) extends HasProfile

If anyone needs more details on this let me know, unfortunately I can't show the exact files.

kpbochenek commented 4 years ago

finagle/StackTest.scala#L171 - no errors with metals 0.8.1 akka/Logging.scala#L1071 - no errors with metals 0.8.1

scala/t1785.scala#L5 - no errors scala/t2080.scala#L11 - same error as from compiler, I think it is okay scala/t3368.scala#L3 - no errors scala/t430-feb09.scala#L32 - no errors lila/projection.scala#L30 - still an issue