Skip to content
This repository was archived by the owner on Nov 23, 2021. It is now read-only.

Commit be56406

Browse files
authored
Merge pull request #15 from gdkrmr/dev
Dev
2 parents 0eaa321 + 0db693e commit be56406

File tree

2 files changed

+149
-113
lines changed

2 files changed

+149
-113
lines changed

Diff for: flycheck-julia.el

+92-76
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@
3333
;;
3434
;; Add the following to your init file:
3535
;;
36-
;; ;; Enable Flycheck checker
36+
;; (add-to-list 'load-path "/path/to/directory/containing/flycheck-julia.el/file")
37+
;; (require 'flycheck-julia)
3738
;; (flycheck-julia-setup)
39+
;; (add-to-list 'flycheck-global-modes 'julia-mode)
40+
;; (add-to-list 'flycheck-global-modes 'ess-julia-mode)
3841
;;
3942
;; # Usage
4043
;;
@@ -47,8 +50,6 @@
4750
(require 'json)
4851
(require 'flycheck)
4952

50-
51-
5253
(defgroup flycheck-julia nil
5354
"flycheck-julia options"
5455
:prefix "flycheck-julia"
@@ -65,97 +66,111 @@
6566
:type 'integer
6667
:group 'flycheck-julia)
6768

68-
(defcustom flycheck-julia-max-wait 1
69-
"The maximum time to wait for an answer from the server."
70-
:type 'number
71-
:group 'flycheck-julia)
72-
73-
(defun flycheck-julia-start-or-query-server (checker callback)
74-
"Start a Julia syntax check, init the server if necessary.
75-
76-
CHECKER and CALLBACK are flycheck requirements."
77-
78-
;; TODO: use (when ...) here and do the query
79-
(if (not (flycheck-julia-serverp))
80-
(progn
81-
(message "no server --- starting")
82-
(flycheck-julia-server-start)
83-
(funcall callback 'finished nil))
84-
(message "server running --- querying")
85-
(funcall callback 'finished (flycheck-julia-server-query checker))))
69+
;; (defcustom flycheck-julia-max-wait 0.01
70+
;; "The maximum time to wait for an answer from the server."
71+
;; :type 'number
72+
;; :group 'flycheck-julia)
8673

87-
;; TODO: make these functions interactive
88-
;; needs checking, if the server is already running, closing of the linter
89-
;; buffer, etc...
74+
;; This is the variable that is used to receive the data from the server
75+
;; TODO: Find out if this is possible without a global value
76+
(setq flycheck-julia-proc-output "")
77+
(setq flycheck-julia-server-proc nil)
9078

91-
(defun flycheck-julia-serverp ()
92-
"Check if the lint server is up"
93-
(get-process "flycheck-julia-server"))
79+
(defun flycheck-julia-server-p ()
80+
"Check if the Lint server is up, returns the process or nil"
81+
(processp flycheck-julia-server-proc))
9482

9583
(defun flycheck-julia-server-start ()
96-
"Start the julia server for linting."
97-
(start-process-shell-command
98-
"flycheck-julia-server" "*julia-linter*"
99-
;; TODO: use pipes or something different than an open port
100-
;; TODO: decide how too handle query on exit (set-process-query-on-exit-flag)
101-
(concat flycheck-julia-executable
102-
" -e \'using Lint\; lintserver\("
103-
(number-to-string flycheck-julia-port)
104-
"\, \"standard-linter-v2\"\)\'")))
84+
"If not already running, start the Julia server for linting."
85+
(if (not (flycheck-julia-server-p))
86+
(setq flycheck-julia-server-proc
87+
(start-process-shell-command
88+
"flycheck-julia-server" "*julia-linter*"
89+
;; TODO: use pipes or something different than an open port
90+
;; TODO: decide how too handle query on exit (set-process-query-on-exit-flag)
91+
(concat flycheck-julia-executable
92+
" -e \'using Lint\; lintserver\("
93+
(number-to-string flycheck-julia-port)
94+
"\, \"standard-linter-v2\"\)\'")))
95+
(message "flycheck-julia-server-start: server already running.")))
10596

10697
(defun flycheck-julia-server-stop ()
107-
"Kill the julia lint server."
108-
(kill-process (get-process "flycheck-julia-server")))
98+
"Kill the Julia lint server."
99+
(interactive)
100+
(delete-process flycheck-julia-server-proc)
101+
(setq flycheck-julia-server-proc nil))
109102

110103
(defun flycheck-julia-server-restart ()
111-
"Kill the julia lint server and restart it."
104+
"Kill the Julia lint server and restart it."
105+
(interactive)
112106
(flycheck-julia-server-stop)
113107
(sleep-for 5)
114108
(flycheck-julia-server-start))
115109

116-
(defun flycheck-julia-server-query (checker)
110+
(defun flycheck-julia-start-or-query-server (checker callback)
111+
"Start a Julia syntax check, start the server if necessary.
112+
113+
CHECKER and CALLBACK are flycheck requirements."
114+
115+
(when (not (flycheck-julia-server-p)) (flycheck-julia-server-start))
116+
(flycheck-julia-server-query checker callback))
117+
118+
(defun flycheck-julia-server-query (checker callback)
117119
"Query a lint.
118120
119121
Query a lint for the current buffer and return the errors as
120122
flycheck objects.
121123
122124
CHECKER is 'julia-linter, this is a flycheck internal."
123-
124-
;; TODO: is it better to have the network process running all the time?
125-
;; i.e. is there overhead for using a new process every time this function is run?
126-
(let ((proc (make-network-process
127-
:name "julia-lint-client"
128-
:host 'local
129-
:service flycheck-julia-port))
130-
(query-list `(("file" . ,(if buffer-file-name (buffer-file-name) ""))
131-
("code_str" . ,(buffer-substring-no-properties
132-
(point-min) (point-max)))
133-
("ignore_info" . ,json-false)
134-
("ignore_warnings" . ,json-false)
135-
("show_code" . t)))
136-
(proc-output nil))
137-
138-
;; Network processes may be return results in different orders, then we are
139-
;; screwed, not sure what to do about this? use named pipes? use sockets?
140-
;; use priority queues?
141-
;; I actually never observed this, so ignoring it for now.
142-
;; TODO: this gives a compiler warning, try to make the warning disappear!
143-
(defun flycheck-julia-keep-output (process output)
144-
(setq proc-output (concat proc-output output)))
145-
(set-process-filter proc 'flycheck-julia-keep-output)
146-
147-
(process-send-string proc (json-encode query-list))
148-
149-
;; Because our process is asynchronous, we need to
150-
;; 1. to wait and
151-
;; 2. the string is sent in 500 char pieces and the results may arrive in a
152-
;; different order. -> I did not observe this behavior until now!
153-
;; TODO: figure out a way to do this completely asynchronous.
154-
(accept-process-output proc flycheck-julia-max-wait)
155-
(flycheck-julia-error-parser
156-
(when proc-output (json-read-from-string proc-output))
157-
checker
158-
(current-buffer))))
125+
(setq flycheck-julia-proc-output "")
126+
127+
(let* ((filter (lambda (process output)
128+
(setq flycheck-julia-proc-output
129+
(concat flycheck-julia-proc-output output))))
130+
;; This is where the asynchronous magic is supposed to happen:
131+
;;
132+
;; the returned string can be:
133+
;;
134+
;; "", i.e the server is not running yet -> not parsed correctly
135+
;;
136+
;; "[]", there are no errors -> parsed correctly to json
137+
;;
138+
;; a complete json object -> there are errors/issues in the file,
139+
;; everything is fine
140+
;;
141+
;; an incomplete json object -> the object was not retrieved correctly
142+
;;
143+
;;Also: this sentinl should only be called if the connection is closed,
144+
;; if it gets with a different message, something is wrong
145+
(sentinel (lambda (process event)
146+
(unless (string= event "connection broken by remote peer\n")
147+
(message "connection not closed!"))
148+
(delete-process process)
149+
(if (string= flycheck-julia-proc-output "")
150+
(funcall callback 'interrupted)
151+
(condition-case nil
152+
(funcall callback 'finished
153+
(flycheck-julia-error-parser
154+
(json-read-from-string
155+
flycheck-julia-proc-output)
156+
checker
157+
(current-buffer)))
158+
(error (funcall callback 'errored
159+
"there was a parsing error"))))))
160+
;; if the server is not running yet, this fails because it cannot
161+
;; connect to the server and np will be nil
162+
(np (ignore-errors (make-network-process :name "flycheck-julia-client"
163+
:host 'local
164+
:service flycheck-julia-port
165+
:filter filter
166+
:sentinel sentinel)))
167+
(js (json-encode `(("file" . ,(if buffer-file-name (buffer-file-name) (buffer-name)))
168+
("code_str" . ,(buffer-substring-no-properties (point-min) (point-max)))
169+
("ignore_info" . ,json-false)
170+
("ignore_warnings" . ,json-false)
171+
("show_code" . t)))))
172+
;; return immediately without any errors, leave that to the sentinel
173+
(if np (process-send-string np js) (funcall callback 'interrupted))))
159174

160175
(defun flycheck-julia-error-parser (errors checker buffer)
161176
"Parse the error returned from the Julia lint server.
@@ -173,6 +188,7 @@ BUFFER is the buffer that was checked for errors."
173188
;; Lint.jl returns 0-based line and column numbers
174189
;; Lint.jl returns only a line in the format [[l, 0], [l, 80]],
175190
:line (1+ (aref (aref (cdr (assoc 'position (cdr (assoc 'location it)))) 0) 0))
191+
;; TODO: simply put 0 here?
176192
:column (1+ (aref (aref (cdr (assoc 'position (cdr (assoc 'location it)))) 0) 1))
177193
:message (cdr (assoc 'excerpt it))
178194
:level (intern (cdr (assoc 'severity it)))))

Diff for: test/flycheck-julia-test.el

+57-37
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,25 @@
2222

2323
;;; Commentary:
2424

25-
;; Test cases Flycheck OCaml.
25+
;; Test cases Flycheck Julia.
2626

2727
;;; Code:
2828

2929

30+
(require 'flycheck)
3031
(require 'flycheck-julia)
3132
(require 'flycheck-ert)
3233

3334
(load "ess-autoloads.el")
3435
(require 'ess-site)
36+
(flycheck-julia-setup)
37+
(setq flycheck-julia-port 3457)
3538

3639
(ert-deftest flycheck-julia-start-server ()
3740
:tags '(server)
3841
(flycheck-julia-server-start)
39-
(should (flycheck-julia-serverp))
42+
(sleep-for 5)
43+
(should (flycheck-julia-server-p))
4044
(flycheck-julia-server-stop)
4145
(sleep-for 5)
4246
(kill-buffer "*julia-linter*"))
@@ -45,61 +49,77 @@
4549
:tags '(server)
4650
(flycheck-julia-server-start)
4751
(sleep-for 5)
52+
(should (flycheck-julia-server-p))
4853
(flycheck-julia-server-stop)
4954
(sleep-for 5)
50-
(should (not (flycheck-julia-serverp)))
55+
(should (not (flycheck-julia-server-p)))
5156
(sleep-for 5)
5257
(kill-buffer "*julia-linter*"))
5358

5459
(ert-deftest flycheck-julia-restart-server ()
5560
:tags '(server)
5661
(flycheck-julia-server-start)
5762
(sleep-for 5)
63+
(should (flycheck-julia-server-p))
5864
(flycheck-julia-server-restart)
5965
(sleep-for 5)
60-
(should (flycheck-julia-serverp))
66+
(should (flycheck-julia-server-p))
6167
(flycheck-julia-server-stop)
6268
(sleep-for 5)
6369
(kill-buffer "*julia-linter*"))
6470

71+
;; (ert-deftest flycheck-julia-test-all ()
72+
;; (with-temp-buffer
73+
;; (ess-julia-mode)
74+
;; (flycheck-mode)
75+
;; (sleep-for 5)
76+
;; (print (flycheck-may-enable-checker 'flycheck-julia))
77+
;; (print flycheck-enabled-checkers)
78+
;; (flycheck- select-checker 'flycheck-julia)
79+
;; (print (flycheck-may-use-checker 'flycheck-julia))
80+
;; (insert-string "\ny\n")
81+
;; (flycheck-buffer)
82+
;; (sleep-for 5)
83+
;; (print flycheck-current-errors)
84+
;; (flycheck-buffer)
85+
;; (sleep-for 5)
86+
;; (print flycheck-current-errors)
87+
;; (sleep-for 5)
88+
;; (print flycheck-current-errors)
89+
;; (sleep-for 5)
90+
;; (print flycheck-current-errors)
91+
;; (sleep-for 5)
92+
;; (print flycheck-current-errors)
93+
;; (should (flycheck-julia-server-p))
94+
;; )
95+
;; (sleep-for 5)
96+
;; (kill-buffer "*julia-linter*"))
97+
6598
;; Lint.jl does extensive testing on the correctness of errors, so we only check
6699
;; that querying the server actually works.
67100
;; (ert-deftest flycheck-julia-test-query ()
68101
;; :tags '(query)
69102
;; (flycheck-julia-server-start)
70-
;; (sleep-for 15)
71-
;; (should
72-
;; (with-temp-buffer
73-
;; (insert-string "\ny\n")
74-
;; (ignore-errors
75-
;; (flycheck-julia-server-query 'flycheck-julia)
76-
;; (sleep-for 15)
77-
;; (flycheck-julia-server-query 'flycheck-julia)
78-
;; (sleep-for 15)
79-
;; (flycheck-julia-server-query 'flycheck-julia)
80-
;; (sleep-for 15)
81-
;; (flycheck-julia-server-query 'flycheck-julia)
82-
;; (sleep-for 15)
83-
;; (flycheck-julia-server-query 'flycheck-julia)
84-
;; (sleep-for 15)
85-
;; (flycheck-julia-server-query 'flycheck-julia))
86-
87-
;; ;; some debug stuff:
88-
;; ;; Print out the contents of the julia server process buffer
89-
;; (sleep-for 15)
90-
;; (let ((oldbuf (current-buffer)))
91-
;; (set-buffer (get-buffer "*julia-linter*"))
92-
;; (message (buffer-substring-no-properties (point-min) (point-max)))
93-
;; (set-buffer oldbuf))
94-
;; (message (buffer-name))
95-
96-
;; ;; check for the error
97-
;; ;; (sleep-for 5)
98-
;; (let ((retobj (flycheck-julia-server-query 'flycheck-julia)))
99-
;; (sleep-for 5)
100-
;; (cl-search
101-
;; "undeclared symbol"
102-
;; (aref (nth 0 retobj) 6)))))
103+
;; (sleep-for 5)
104+
;; (with-temp-buffer
105+
;; (insert-string "\ny\n")
106+
;; (ess-julia-mode)
107+
;; (flycheck-mode)
108+
;; (sleep-for 15)
109+
110+
;; (message "test 0")
111+
;; (flycheck-buffer)
112+
;; (print flycheck-current-errors)
113+
;; (sleep-for 15)
114+
;; (print flycheck-current-errors)
115+
;; ;; Seeping causes the network process to close the connection
116+
;; ;; Fails, because process is already dead
117+
;; (message "test 1")
118+
;; (flycheck-buffer)
119+
;; (print flycheck-current-errors)
120+
;; (sleep-for 15)
121+
;; (print flycheck-current-errors)
122+
;; (should (cl-search "undeclared symbol" (aref (nth 0 flycheck-current-errors) 6))))
103123
;; ;; cleanup
104124
;; (sleep-for 5)
105125
;; (flycheck-julia-server-stop)

0 commit comments

Comments
 (0)