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

Use paredit in the signature provider to find correct symbol #450

Merged
merged 22 commits into from
Nov 7, 2019

Conversation

cfehse
Copy link
Contributor

@cfehse cfehse commented Nov 4, 2019

What has Changed?

  • Changed the method to find the symbol for the info call to use paredit and to retrieve the symbol from the containing ( ) list.
  • Corrected the handling of 'junk' and 'punk' in forwardSexp() and backwardSexp().

Fixes #410

My Calva PR Checklist

I have:

  • Read How to Contribute.
  • Made sure I am directing this pull request at the dev branch. (Or have specific reasons to target some other branch.)
  • Made sure I am changed the default PR base branch, so that it is not master. (Sorry for the nagging.)
  • Tested the VSIX built from the PR (well, if this is a PR that changes the source code.) You'll find the artifacts by clicking Show all checks in the CI section of the PR page, and then Details on the ci/circleci: build test. (For now you'll need to opt in to the CircleCI New Experience UI to see the Artifacts tab, because bug.)
    • Tested the particular change
    • Figured if the change might have some side effects and tested those as well.
    • Smoke tested the extension as such.
  • Referenced the issue I am fixing/addressing in a commit message for the pull request.
  • Updated the [Unreleased] entry in CHANGELOG.md, linking the issue(s) that the PR is addressing.

The Calva Team PR Checklist:

Before merging we (at least one of us) have:

  • Made sure the PR is directed at the dev branch (unless reasons).
  • Read the source changes.
  • Given feedback and guidance on source changes, if needed. (Please consider noting extra nice stuff as well.)
  • Tested the VSIX built from the PR (well, if this is a PR that changes the source code.)
    • Tested the particular change
    • Figured if the change might have some side effects and tested those as well.
    • Smoke tested the extension as such.
  • If need be, had a chat within the team about particular changes.

Ping @PEZ, @kstehn, @bpringe

@PEZ
Copy link
Collaborator

PEZ commented Nov 4, 2019

I truly like that you go for the structural way. However, paredit.js is abandonware, and I think we should try get rid of it, rather than build more with it. Could this maybe be done using the LispTokenCursor like we do here: https://github.com/BetterThanTomorrow/calva/blob/master/src/utilities.ts#L91

@cfehse
Copy link
Contributor Author

cfehse commented Nov 4, 2019

This can surely be done with the LispTokenCursor. If I have time and the mood I will change that eventuelly - but for now this is better than the current implementation which does not check if the current form is the form for which the symbol can be retrieved.

@cfehse
Copy link
Contributor Author

cfehse commented Nov 4, 2019

@PEZ

By the way what is the advantage of the LispTokenCursor over paredit. I find neither of them especially easy to use - as far as I now know both.

@PEZ
Copy link
Collaborator

PEZ commented Nov 4, 2019

I like paredit as such. 😄 What I am objecting to is paredit.js, which is bug ridden and not maintained.

Our own paredit is built with our own LispTokenCursor, which might not always have the perfect API , but it is at least maintained, and much more complete and has fewer bugs than paredit.js. Also, we can always build some nicer abstraction on top of it. A bit like our paredit.ts module does.

I'll see if I have the time to try modify this PR to use our own stuff instead. If not, we'll merge it and fix that later, as you suggest.

@cfehse
Copy link
Contributor Author

cfehse commented Nov 4, 2019

Okay I understand. gg

@PEZ
Copy link
Collaborator

PEZ commented Nov 4, 2019

OK. So here is a version using docmirror+LispTokenCursor: 77e5a97

Unless I have misunderstood something, it is equivalent to the paredit.js version. I actually think the TokenCursor API is pretty sweet, at least for this task.

When doing this I noticed one more advantage with the docmirror approach: It avoids building a new AST every time the symbol is fetched.

There is a big risk that I have misunderstood something though, so therefore I am first pushing this in its own branch, so that you can have a look before I update this PR.

@cfehse
Copy link
Contributor Author

cfehse commented Nov 5, 2019

When doing this I noticed one more advantage with the docmirror approach: It avoids building a new AST every time the symbol is fetched.

For that reason I only builded the AST for the current toplevel form in my approach. But nevertheless your version looks very clean. I will take a look and integrate it. Thanks.

@PEZ
Copy link
Collaborator

PEZ commented Nov 5, 2019

I'll push my changes and then it is ready to merge, I'd say.

@cfehse
Copy link
Contributor Author

cfehse commented Nov 5, 2019

I'll push my changes and then it is ready to merge, I'd say.

Your code is not doing, what it is supposed to to. Wait - I take a look at this.

@PEZ
Copy link
Collaborator

PEZ commented Nov 5, 2019

Your code is not doing, what it is supposed to to. Wait - I take a look at this.

Too late. 😄

At least I haven't merged the PR yet.

@cfehse
Copy link
Contributor Author

cfehse commented Nov 5, 2019

@PEZ

This docMirror.getDocument(document).getTokenCursor(idx); returns the Cursor set to the last token of the last line of the doc regardless where the position is.

@cfehse
Copy link
Contributor Author

cfehse commented Nov 5, 2019

@PEZ

I am handle this over to you now - I do not have the time to rework the whole thing. The idea is to find the correct symbol regardless in which place you are in a form.
Examples ( | is the cursor):

