Skip to content

Commit f8521d9

Browse files
committed
Dealt with haskell-ident-at-point returning nil.
The documentation mandates that `haskell-ident-at-point` return nil when there is no identifier at point; however, apparently, it instead returned `""` in that case at some point, and so some code made faulty assumptions based on that.
1 parent 4892713 commit f8521d9

File tree

4 files changed

+87
-78
lines changed

4 files changed

+87
-78
lines changed

haskell-commands.el

Lines changed: 77 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -279,23 +279,28 @@ given a prefix arg."
279279
"Print info on the identifier at point.
280280
If PROMPT-VALUE is non-nil, request identifier via mini-buffer."
281281
(interactive "P")
282-
(haskell-process-do-simple-echo
283-
(let ((ident (replace-regexp-in-string
284-
"^!\\([A-Z_a-z]\\)"
285-
"\\1"
286-
(if prompt-value
287-
(read-from-minibuffer "Info: " (haskell-ident-at-point))
288-
(haskell-ident-at-point))))
289-
(modname (unless prompt-value
290-
(haskell-utils-parse-import-statement-at-point))))
291-
(if modname
292-
(format ":browse! %s" modname)
293-
(format (if (string-match "^[a-zA-Z_]" ident)
294-
":info %s"
295-
":info (%s)")
296-
(or ident
297-
(haskell-ident-at-point)))))
298-
'haskell-mode))
282+
(let ((at-point (haskell-ident-at-point)))
283+
(when (or prompt-value at-point)
284+
(let* ((ident (replace-regexp-in-string
285+
"^!\\([A-Z_a-z]\\)"
286+
"\\1"
287+
(if prompt-value
288+
(read-from-minibuffer "Info: " at-point)
289+
at-point)))
290+
(modname (unless prompt-value
291+
(haskell-utils-parse-import-statement-at-point)))
292+
(command (cond
293+
(modname
294+
(format ":browse! %s" modname))
295+
((string= ident "") ; For the minibuffer input case
296+
nil)
297+
(t (format (if (string-match "^[a-zA-Z_]" ident)
298+
":info %s"
299+
":info (%s)")
300+
(or ident
301+
at-point))))))
302+
(when command
303+
(haskell-process-do-simple-echo command 'haskell-mode))))))
299304

300305
;;;###autoload
301306
(defun haskell-process-do-type (&optional insert-value)
@@ -369,67 +374,71 @@ to to get there."
369374
(defun haskell-process-insert-type ()
370375
"Get the identifer at the point and insert its type, if
371376
possible, using GHCi's :type."
372-
(let ((process (haskell-interactive-process))
373-
(query (let ((ident (haskell-ident-at-point)))
374-
(format (if (string-match "^[_[:lower:][:upper:]]" ident)
375-
":type %s"
376-
":type (%s)")
377-
ident))))
378-
(haskell-process-queue-command
379-
process
380-
(make-haskell-command
381-
:state (list process query (current-buffer))
382-
:go (lambda (state)
383-
(haskell-process-send-string (nth 0 state)
384-
(nth 1 state)))
385-
:complete (lambda (state response)
386-
(cond
387-
;; TODO: Generalize this into a function.
388-
((or (string-match "^Top level" response)
389-
(string-match "^<interactive>" response))
390-
(message response))
391-
(t
392-
(with-current-buffer (nth 2 state)
393-
(goto-char (line-beginning-position))
394-
(insert (format "%s\n" (replace-regexp-in-string "\n$" "" response)))))))))))
377+
(let ((ident (haskell-ident-at-point)))
378+
(when ident
379+
(let ((process (haskell-interactive-process))
380+
(query (format (if (string-match "^[_[:lower:][:upper:]]" ident)
381+
":type %s"
382+
":type (%s)")
383+
ident)))
384+
(haskell-process-queue-command
385+
process
386+
(make-haskell-command
387+
:state (list process query (current-buffer))
388+
:go (lambda (state)
389+
(haskell-process-send-string (nth 0 state)
390+
(nth 1 state)))
391+
:complete (lambda (state response)
392+
(cond
393+
;; TODO: Generalize this into a function.
394+
((or (string-match "^Top level" response)
395+
(string-match "^<interactive>" response))
396+
(message response))
397+
(t
398+
(with-current-buffer (nth 2 state)
399+
(goto-char (line-beginning-position))
400+
(insert (format "%s\n" (replace-regexp-in-string "\n$" "" response)))))))))))))
395401

396402
(defun haskell-mode-find-def (ident)
397403
"Find definition location of identifier. Uses the GHCi process
398-
to find the location.
404+
to find the location. Returns `nil' if it can't find the
405+
identifier or the identifier isn't a string.
399406
400407
Returns:
401408
402409
(library <package> <module>)
403410
(file <path> <line> <col>)
404411
(module <name>)
412+
nil
405413
"
406-
(let ((reply (haskell-process-queue-sync-request
407-
(haskell-interactive-process)
408-
(format (if (string-match "^[a-zA-Z_]" ident)
409-
":info %s"
410-
":info (%s)")
411-
ident))))
412-
(let ((match (string-match "-- Defined \\(at\\|in\\) \\(.+\\)$" reply)))
413-
(when match
414-
(let ((defined (match-string 2 reply)))
415-
(let ((match (string-match "\\(.+?\\):\\([0-9]+\\):\\([0-9]+\\)$" defined)))
416-
(cond
417-
(match
418-
(list 'file
419-
(expand-file-name (match-string 1 defined)
420-
(haskell-session-current-dir (haskell-interactive-session)))
421-
(string-to-number (match-string 2 defined))
422-
(string-to-number (match-string 3 defined))))
423-
(t
424-
(let ((match (string-match "`\\(.+?\\):\\(.+?\\)'$" defined)))
425-
(if match
426-
(list 'library
427-
(match-string 1 defined)
428-
(match-string 2 defined))
429-
(let ((match (string-match "`\\(.+?\\)'$" defined)))
430-
(if match
431-
(list 'module
432-
(match-string 1 defined))))))))))))))
414+
(when (stringp ident)
415+
(let ((reply (haskell-process-queue-sync-request
416+
(haskell-interactive-process)
417+
(format (if (string-match "^[a-zA-Z_]" ident)
418+
":info %s"
419+
":info (%s)")
420+
ident))))
421+
(let ((match (string-match "-- Defined \\(at\\|in\\) \\(.+\\)$" reply)))
422+
(when match
423+
(let ((defined (match-string 2 reply)))
424+
(let ((match (string-match "\\(.+?\\):\\([0-9]+\\):\\([0-9]+\\)$" defined)))
425+
(cond
426+
(match
427+
(list 'file
428+
(expand-file-name (match-string 1 defined)
429+
(haskell-session-current-dir (haskell-interactive-session)))
430+
(string-to-number (match-string 2 defined))
431+
(string-to-number (match-string 3 defined))))
432+
(t
433+
(let ((match (string-match "`\\(.+?\\):\\(.+?\\)'$" defined)))
434+
(if match
435+
(list 'library
436+
(match-string 1 defined)
437+
(match-string 2 defined))
438+
(let ((match (string-match "`\\(.+?\\)'$" defined)))
439+
(if match
440+
(list 'module
441+
(match-string 1 defined)))))))))))))))
433442

