@@ -92,6 +92,7 @@ actual Emacs buffer of the module being loaded."
92
92
(cursor (haskell-process-response-cursor process))
93
93
(warning-count 0 ))
94
94
(haskell-process-set-response-cursor process 0 )
95
+ (haskell-check-remove-overlays module-buffer)
95
96
(while (haskell-process-errors-warnings module-buffer session process buffer)
96
97
(setq warning-count (1+ warning-count)))
97
98
(haskell-process-set-response-cursor process cursor )
@@ -265,10 +266,135 @@ actual Emacs buffer of the module being loaded."
265
266
(modules (split-string modules-string " , " )))
266
267
(cons modules modules-string)))
267
268
269
+ (defface haskell-error-face
270
+ '((((supports :underline (:style wave)))
271
+ :underline (:style wave :color " #dc322f" ))
272
+ (t
273
+ :inherit error ))
274
+ " Face used for marking error lines."
275
+ :group 'haskell-mode )
276
+
277
+ (defface haskell-warning-face
278
+ '((((supports :underline (:style wave)))
279
+ :underline (:style wave :color " #b58900" ))
280
+ (t
281
+ :inherit warning ))
282
+ " Face used for marking warning lines."
283
+ :group 'haskell-mode )
284
+
285
+ (defface haskell-hole-face
286
+ '((((supports :underline (:style wave)))
287
+ :underline (:style wave :color " #6c71c4" ))
288
+ (t
289
+ :inherit warning ))
290
+ " Face used for marking hole lines."
291
+ :group 'haskell-mode )
292
+
293
+ (defvar haskell-check-error-fringe (propertize " !" 'display '(left-fringe exclamation-mark)))
294
+ (defvar haskell-check-warning-fringe (propertize " ?" 'display '(left-fringe question-mark)))
295
+ (defvar haskell-check-hole-fringe (propertize " _" 'display '(left-fringe horizontal-bar)))
296
+
297
+ (defun haskell-check-overlay-p (ovl )
298
+ (overlay-get ovl 'haskell-check ))
299
+
300
+ (defun haskell-check-filter-overlays (xs )
301
+ (cl-remove-if-not 'haskell-check-overlay-p xs))
302
+
303
+ (defun haskell-check-remove-overlays (buffer )
304
+ (with-current-buffer buffer
305
+ (remove-overlays (point-min ) (point-max ) 'haskell-check t )))
306
+
307
+ (defmacro with-overlay-properties (proplist ovl &rest body )
308
+ " Evaluate BODY with names in PROPLIST bound to the values of
309
+ correspondingly-named overlay properties of OVL."
310
+ (let ((ovlvar (cl-gensym " OVL-" )))
311
+ `(let* ((, ovlvar , ovl )
312
+ ,@(mapcar (lambda (p ) `(, p (overlay-get , ovlvar ', p ))) proplist))
313
+ ,@body )))
314
+
315
+ (defun overlay-start> (o1 o2 )
316
+ (> (overlay-start o1) (overlay-start o2)))
317
+ (defun overlay-start< (o1 o2 )
318
+ (< (overlay-start o1) (overlay-start o2)))
319
+
320
+ (defun first-overlay-in-if (test beg end )
321
+ (let ((ovls (cl-remove-if-not test (overlays-in beg end))))
322
+ (cl-first (sort (cl-copy-list ovls) 'overlay-start< ))))
323
+
324
+ (defun last-overlay-in-if (test beg end )
325
+ (let ((ovls (cl-remove-if-not test (overlays-in beg end))))
326
+ (cl-first (sort (cl-copy-list ovls) 'overlay-start> ))))
327
+
328
+ (defun haskell-error-overlay-briefly (ovl )
329
+ (with-overlay-properties (haskell-msg haskell-msg-type) ovl
330
+ (cond ((not (eq haskell-msg-type 'warning ))
331
+ haskell-msg)
332
+ ((string-prefix-p " Warning:\n " haskell-msg)
333
+ (cl-subseq haskell-msg 13 ))
334
+ (t (error " Invariant failed: a warning message from GHC has unexpected form: %s . " haskell-msg)))))
335
+
336
+ (defun haskell-goto-error-overlay (ovl )
337
+ (cond (ovl
338
+ (goto-char (overlay-start ovl))
339
+ (haskell-mode-message-line (haskell-error-overlay-briefly ovl)))
340
+ (t
341
+ (message " No further notes from Haskell compiler. " ))))
342
+
343
+ (defun haskell-goto-prev-error ()
344
+ (interactive )
345
+ (haskell-goto-error-overlay
346
+ (let ((ovl-at (cl-first (haskell-check-filter-overlays (overlays-at (point ))))))
347
+ (or (last-overlay-in-if 'haskell-check-overlay-p
348
+ (point-min ) (if ovl-at (overlay-start ovl-at) (point )))
349
+ ovl-at))))
350
+
351
+ (defun haskell-goto-next-error ()
352
+ (interactive )
353
+ (haskell-goto-error-overlay
354
+ (let ((ovl-at (cl-first (haskell-check-filter-overlays (overlays-at (point ))))))
355
+ (or (first-overlay-in-if 'haskell-check-overlay-p
356
+ (if ovl-at (overlay-end ovl-at) (point )) (point-max ))
357
+ ovl-at))))
358
+
359
+ (defun haskell-check-paint-overlay (buffer error-from-this-file-p line msg file type hole coln )
360
+ (with-current-buffer buffer
361
+ (let (beg end)
362
+ (goto-char (point-min ))
363
+ ; ; XXX: we can avoid excess buffer walking by relying on the maybe-fact that
364
+ ; ; GHC sorts error messages by line number, maybe.
365
+ (cond
366
+ (error-from-this-file-p
367
+ (forward-line (1- line))
368
+ (forward-char (1- coln))
369
+ (setq beg (point ))
370
+ (if (eq type 'hole )
371
+ (forward-char (length hole))
372
+ (skip-chars-forward " ^[:space:]" (line-end-position )))
373
+ (setq end (point )))
374
+ (t
375
+ (setq beg (point ))
376
+ (forward-line )
377
+ (setq end (point ))))
378
+ (let ((ovl (make-overlay beg end)))
379
+ (overlay-put ovl 'haskell-check t )
380
+ (overlay-put ovl 'haskell-file file)
381
+ (overlay-put ovl 'haskell-msg msg)
382
+ (overlay-put ovl 'haskell-msg-type type)
383
+ (overlay-put ovl 'help-echo msg)
384
+ (overlay-put ovl 'haskell-hole hole)
385
+ (cl-destructuring-bind (face fringe ) (cl-case type
386
+ (warning (list 'haskell-warning-face haskell-check-warning-fringe))
387
+ (hole (list 'haskell-hole-face haskell-check-hole-fringe))
388
+ (error (list 'haskell-error-face haskell-check-error-fringe)))
389
+ (overlay-put ovl 'before-string fringe )
390
+ (overlay-put ovl 'face face))))))
391
+
268
392
(defun haskell-process-errors-warnings (module-buffer session process buffer &optional return-only )
269
- " Trigger handling type errors or warnings. Either prints the
393
+ " Trigger handling type errors or warnings. Either prints the
270
394
messages in the interactive buffer or if CONT is specified,
271
- passes the error onto that."
395
+ passes the error onto that.
396
+
397
+ When MODULE-BUFFER is non-NIL, paint error overlays."
272
398
(cond
273
399
((haskell-process-consume
274
400
process
@@ -302,27 +428,31 @@ passes the error onto that."
302
428
(- (haskell-process-response-cursor process) 1 ))
303
429
(let* ((buffer (haskell-process-response process))
304
430
(file (match-string 1 buffer))
305
- (location (match-string 2 buffer))
431
+ (location-raw (match-string 2 buffer))
306
432
(error-msg (match-string 3 buffer))
307
- (warning (string-match " ^Warning:" error-msg))
308
- (splice (string-match " ^Splicing " error-msg))
433
+ (type (cond ((string-match " ^Warning:" error-msg) 'warning )
434
+ ((string-match " ^Splicing " error-msg) 'splice )
435
+ (t 'error )))
436
+ (critical (not (eq type 'warning )))
437
+ ; ; XXX: extract hole information, pass down to `haskell-check-paint-overlay'
309
438
(final-msg (format " %s :%s : %s "
310
439
(haskell-session-strip-dir session file)
311
- location
312
- error-msg)))
440
+ location-raw
441
+ error-msg))
442
+ (location (haskell-process-parse-error (concat file " :" location-raw " : x" )))
443
+ (line (plist-get location :line ))
444
+ (col1 (plist-get location :col )))
445
+ (when module-buffer
446
+ (haskell-check-paint-overlay module-buffer (string= (file-truename (buffer-file-name module-buffer)) (file-truename file))
447
+ line error-msg file type nil col1))
313
448
(if return-only
314
- (let* ((location (haskell-process-parse-error (concat file " :" location " : x" )))
315
- (file (plist-get location :file ))
316
- (line (plist-get location :line ))
317
- (col1 (plist-get location :col )))
318
- (list :file file :line line :col col1 :msg error-msg :type (if warning 'warning 'error )))
319
- (progn (funcall (cond (warning
320
- 'haskell-interactive-mode-compile-warning )
321
- (splice
322
- 'haskell-interactive-mode-compile-splice )
323
- (t 'haskell-interactive-mode-compile-error ))
449
+ (list :file file :line line :col col1 :msg error-msg :type type)
450
+ (progn (funcall (cl-case type
451
+ (warning 'haskell-interactive-mode-compile-warning )
452
+ (splice 'haskell-interactive-mode-compile-splice )
453
+ (error 'haskell-interactive-mode-compile-error ))
324
454
session final-msg)
325
- (unless warning
455
+ (when critical
326
456
(haskell-mode-message-line final-msg))
327
457
(haskell-process-trigger-suggestions
328
458
session
0 commit comments