tree-sitter / tree-sitter-haskell

Haskell grammar for tree-sitter.
MIT License
151 stars 36 forks source link

Qualified/unqualified module paths colored differently #115

Open ysangkok opened 6 months ago

ysangkok commented 6 months ago

Not sure whether this is the right repo. But using NVim with melange, the Data.Text part of these imports are colored differently:

import Data.Text (Text)
import Data.Text qualified as T

That ends up showing a weird mix, if you sort your imports by module path instead of whether they are qualified or not.

If this is the intended behaviour, feel free to close. But I would like to hear if there are any suggestions for coloring these similarity. Or is it the responsibility of the queries? Not sure which queries are in this repo.

But it looks like the conflicting colors are @constructor and @namespace, judging by :Inspect. And in the unqualified example, the module path is a @constructor. That doesn't really make sense to me, is that intentional?

tek commented 6 months ago

The queries here are mirrored from https://github.com/nvim-treesitter/nvim-treesitter. But I can't imagine why only Data would have a different highlight.

edit: I guess the fact that they've chosen qualifying_module as a query for the dot seems like it could cause unintended effects. I'm currently working on a redesign of the part that most likely made that hack necessary, so maybe it'll be fixed by that soon.

ysangkok commented 6 months ago

Just to clarify, when I wrote Data... I just meant Data.Text. I have now expanded this. The whole module path is colored consistently. The problem is that the qualification changes how the whole module path is colored.

Tiseno commented 5 months ago

There are some weird stuff going on with qualified stuff in a couple of places, here is an example:

import           Data.Tuple (curry)
import qualified Data.Tuple as Tuple
c :: a -> Tuple.Solo a
c = Tuple.MkSolo
s = Tuple.swap

Which to me is presented like this

image

The treesitter-tree looks like this

  import [0, 0] - [0, 35] @keyword.import / 
    qualified_module [0, 17] - [0, 27] @operator / @module /
      module [0, 17] - [0, 21] @operator / @module /
      module [0, 22] - [0, 27] @operator / @module /
    import_list [0, 28] - [0, 35] @punctuation.bracket / 
      import_item [0, 29] - [0, 34] @variable / 
        variable [0, 29] - [0, 34] @variable / 
  import [1, 0] - [1, 36] @keyword.import / 
    qualified_module [1, 17] - [1, 27] @operator / @module / @constructor / 
      module [1, 17] - [1, 21] @operator / @module / @constructor / 
      module [1, 22] - [1, 27] @operator / @module / @constructor / 
    module [1, 31] - [1, 36] @module / @module /
  signature [2, 0] - [2, 22] @variable / @function / @variable / @_name / @function / @_type
    name: variable [2, 0] - [2, 1] @variable / @function / @variable / @_name / @function / @_type
    type: fun [2, 5] - [2, 22] @type / 
      type_name [2, 5] - [2, 6] @type / 
        type_variable [2, 5] - [2, 6] @type / 
      type_apply [2, 10] - [2, 22] @operator / @module / @module /
        type_name [2, 10] - [2, 20] @operator / @module / @module /
          qualified_type [2, 10] - [2, 20] @operator / @module / @module /
            module [2, 10] - [2, 15] @operator / @module / @module /
            type [2, 16] - [2, 20] @operator / @type / 
        type_name [2, 21] - [2, 22] @type / 
          type_variable [2, 21] - [2, 22] @type / 
  function [3, 0] - [3, 16] @variable / @function / @variable / @function / 
    name: variable [3, 0] - [3, 1] @variable / @function / @variable / @function / 
    rhs: exp_name [3, 4] - [3, 16] @module /
      qualified_constructor [3, 4] - [3, 16] @module /
        module [3, 4] - [3, 9] @module /
        constructor [3, 10] - [3, 16] @constructor / 
  function [4, 0] - [4, 14] @variable / @function / @variable / 
    name: variable [4, 0] - [4, 1] @variable / @function / @variable / 
    rhs: exp_name [4, 4] - [4, 14] @operator / @module / @module /
      qualified_variable [4, 4] - [4, 14] @operator / @module / @module /
        module [4, 4] - [4, 9] @operator / @module / @module /
        variable [4, 10] - [4, 14] @operator / @variable / 

As noted @tek qualified_module (and also qualified_type and qualified_variable) makes everything operators to highlight the dot as an operator, which in itself is a bit weird, to me atleast, as the dot in module access and record access is semantically not even an operator.

Then we have the other weird captures that I do not really understand:

(module) @module
((qualified_module
  (module) @constructor)
  .
  (module))
(qualified_type
  (module) @module)
(qualified_variable
  (module) @module)
(import
  (module) @module)
(import
  (module) @constructor
  .
  (module))

Which seems ... wrong? An imported qualified_module is certainly not a constructor :thinking:

Seems like these changed in a big refactor which made capture names more consistent across a lot of languages

Personally I would change it to the captures

(module) @variable
(qualified_module) @variable
(qualified_type) @type
(qualified_variable) @variable
(qualified_constructor)  @constructor

Instead which will make the module the same highlight as the accessed member:

image

which makes more sense to me, as the syntactic units still represent a type, a constructor, and a variable, respectively, regardless if they are accessed from a module or not, and the accessor dots keep the same color as the unit :shrug:

Edit: I realize I use the latest nvim-treesitter and stable neovim, and not nightly, maybe there are changes on nightly which makes the module group actually highlight to something. I would still argue that the operator captures should be removed though and the dot for qualified module/record access should have the same capture as the accessed name.