Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formatter error when assigning to nilable type in property missing space after name #14482

Open
Blacksmoke16 opened this issue Apr 11, 2024 · 2 comments

Comments

@Blacksmoke16
Copy link
Member

class Foo
  property id: Int32? = 1
end

Trying to format this results in:

expecting =, not `IDENT, id`, at :2:12 (Exception)
  from /crystal/src/compiler/crystal/tools/formatter.cr:5170:9 in '??'
  from /crystal/src/compiler/crystal/tools/formatter.cr:3395:7 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/tools/formatter.cr:4815:7 in '??'
  from /crystal/src/compiler/crystal/tools/formatter.cr:4664:7 in 'format_nested_with_end'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:20:7 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/tools/formatter.cr:23:7 in 'format_source'
  from /crystal/src/compiler/crystal/command/format.cr:133:7 in 'format_many'
  from /crystal/src/compiler/crystal/command/format.cr:63:5 in 'format'
  from /crystal/src/compiler/crystal/command.cr:179:7 in 'tool'
  from /crystal/src/compiler/crystal/command.cr:117:7 in 'run'
  from /crystal/src/compiler/crystal.cr:11:1 in '__crystal_main'
  from /crystal/src/crystal/main.cr:129:5 in 'main'
  from src/env/__libc_start_main.c:95:2 in 'libc_start_main_stage2'

Seems it does not like the invalid syntax in combination with an assignment to a nilable type.

Also somewhat related to #10698.

@HertzDevil
Copy link
Contributor

It looks like this snippet straight up parses to something without the id at all:

macro f(x)
  {% p x %} # => class Foo; property = 1; end
end

f(class Foo
    property id: Int32? = 1
  end)

@HertzDevil
Copy link
Contributor

HertzDevil commented Apr 12, 2024

So it turns out the parser is very lax when detecting valid assignment targets. In particular, Crystal::Parser#can_be_assigned? accepts far more Call nodes than #multi_assign_target?, so all the following lines have a similar issue:

foo() = 1         # => foo = 1
foo(x: 1) = 2     # => foo = 2
foo.[](1) = 2     # => foo[1] = 2
foo.[](x: 1) = 2  # => foo[x: 1] = 2
foo.[](&.bar) = 2 # => foo.[]=(2, &.bar)

foo x: 1 = 2 # => foo = 2

# these type names are also valid regular code
foo x: T? = 1     # => foo = 1
foo x: {T} = 1    # => foo = 1
foo x: {y: T} = 1 # => foo = 1

But note:

foo x: T = 1    # => foo(x: T = 1)
foo x: T[1] = 1 # => foo(x: T[1] = 1)
foo x: T* = 1   # Error: unexpected token: "="

The lines that involve parentheses should definitely be syntax errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants