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

Introduce Java doc comment rendering #3472

Merged
merged 27 commits into from Oct 6, 2023
Merged

Introduce Java doc comment rendering #3472

merged 27 commits into from Oct 6, 2023

Conversation

vemv
Copy link
Member

@vemv vemv commented Sep 21, 2023

Introduces cider-docstring.el which is able to render "fragments" (a mixture of plain text and html) into a propertized string.

Starts using such rendered strings in:

  • Company (and with it, Corfu, since internally it queries Company stuff)
    • For both, the output is always trimmed to 20 lines (customizable)
    • The trimming is smart as it can perform several attempts based on 3 sources: The first sentence, the full body, and the block tags (i.e. the returns/throws/params metadata)
  • Eldoc
    • Here we always favor only rendering the first sentence only
  • cider-doc anciliary buffers
    • as shown e.g. when pressing f1 while using Company
    • Here, we favor short rendering only if using Company
  • Mouse tooltips.

For best results, we also start sending a Compliment context to eldoc and info requests.

The context is slightly different than usual: instead of (.foo__prefix__ bar), we have to send (__prefix__ bar), because we're not requesting a completion, but for an inferred class.

Therefore a cider-completion-get-info-context-at-point defun is introduced.

Two new .el files are introduced:

  • cider-context, for extracting the context
  • cider-docstring, for docstring rendering

This way we avoid cyclical deps.

@vemv vemv requested a review from bbatsov September 21, 2023 12:05
@bbatsov
Copy link
Member

bbatsov commented Sep 21, 2023

Company (and with it, Corfu, since internally it queries Company stuff)

I don't get this - Corfu doesn't use anything company-specific to my knowledge.

cider-context, for extracting the context

I have some doubts about the extraction of this. I get why you did it, but it looks relatively weird on its own, given the significant connection to completion. Perhaps at least we can name the file cider-completion-context so it's clearer what this is?

@bbatsov
Copy link
Member

bbatsov commented Sep 21, 2023

I think we should also expand the completion/docs documentation to mention some of those changes.

@vemv
Copy link
Member Author

vemv commented Sep 21, 2023

I don't get this - Corfu doesn't use anything company-specific to my knowledge.

It queries these for showing docstrings:

https://github.com/minad/corfu/blob/cc244c54b392ce4d27ed166730efde4f4d01a07f/extensions/corfu-echo.el#L88C41-L88C52

https://github.com/minad/corfu/blob/cc244c54b392ce4d27ed166730efde4f4d01a07f/extensions/corfu-popupinfo.el#L216C13-L216C62

Perhaps at least we can name the file cider-completion-context so it's clearer what this is?

SGTM!

I think we should also expand the completion/docs documentation to mention some of those changes.

Will do 👍

Base automatically changed from cider-nrepl-0-38-0 to master September 21, 2023 17:01
@vemv vemv marked this pull request as ready for review September 22, 2023 19:32
@vemv
Copy link
Member Author

vemv commented Sep 22, 2023

@bbatsov ready again.

Besides from Company, cider-doc and eldoc, I've been trying these docstrings over the mouse tooltips as well.

Looking correct and concise in all of those.

