crystal-lang-tools / vscode-crystal-lang

Yet another VSCode extension for Crystal Programming Language
https://marketplace.visualstudio.com/items?itemName=crystal-lang-tools.crystal-lang
MIT License
275 stars 57 forks source link

Syntax highlight mismatch for methods and variables #186

Closed wJoenn closed 5 months ago

wJoenn commented 5 months ago

Describe the bug The syntax highlight does not take into consideration what the variable actually is and ends up highlighting it with different colours depending on the context. For example after declaring a method foo, it will be highlighted in a colour when used with parenthesis, another when chained with another method, and another when called without parenthesis

Same when declaring a variable bar which changes colour depending on whether it's used as is or chained

It's also true when using standard library methods without parenthesis such as tests

To Reproduce Create a new Crystal file and copy paste the code snippet I wrote down below

Expected behavior Methods and variables should have a consistent colour no matter whether they are used with parenthesis or not nor whether they are chained. (See ruby example screenshot)

Piece of Code

def foo
  "bar"
end

p foo()
p foo.strip
p foo

bar = "foo"
bar = bar.strip
p bar

describe "#foo" do
  it "should return 'bar'" do
    foo.should eq "bar"
  end
end
Screenshots Crystal Ruby (with Spotify's ruby-lsp extension)
image image

Desktop (please complete the following information):

nobodywasishere commented 5 months ago

I can make the colors more consistent between contexts but unfortunately it's not possible to match the behavior of LSP as our syntax highlighting is via a tmlanguage grammar (a series of regexes). It may be possible for crystalline to implement syntax highlighting, but that's beyond the scope of this repo.

wJoenn commented 5 months ago

If I understand correctly, the type of the file can be declared in the tmlanguage declaration

"fileTypes": [
  "cr"
],

Would there be a way to create a new file for specs with a fileType of spec.cr that would hardcode every spec keywords as either control or the equivalent of a method depending on the keyword maybe ? Something like these

{
  "comment": "everything being a reserved word, not a value and needing a 'end' is a..",
  "match": "(?<!\\.)\\b(describe|expect|it|expect_raises)\\b(?![?!:])",
  "name": "keyword.control.crystal"
},
{
  "comment": "every 'spec' related method is a..",
  "match": "(?<!\\.)\\b(should|eq|be|be_a|be_nil|be_true|be_false|be_truthy|be_falsey|be_close|contain|match)\\b(?![?!:])",
  "name": "entity.name.function.crystal"
},

That would solve the spec related syntax though and I understand what you mean for the rest, I can't think of a solution to match foo and bar to a different regexp to make one be highlighted as a method and the other as a variable 🤔

Have you ever talked about this to Crystalline's team ?

nobodywasishere commented 5 months ago

I could add the spec stuff as keywords to the normal language, as they are built-in and available ootb (though only used in specs). I've not talked to the developer of Crystalline about this yet.