434443
;;;###autoload
435444
(defun haskell-mode-jump-to-def (ident)

haskell-doc.el

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1677,7 +1677,7 @@ If `haskell-doc-use-inf-haskell' is non-nil, this function will consult
16771677
the inferior Haskell process for type/kind information, rather than using
16781678
the haskell-doc database."
16791679
(if haskell-doc-use-inf-haskell
1680-
(unless (string= "" sym)
1680+
(unless (or (null sym) (string= "" sym))
16811681
(let* ((message-log-max nil)
16821682
(result (ignore-errors
16831683
(unwind-protect

haskell.el

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,11 +299,11 @@
299299
(insert (cdr mapping)))
300300
(insert module)))
301301
(haskell-mode-format-imports)))
302-
((not (string= "" (save-excursion (forward-char -1) (haskell-ident-at-point))))
302+
(t
303303
(let ((ident (save-excursion (forward-char -1) (haskell-ident-at-point))))
304304
(insert " ")
305-
(haskell-process-do-try-info ident)))
306-
(t (insert " ")))))
305+
(when ident
306+
(haskell-process-do-try-info ident)))))))
307307

308308
;;;###autoload
309309
(defun haskell-mode-jump-to-tag (&optional next-p)
@@ -312,7 +312,7 @@
312312
(let ((ident (haskell-ident-at-point))
313313
(tags-file-name (haskell-session-tags-filename (haskell-session)))
314314
(tags-revert-without-query t))
315-
(when (not (string= "" (haskell-string-trim ident)))
315+
(when (and (stringp ident) (not (string= "" (haskell-string-trim ident))))
316316
(cond ((file-exists-p tags-file-name)
317317
(find-tag ident next-p))
318318
(t (haskell-process-generate-tags ident))))))

inf-haskell.el

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ in the buffer. This can be done interactively with the \\[universal-argument] p
490490
The returned info is cached for reuse by `haskell-doc-mode'."
491491
(interactive
492492
(let ((sym (haskell-ident-at-point)))
493-
(list (read-string (if (> (length sym) 0)
493+
(list (read-string (if sym
494494
(format "Show type of (default %s): " sym)
495495
"Show type of: ")
496496
nil nil sym)
@@ -526,7 +526,7 @@ The returned info is cached for reuse by `haskell-doc-mode'."
526526
"Query the haskell process for the kind of the given expression."
527527
(interactive
528528
(let ((type (haskell-ident-at-point)))
529-
(list (read-string (if (> (length type) 0)
529+
(list (read-string (if type
530530
(format "Show kind of (default %s): " type)
531531
"Show kind of: ")
532532
nil nil type))))
@@ -539,7 +539,7 @@ The returned info is cached for reuse by `haskell-doc-mode'."
539539
"Query the haskell process for the info of the given expression."
540540
(interactive
541541
(let ((sym (haskell-ident-at-point)))
542-
(list (read-string (if (> (length sym) 0)
542+
(list (read-string (if sym
543543
(format "Show info of (default %s): " sym)
544544
"Show info of: ")
545545
nil nil sym))))
@@ -552,7 +552,7 @@ The returned info is cached for reuse by `haskell-doc-mode'."
552552
"Attempt to locate and jump to the definition of the given expression."
553553
(interactive
554554
(let ((sym (haskell-ident-at-point)))
555-
(list (read-string (if (> (length sym) 0)
555+
(list (read-string (if sym
556556
(format "Find definition of (default %s): " sym)
557557
"Find definition of: ")
558558
nil nil sym))))
@@ -771,7 +771,7 @@ see if this is newer than `haskell-package-conf-file' every time
771771
we load it."
772772
(interactive
773773
(let ((sym (haskell-ident-at-point)))
774-
(list (read-string (if (> (length sym) 0)
774+
(list (read-string (if sym
775775
(format "Find documentation of (default %s): " sym)
776776
"Find documentation of: ")
777777
nil nil sym))))

0 commit comments

Comments
 (0)