crystal tool implementations ~> given undefined constant incorrectly

Created on 15 Jan 2019  路  5Comments  路  Source: crystal-lang/crystal

Came across this issue working on the scry codebase. When two modules interact but the dependencies are required in a different file, crystal tool implementations returns undefined constant on an alias for a class in the other module (not sure if this is the only time this will happen but it is how I have come across it).

Example (gist link for clarity)

Requires 3 files:

foo.cr:

module ModA::ModB
  class Foo < Exception
  end
end

bar.cr:

module ModA
  class Bar
    alias Thing = ModB::Foo
  end
end

main.cr:

require "./bar.cr"
require "./foo.cr"

ModA::Bar.new

This code compiles if you do crystal main.cr but if you run crystal tool implementations -f json -c bar.cr:3:26 bar.cr you get back a message of undefined constant ModB::Foo (did you mean 'ModA') (the did you mean part would go away if I renamed ModB to something more distinct from ModA).

crystal -v

Crystal 0.27.0 (2018-11-04)

LLVM: 6.0.1
Default target: x86_64-apple-macosx

I believe I reproduced on master. I ran make libcrystal and used bin/crystal.

* issue location in scry is here

Most helpful comment

So, just to kind of consolidate the thinking...

The solution to this issue is to call implementations with the main file of the codebase. To do that, tools should standardize on how to determine what that class is with the most likely source being the targets section of the shard.yml file.

Any other thoughts?

All 5 comments

The crystal tool is not super friendly to tooling integration currently.

You can sometimes get around this problem by figuring out a file that requires everything you need, and do crystal tool implementations -f json -c bar.cr:3:26 that_file.cr (or if it was -c bar.cr:3:26 bar.cr that_file.cr, can't remember), but then you have to know what file to look for. So how to figure out what file to put there? In some cases, you can look at the targets in shards.yml, and assume that file requires it. In other cases you note that it is a spec file you look in and can guess that spec_helper requries it. And you can fallback to a file that match the name of the project.

But these are not fool-proof, and will never be guaranteed to work, especiellt not if there are multiple targets defined in shards.yml. You can also not insert more than one of these choices, as tool requires a single entry point.

See more discussion about this in https://github.com/crystal-lang-tools/emacs-crystal-mode/pull/18

This isn't solvable, since the crystal compiler cannot find main.cr or foo.cr, given only bar.cr. This is why crystal tool implementations takes both the file to look for the implementations in, and a file to compile when looking at on it's own.

Most crystal files cannot be compiled on their own, in fact most can't.

There may be hard parts, but the situation should be possible to improve by adding some project specification that direct the tool. For example, for code outside the specs, the tool could look in the shards file and use the target specification if it is there, if it doesn't find enough definitions when compiling the file directly.

I like require for including library deps, but it tend to suck as a project definition tool - there is a reason Rails has removed the need for manual requires for most files.

@yxhuvud that's definitely out of scope for the crystal compiler though, a specification of something like that would be up to tooling developers to implement, although the core team would participate in it's standardization. I think for 99% of situations, the default file can be guessed using heuristics from shard.yml.

So, just to kind of consolidate the thinking...

The solution to this issue is to call implementations with the main file of the codebase. To do that, tools should standardize on how to determine what that class is with the most likely source being the targets section of the shard.yml file.

Any other thoughts?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cjgajard picture cjgajard  路  3Comments

oprypin picture oprypin  路  3Comments

nabeelomer picture nabeelomer  路  3Comments

TechMagister picture TechMagister  路  3Comments

asterite picture asterite  路  3Comments