greghendershott / racket-mode

Emacs major and minor modes for Racket: edit, REPL, check-syntax, debug, profile, packages, and more.
https://www.racket-mode.com/
GNU General Public License v3.0
682 stars 93 forks source link

`racket-xp-mode` shows public class methods as not bound #440

Open alex-hhh opened 4 years ago

alex-hhh commented 4 years ago

I'm trying out the new racket-xp-mode and I noticed that it marks all public class methods as unbound occurrences and crosses them out. Here is an example:

#lang racket
(define my-class%
  (class object% (init) (super-new)
    (define/public (say-hello)
      (printf "Hello World~%"))))
(define c (new my-class%))
(send c say-hello)

The say-hello method is obviously used, but it is shown as unused:

nbo

It seems that functions which are exported from the module are not marked as "not used" even if they are not called from within a module. Perhaps public methods could also be treated the same?

My code base uses classes public methods extensively and they all show crossed out.


To help me help you, please:

  1. Open any racket-mode or racket-repl-mode buffer.

  2. M-x racket-bug-report ENTER.

  3. Copy and paste that, here.

``` ((alist-get 'racket-mode package-alist)) ((emacs-version "26.3") (emacs-uptime "9 minutes, 9 seconds") (system-type windows-nt) (major-mode racket-mode) (racket--el-source-dir "c:/Users/alexh/.emacs.d/lisp/racket-mode/") (racket--rkt-source-dir "c:/Users/alexh/.emacs.d/lisp/racket-mode/racket/") (racket-program "C:\\Program Files\\Racket\\Racket.exe") (racket-command-port 55555) (racket-command-timeout 10) (racket-memory-limit 2048) (racket-error-context low) (racket-error-context low) (racket-history-filter-regexp "\\`\\s *\\S ?\\S ?\\s *\\'") (racket-images-inline t) (racket-images-keep-last 100) (racket-use-repl-submit-predicate nil) (racket-images-system-viewer "display") (racket-pretty-print t) (racket-indent-curly-as-sequence t) (racket-indent-sequence-depth 0) (racket-pretty-lambda nil) (racket-smart-open-bracket-enable nil) (racket-module-forms "\\s(\\(?:module[*+]?\\|library\\)") (racket-logger-config ((cm-accomplice . warning) (GC . info) (module-prefetch . warning) (optimizer . info) (racket/contract . error) (sequence-specialization . info) (* . fatal)))) (enabled-minor-modes (auto-composition-mode) (auto-compression-mode) (auto-encryption-mode) (auto-fill-mode) (auto-save-mode) (blink-cursor-mode) (cursor-sensor-mode) (diff-auto-refine-mode) (display-time-mode) (electric-indent-mode) (file-name-shadow-mode) (flyspell-mode) (font-lock-mode) (global-eldoc-mode) (global-font-lock-mode) (line-number-mode) (menu-bar-mode) (mouse-wheel-mode) (racket-xp-mode) (savehist-mode) (semantic-minor-modes-format) (show-paren-mode) (tooltip-mode)) (disabled-minor-modes (abbrev-mode) (auto-fill-function) (auto-insert-mode) (auto-save-visited-mode) (buffer-read-only) (bug-reference-mode) (bug-reference-prog-mode) (cl-old-struct-compat-mode) (column-number-mode) (compilation-in-progress) (compilation-minor-mode) (compilation-shell-minor-mode) (completion-in-region-mode) (cursor-intangible-mode) (defining-kbd-macro) (diff-minor-mode) (dired-hide-details-mode) (eldoc-mode) (electric-layout-mode) (electric-pair-mode) (electric-quote-mode) (flymake-mode) (glasses-mode) (global-prettify-symbols-mode) (global-semantic-highlight-edits-mode) (global-semantic-highlight-func-mode) (global-semantic-show-parser-state-mode) (global-semantic-show-unmatched-syntax-mode) (global-semantic-stickyfunc-mode) (global-visual-line-mode) (goto-address-mode) (goto-address-prog-mode) (horizontal-scroll-bar-mode) (hs-minor-mode) (ido-everywhere) (isearch-mode) (ispell-minor-mode) (jit-lock-debug-mode) (midnight-mode) (next-error-follow-minor-mode) (org-cdlatex-mode) (org-src-mode) (orgstruct-mode) (outline-minor-mode) (overwrite-mode) (paragraph-indent-minor-mode) (prettify-symbols-mode) (protect-buffer-from-kill-mode) (protect-process-buffer-from-kill-mode) (racket-smart-open-bracket-mode) (remember-notes-mode) (semantic-highlight-edits-mode) (semantic-highlight-func-mode) (semantic-mode) (semantic-show-parser-state-mode) (semantic-show-unmatched-syntax-mode) (semantic-stickyfunc-mode) (server-mode) (sh-electric-here-document-mode) (size-indication-mode) (sqlind-minor-mode) (temp-buffer-resize-mode) (tool-bar-mode) (transient-mark-mode) (unify-8859-on-decoding-mode) (unify-8859-on-encoding-mode) (url-handler-mode) (use-hard-newlines) (view-mode) (visible-mode) (visual-line-mode) (window-divider-mode) (xref-etags-mode)) ```
greghendershott commented 4 years ago

When I try that in Dr Racket and mouse hover on say-hello it shows the same tooltip, "no bound occurrences". The underlying analysis by drracket/check-syntax says that it is unbound a.k.a. unused.

The difference in Racket Mode is that it "surfaces this in the UI" more prominently. As a result it's going to make more evident any bugs, edge cases, or omissions in the analysis done by drracket/check-syntax.

Another case is https://github.com/racket/drracket/issues/110 which I've attempted to fix with PR https://github.com/racket/drracket/pull/362.

Also, in some cases the "blame" isn't really even drracket/check-syntax. One such example: (provide (all-defined-out)). The problem you're reporting might need to be fixed in racket/class, or in drracket/check-syntax, I don't yet know which.

Probably we should open this as an issue, also, at https://github.com/racket/drracket/issues ? If you agree, and you'd like to go ahead and do that, and link back to this issue here, that would be great. Otherwise I will.

alex-hhh commented 4 years ago

I am not sure where the right place to fix this would be, as I'm not familiar with the inner workings of drracket/check-syntax (or most of Racket itself, actually :-) ), so feel free to move this issue into a more appropriate project.

The workaround for me would be to change the face in Emacs, so they are not crossed out, as the most annoying part is when I open a Racket source file and have all the method names crossed out. It looks like this is the approach DrRacket takes (unbound names are not crossed out)

The underlying analysis by drracket/check-syntax says that it is unbound a.k.a. unused.

I am not sure that "unbound" and "unused" are synonyms: in my original example, say-hello is in fact unbound, but it is actually used.

greghendershott commented 4 years ago

For that work-around, you can customize racket-xp-unused-face to something like '(inherit default).

You won't see other, truly unused identifiers. It would be nice if Racket Mode could distinguish this, but, that's kind of the essence of the problem here. :smile:

I'll open an issue on the drracket repo and see if Robby thinks it's something that can/should be fixed there, or in racket/class.