forked from idris-hackers/idris-mode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
idris-warnings.el
132 lines (113 loc) · 5.41 KB
/
idris-warnings.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
;;; idris-warnings.el --- Mark warnings reported by Idris in buffers -*- lexical-binding: t -*-
;; Copyright (C) 2013 Hannes Mehnert
;; Author: Hannes Mehnert <hannes@mehnert.org>
;; License:
;; Inspiration is taken from SLIME/DIME (http://common-lisp.net/project/slime/) (https://github.com/dylan-lang/dylan-mode)
;; Therefore license is GPL
;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
(require 'idris-core)
(require 'idris-common-utils)
(require 'cl-lib)
(defface idris-warning-face
'((((supports :underline (:style wave)))
:underline (:style wave :color "red"))
(t
:inherit warning))
"Face for warnings from the compiler."
:group 'idris-faces)
(defvar idris-warnings-buffers '() "All buffers which have warnings.")
(defvar-local idris-warnings '() "All warnings in the current buffer.")
(defvar idris-raw-warnings '() "All warnings from Idris.")
(defun idris-warning-event-hook-function (event)
(pcase event
(`(:warning ,output ,_target)
(idris-warning-overlay output)
t)
(_ nil)))
(defun idris-warning-reset-all ()
(mapc #'idris-warning-reset-buffer idris-warnings-buffers)
(setq idris-raw-warnings '())
(setq idris-warnings-buffers '()))
(defun idris-warning-reset-buffer (buffer)
(when (buffer-live-p buffer)
(with-current-buffer buffer (idris-warning-reset))))
(defun idris-warning-reset ()
(mapc #'delete-overlay idris-warnings)
(setq idris-warnings '())
(delq (current-buffer) idris-warnings-buffers))
(defun idris-warning-overlay-p (overlay)
(overlay-get overlay 'idris-warning))
(defun idris-warning-overlay-at-point (point)
"Return the overlay for a note starting at POINT, otherwise nil."
(cl-find point (cl-remove-if-not 'idris-warning-overlay-p (overlays-at point))
:key 'overlay-start))
(defun idris-warning-overlay (warning)
"Add a compiler warning to the buffer as an overlay.
May merge overlays, if there's already one in the same location.
WARNING is of form (filename (startline startcolumn) (endline endcolumn)
message &optional highlighting-spans).
As of 20140807 (Idris 0.9.14.1-git:abee538) (endline endcolumn)
is mostly the same as (startline startcolumn)"
(cl-destructuring-bind (filename sl1 sl2 message spans) warning
(let ((startline (if (>=-protocol-version 2 1)
(1+ (nth 0 sl1))
(nth 0 sl1)))
(startcol (if (>=-protocol-version 2 1)
(nth 1 sl1)
(1- (nth 1 sl1))))
(endline (if (>=-protocol-version 2 1)
(1+ (nth 0 sl2))
(nth 0 sl2)))
(endcol (if (>=-protocol-version 2 1)
(nth 1 sl2)
(1- (nth 1 sl2)))))
(push (list filename startline startcol message spans) idris-raw-warnings)
(let* ((fullpath (concat (file-name-as-directory idris-process-current-working-directory)
filename))
(buffer (get-file-buffer fullpath)))
(when (not (null buffer))
(with-current-buffer buffer
(save-excursion
(save-restriction
(widen) ;; Show errors at the proper location in narrowed buffers
(goto-char (point-min))
(let* ((startp (line-beginning-position startline))
(endp (line-end-position startline))
(start (+ startp startcol))
(end (if (and (= startline endline) (= startcol endcol))
;; a hack to have warnings, which point to empty lines, reported
(if (= startp endp)
(progn (goto-char startp)
(insert " ")
(1+ endp))
endp)
(+ (line-beginning-position endline) endcol)))
(overlay (idris-warning-overlay-at-point startp)))
(if overlay
(idris-warning-merge-overlays overlay message)
(idris-warning-create-overlay start end message)))))))))))
(defun idris-warning-merge-overlays (overlay message)
(overlay-put overlay 'help-echo
(concat (overlay-get overlay 'help-echo) "\n" message)))
(defun idris-warning-create-overlay (start end message)
(let ((overlay (make-overlay start end)))
(overlay-put overlay 'idris-warning message)
(overlay-put overlay 'help-echo message)
(overlay-put overlay 'face 'idris-warning-face)
(overlay-put overlay 'mouse-face 'highlight)
(push overlay idris-warnings)
(unless (memq (current-buffer) idris-warnings-buffers)
(push (current-buffer) idris-warnings-buffers))
overlay))
(provide 'idris-warnings)