(def  | (fn   [1   map  ]  {   } )    ) => def
(def    (fn | [1   map  ]  {   } )    ) => fn
(def    (fn   [1 | map  ]  {   } )    ) => fn
(def    (fn   [1   map  ]  { | } )    ) => fn
(def    (fn   [1   map  ]  {   } ) |  ) => def

Add LispTokenCursor method for searching backwards for
a specific list type
@PEZ
Copy link
Collaborator

PEZ commented Nov 5, 2019

Now I think I got it right. At least for the test cases you provided there. Look:

signature-help-test

Please help sanity check the LispTokenCursor method I added for helping with the task.

@cfehse
Copy link
Contributor Author

cfehse commented Nov 5, 2019

@PEZ

I take a look at that tomorrow. Thanks.

@PEZ
Copy link
Collaborator

PEZ commented Nov 5, 2019

Tomorrow is such a long time away, so I added two more things to the signature help:

  1. Show active parameter.
    • Only for regular forms so far.
    • It keeps & more active when that is reach and more arguments added.
  2. Show function name in signature help.

It looks like so:

active-params-in-signature

I also made the escape key dismiss the signature hover.

@PEZ
Copy link
Collaborator

PEZ commented Nov 6, 2019

Now the bugs reported in calva-dev should be fixed. They were about:

  • argument lists where parameter destruction is going on
  • ignored forms in the calling argument list
  • macros with optional arguments (of type arg?). These don't get active parameter markup now.

As far as I can tell, this should be good to go.

@cfehse
Copy link
Contributor Author

cfehse commented Nov 6, 2019

@PEZ

Am I missing something? The getSymbol() method of the CalvaSignatureHelpProvider() does not work at all for me. Returns undefined. I pulled this branch from upstream and made a fresh rebuild. I have no idea.

@PEZ
Copy link
Collaborator

PEZ commented Nov 6, 2019

Does the VSIX work for you?

@cfehse
Copy link
Contributor Author

cfehse commented Nov 6, 2019

@PEZ

No the signature help will not pop up.

@PEZ
Copy link
Collaborator

PEZ commented Nov 6, 2019

How odd. Could it be a Windows thing...

@cfehse
Copy link
Contributor Author

cfehse commented Nov 6, 2019

The VSIX does not work on WSL either.

Now trying native linux...

@cfehse
Copy link
Contributor Author

cfehse commented Nov 6, 2019

@PEZ

On native linux the code works. Very strange...

@PEZ
Copy link
Collaborator

PEZ commented Nov 6, 2019

Works on my Windows in Virtual Box...

Is it the same project you use when it works and when it doesn't?

@cfehse
Copy link
Contributor Author

cfehse commented Nov 6, 2019

@PEZ

It's not a Windows problem. It is a data problem. I have test data here where it is not working. backwardList() does return false where it should not I think.

@PEZ
Copy link
Collaborator

PEZ commented Nov 6, 2019

Cool. Are you on it now? Otherwise I'd like that data. 😄

@cfehse
Copy link
Contributor Author

cfehse commented Nov 6, 2019

@PEZ

The code does not work for me after a '(comment ...)` and under some circumstances in that comment form. It works for the first form in the comment.

@cfehse
Copy link
Contributor Author

cfehse commented Nov 6, 2019

@PEZ

Here is some code which confuses the code:

(ns brainpie-test-api.test-case) 

(def )

;; Interactive development
(comment
  (def )
  (while true (do (println "start sleeping")
                  (Thread/sleep 1000)))

  (defn prompt
    "get information from the user"
    [msg]
    (println msg)
    (read-line))
  (prompt "What is my name")

  (go
    (while true
      (println "hello")
      (Thread/sleep 1000)))

  (go
    (def x (atom 1))
    (while (< @x 5)
      (do
        (println @x)
        (Thread/sleep 1000)
        (swap! x inc))))

  (defn fehse
    [x]

    (+ x (+ x 3)))

  (println (fehse))

  (def   (fn [1  map]))

  (defn   [] (map println [1 1 1 1] {1 1} #'- (fehse)))

  )

@PEZ
Copy link
Collaborator

PEZ commented Nov 6, 2019

Works for me with that test data.

@cfehse
Copy link
Contributor Author

cfehse commented Nov 6, 2019

@PEZ

On my systems it is not working. Sadly...

@PEZ
Copy link
Collaborator

PEZ commented Nov 6, 2019

So this is a Windows problem after all. At least related. Setting the line ending of the file in VS Code to CRLF will provoke the error. Now the hunt for why this throws things off begins...

We were getting the wrong mapping between offset and rowCol on Windows
@PEZ
Copy link
Collaborator

PEZ commented Nov 6, 2019

Windows/CRLF issue should be fixed now.

Now the only case where I know the wrong argument is marked as active is in thread-first macros, such as ->, and some->. I think I have an idea of how to fix that, but I don't think we need to hold shipping this PR because of that.

@PEZ
Copy link
Collaborator

PEZ commented Nov 7, 2019

And now made it work also when inside thread-first forms.

Here's a demo showing the behaviour working for various test cases:

signature-help

@cfehse
Copy link
Contributor Author

cfehse commented Nov 7, 2019

@PEZ

Now this looks good to me. Very nice feature indeed!

@PEZ PEZ merged commit 4163833 into dev Nov 7, 2019
@PEZ PEZ deleted the wip/sinature-handler-use-paredit branch November 7, 2019 10:38
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.

2 participants