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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Support Elm Programming Language #2222

Closed
wants to merge 10 commits into from

Conversation

anmolitor
Copy link

@anmolitor anmolitor commented Feb 2, 2024

What

Adds support for the Elm programming language.
I have tried to bring #891 up to date.

Is there a good way to unit test the generated tree sitter queries?
I am currently struggling to extend the functionality - Elm is quite different in its syntax from most currently supported languages. For example, record_expr[field][expression] for change value inside of a map/struct { a = 1, b = 2 } currently always results in { a = , b = 2 }, even if the cursor/target is on "b".
I read https://www.cursorless.org/docs/contributing/parse-tree-patterns/ and set up tree-sitter-node locally with tree-sitter-elm to easily inspect the trees, but there are a lot of utility functions in use in the cursorless codebase regarding NodeMatchers that I do not fully understand. Is there some additional documentation/examples that I haven't found yet?

EDIT:
I have looked at the open Haskell MR which has a similar syntax. Scm Queries seem to be easier to debug to I will be trying that for now.

Checklist

  • Recorded tests for the new language
  • Used "change" / "clear" instead of "take" for selection tests to make recorded tests easier to read
  • Added a few specific tests that use "chuck" instead of "change" to test removal behaviour when it's interesting, especially:
    • "chuck arg" with single argument in list
    • "chuck arg" with multiple arguments in list
    • "chuck item" with single argument in list
    • "chuck item" with multiple arguments in list
  • Added @textFragment captures. Usually you want to put these on comment and string nodes. This enables "take round" to work within comments and strings.
  • Added a test for "change round" inside a string, eg "hello (there)"
  • Supported "type" both for type annotations (eg foo: string) and declarations (eg interface Foo {}) (and added tests for this behaviour 馃槉)
  • Supported "item" both for map pairs and list entries (with tests of course)

Copy link
Member

@pokey pokey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! It would be great if you could migrate these patterns to the new scm query syntax, as we're in the process of removing the old pattern language completely. See the docs, other example PRs, eg json and java, and feel free to drop into a meet-up!

@anmolitor
Copy link
Author

I added most of the scm queries that I understood. Currently I am struggling with scopes - many of the previously recorded tests are now failing because of "NoContainingScopeError"s.
I could fix some of them by adding @.domain on the outer query, which I saw in other languages (and still don't fully understand), but others were not so easy to fix.
In particular, I have no idea how to fix argumentAndParameter tagging.
If I match all params using (
)*, cursorless throws an error because there are multiple matches when it expected only one.
If I instead list every possible param by hand as seperate queries, I get "NoContainingScopeError: Couldn't find containing argumentOrParameter".
Using just (_) inside of the functionDeclarationLeft node gives the same scope related error.

For reference, here is what I thought should work:

;; namedFunction

;;!! f x y = x
;;!  ^^^^^^^^^
(value_declaration 
  functionDeclarationLeft: (function_declaration_left
    (lower_case_identifier) @functionName @name
    pattern: (_) @argumentOrParameter
  )
  body: (_) @namedFunction.interior
) @namedFunction @functionName.domain

Can you give me some hints? I've tried looking at other languages, but most have a mixed bag of scm and ts queries.

@tankorsmash
Copy link

I think @.domain represents the domain of the scope, which is sort of like the area around the actual scope, as a sort of way of getting to the the scope that you're in, without actually literally being in the scope. there's a video of it here

@pokey
Copy link
Member

pokey commented Feb 9, 2024

@anmolitor I think you're running into tree-sitter/tree-sitter#2984. You can work around it as follows:

(function_declaration_left (_) @argumentOrParameter (#not-type? @argumentOrParameter lower_case_identifier))

@pokey
Copy link
Member

pokey commented Feb 9, 2024

also, be sure to use andreas's extension to format your code

@tankorsmash
Copy link

tankorsmash commented Feb 24, 2024

@anmolitor I forked this PR to see if I could help. I couldn't get far, but I did manage to the linked formatter going. It took a while to run on the entire repo but it seems like all it needed to format was the elm.scm file. anmolitor/cursorless@main...tankorsmash:cursorless:main

steps:

  • install the linked extension
  • right click elm.scm in tree
  • very bottom of the dropdown is 'Format' which opens, formats and closes the file

The PR seems to be working though, (without being able to run tests for some reason).


I'd love to have support for state and item scopes on top of what is currently here. Maybe it's not possible though, with how everything is an expression. I'm certainly having trouble getting it going myself!

Based on how python.scm and java.scm are written, I did something similar via a jq filter to get the subtypes for the type bin_op_expr, [.[] | select(.type == "bin_op_expr") | .fields.part.types[].type] (also tried function_call_expr and others), but that led to errors are runtime about overlapping, but I think that's getting some part of the way there.

All the ones in this PR seem to work great (save for arg)!

@anmolitor
Copy link
Author

Wow thanks for the help everyone!
I'm currently dedicating my free time to prepare
https://github.com/anmolitor/protoc-gen-elm 4.0.0,
but that should only take a few more days. I'll come back to work on this PR right afterwards :)

@pokey
Copy link
Member

pokey commented Apr 22, 2024

@anmolitor if you don't think you'll have capacity to bring this one home, maybe @tankorsmash should open a new PR so that the formatting changes can be incorporated and push things forward? (assuming @tankorsmash has time)

@pokey pokey marked this pull request as draft April 22, 2024 12:49
@tankorsmash
Copy link

I'll take another stab at this this weekend, if @anmolitor is busy!

@anmolitor
Copy link
Author

Sorry for the delay. I think I'm currently too busy to complete this PR so I'll close this for now. @tankorsmash feel free to use my code as a starting point :)

@anmolitor anmolitor closed this Apr 30, 2024
@tankorsmash
Copy link

I've messed around with Treesitter more in the meantime, hopefully I can put something together. Thank you for all the work so far!

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

Successfully merging this pull request may close these issues.

None yet

3 participants