crystal-coverage icon indicating copy to clipboard operation
crystal-coverage copied to clipboard

Compile time error for nested expressions

Open hanneskaeufler opened this issue 6 years ago • 4 comments

My project does not compile using the coverage binary. I was able to reproduce the first problem with this code:

class Repro
  @param = 1
  CONST = 1

  def call
    chained.result(CONST * (@param + 1))
  end

  def chained
    self
  end

  def result(param)
    1
  end
end

Which results in

Syntax error in src/repro.cr:6: unterminated call

    chained.result(CONST * (@param + 1))

Looking at the generated code its obsious why:

  def call
    ::Coverage[1, 2]; #<loc:"src/repro.cr",5,0>
    chained.result(CONST * (    ::Coverage[1, 3]; #<loc:"src/repro.cr",5,0>
    @param + 1
))
  end
```crystal require "coverage/runtime" ::Coverage::File.new("spec/repro_spec.cr", "b811eaf68e9e5c1c7a2cf7a4d6fdfd80",[4, 5, 6]) ::Coverage::File.new("src/repro.cr", "acb6becf068269a564cf6832dcdb6b0f",[2, 3, 6, 6, 10, 14])# require "spec" #require of `src/repro.cr` from `spec/repro_spec.cr:2` # class Repro ::Coverage[1, 0]; # @param = 1
::Coverage[1, 1]; #<loc:"src/repro.cr",2,0>

CONST = 1

def call ::Coverage[1, 2]; #loc:"src/repro.cr",5,0 chained.result(CONST * ( ::Coverage[1, 3]; #loc:"src/repro.cr",5,0 @param + 1 )) end def chained ::Coverage[1, 4]; #loc:"src/repro.cr",9,0 self end def result(param) ::Coverage[1, 5]; #loc:"src/repro.cr",13,0 1 end end

</details>

hanneskaeufler avatar Oct 12 '18 20:10 hanneskaeufler

Can even be boiled down to

class Repro
  def call
    (1 * (@param + 1))
  end
end

which then is a

Syntax error in src/repro.cr:2: unexpected token: NEWLINE

  def call
^

Generated code:

require "coverage/runtime" ::Coverage::File.new("spec/repro_spec.cr", "b811eaf68e9e5c1c7a2cf7a4d6fdfd80",[4, 5, 6]) ::Coverage::File.new("src/repro.cr", "30a998374e2ee9bbbae08df42f4b1344",[3, 3])# require "spec" #require of `src/repro.cr` from `spec/repro_spec.cr:2` # class Repro def call ::Coverage[1, 0]; # ( 1 * ( ::Coverage[1, 1]; # @param + 1 )) end end #

::Coverage[0, 0]; #loc:"spec/repro_spec.cr",3,0 describe("foo") do ::Coverage[0, 1]; #loc:"spec/repro_spec.cr",4,0 it("breaks") do ::Coverage[0, 2]; #loc:"spec/repro_spec.cr",5,0 Repro.new.call.should(eq(1)) end end

::Coverage.get_results(Coverage::Outputter::HtmlReport.new)

hanneskaeufler avatar Oct 12 '18 20:10 hanneskaeufler

The original code it fails on for me is:

  def latest(page : Int = 1)
    published_at.lte(Time.now)
      .published_at.desc_order
      .limit(PER_PAGE)
      .offset(PER_PAGE * (page - 1))
  end

hanneskaeufler avatar Oct 12 '18 20:10 hanneskaeufler

I won't fix; I have plans to integrate the covering system directly into Crystal compiler, which would makes pipelining way more easy since we won't produces half-baked code in between.

The only hiccups is I don't know when I will have time to implement it 😄

anykeyh avatar Oct 17 '18 07:10 anykeyh

This PR from the Crystal compiler seems to fix this issue: https://github.com/crystal-lang/crystal/pull/11739

lbguilherme avatar Jan 11 '22 11:01 lbguilherme