@@ -11,6 +11,12 @@
(eldev-add-loading-roots 'test "test/utils")
(eldev-add-extra-dependencies 'runtime '(:package logview :optional t))

;; slightly increase the maximum (applies to checkdoc and the byte compiler alike)
(setq byte-compile-docstring-max-column 100)
Copy link
Member

Choose a reason for hiding this comment

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

The Emacs maintainers advised against doing this, that's why I had changed it. Normally it's best to have development settings in .dir-locals.el (you can have them nested in various folders)

Copy link
Member Author

Choose a reason for hiding this comment

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

It didn't work otherwise though 😞

Copy link
Member

Choose a reason for hiding this comment

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

Hmm, I can't imagine how - after all .dir-locals are applied to the entire directory. Unless Eldev is suppressing those somehow.

Copy link
Member Author

@vemv vemv Sep 27, 2023

Choose a reason for hiding this comment

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

I don't know

There's no mention of .dir-locals in the Eldev repo, which might be a signal that it isn't considered as a config mechanism (it does mention four levels of configuration in the readme)

Copy link
Member

Choose a reason for hiding this comment

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

@doublep Does Eldev ignore dir-locals intentionally? If so, I guess we should have the config in both places.

Copy link
Contributor

Choose a reason for hiding this comment

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

No, it simply doesn't do anything special. Which means they are not activated through some automatic magic.

it does mention four levels of configuration in the readme

Those don't include .dir-locals. All ways of configuration are Eldev-specific, but let you evaluate arbitrary Elisp code, not just set variables to constant values.


(describe "cider--render-docstring"
(it "A large corpus of fragments (as produced by Orchard) can be rendered using `shr' without raising errors"
(dolist (class '("Thread" "Object" "File" "String"))
Copy link
Member

Choose a reason for hiding this comment

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

I'm thinking this setup code can be extracted and you can have several more granular tests, because now it's a bit harder to follow what exactly is the purpose of the test given it has a bunch of asserts and expects in it. I think it's usually better to have several tests that check for fewer things each than fewer tests that check for more things.

Copy link
Member Author

Choose a reason for hiding this comment

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

Mmm, the it "A large corpus of fragments (as produced by Orchard) can be rendered using shr' without raising errors"` sets out a reasonable context as for what to expect.

I essentially want a smoke test. HTML renderding seems somewhat delicate. With a large corpus of html fragments, we can be reasonably sure that we aren't hitting some weird corner of the shr library.

The asserts help ensuring that actually iterating stuff.

A specific suggestion would be most welcome. Perhaps I can simply extract test helpers so that the main thing tested is clearer? Other than that, I'm not sure (why) I'd structurally change this.

Copy link
Member

Choose a reason for hiding this comment

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

I thought you can just generate the large corpus of fragments upfront and test the different things you wanted to verify in it separately in individual tests so it's clearer what's considered correct behavior. The test is not particularly complex, so that's not a big deal.

My main concern is the usage of cl-assert in the test, which I don't quite get, given that you already have expect.

Copy link
Member Author

Choose a reason for hiding this comment

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

I use cl-assert <-> expect in Elisp just like how I use assert <-> is in clojure: an assert ensures the sanity of the test itself, but does is not concerned with the SUT.

This separation can help seeing which if the two intents one is expressing.

Finally, cl-assert appears to fail more clearly under buttercup.

@@ -11,6 +11,12 @@
(eldev-add-loading-roots 'test "test/utils")
(eldev-add-extra-dependencies 'runtime '(:package logview :optional t))

;; slightly increase the maximum (applies to checkdoc and the byte compiler alike)
(setq byte-compile-docstring-max-column 100)
Copy link
Member Author

@vemv vemv Sep 27, 2023

Choose a reason for hiding this comment

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

I don't know

There's no mention of .dir-locals in the Eldev repo, which might be a signal that it isn't considered as a config mechanism (it does mention four levels of configuration in the readme)

@@ -14,6 +14,7 @@ jobs:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
emacs_version: ['26.3', '27.2', '28.2', '29.1']
java_version: ['11', '17']
Copy link
Member Author

Choose a reason for hiding this comment

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

I introduced a JVM matrix (soon to be expanded with JDK 21)

- name: Run tests that need enrich-classpath
if: "!startsWith(matrix.os, 'windows')"
run: |
cd dev; ../clojure.sh clojure -M:gen; cd -
Copy link
Member Author

@vemv vemv Sep 27, 2023

Choose a reason for hiding this comment

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

now the test/File.edn files are generated programatically.

As a nice side-effect, we get to exercise our clojure.sh script, and with it, enrich-classpath.

Both get an extra exercise given the JVM matrix.

We could build more tests like this in a future - nice middle ground between reliable and realistic tests (since there's no nrepl connection - only data).

cider-doc.el Outdated
(cider-docview-render (cider-make-popup-buffer cider-doc-buffer nil 'ancillary) symbol info)))
(cider-docview-render (cider-make-popup-buffer cider-doc-buffer nil 'ancillary) symbol info shorter)))

(defun cider-create-shorter-doc-buffer (symbol)
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if "compact" or "abridged" don't reflect better what we're doing here. "shorter" sounds a bit confusing to me.

cider-doc.el Outdated
"Populates *cider-doc* with the documentation for SYMBOL."
(defun cider-create-doc-buffer (symbol &optional shorter)
"Populates *cider-doc* with the documentation for SYMBOL,
favoring a SHORTER format if specified."
Copy link
Member

Choose a reason for hiding this comment

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

This can be "compact" format or something similar IMO.

@vemv vemv merged commit ee1975d into master Oct 6, 2023
21 of 34 checks passed
@vemv vemv deleted the doc-fragments branch October 6, 2023 17:50
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