Document reserved keys
[emacs.git] / lisp / progmodes / flymake-proc.el
blobc5bb79fee66aee3fe4d4919414a619bc679f11f7
1 ;;; flymake-proc.el --- Flymake backend for external tools -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2003-2018 Free Software Foundation, Inc.
5 ;; Author: Pavel Kobyakov <pk_at_work@yahoo.com>
6 ;; Maintainer: Leo Liu <sdl.web@gmail.com>
7 ;; Version: 0.3
8 ;; Keywords: c languages tools
10 ;; This file is part of GNU Emacs.
12 ;; GNU Emacs is free software: you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation, either version 3 of the License, or
15 ;; (at your option) any later version.
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
25 ;;; Commentary:
27 ;; Flymake is a minor Emacs mode performing on-the-fly syntax checks.
29 ;; This file contains a significant part of the original flymake's
30 ;; implementation, a buffer-checking mechanism that parses the output
31 ;; of an external syntax check tool with regular expressions.
33 ;; That work has been adapted into a flymake "backend" function,
34 ;; `flymake-proc-legacy-flymake' suitable for adding to the
35 ;; `flymake-diagnostic-functions' variable.
37 ;;; Bugs/todo:
39 ;; - Only uses "Makefile", not "makefile" or "GNUmakefile"
40 ;; (from http://bugs.debian.org/337339).
42 ;;; Code:
44 (require 'flymake)
46 (define-obsolete-variable-alias 'flymake-compilation-prevents-syntax-check
47 'flymake-proc-compilation-prevents-syntax-check "26.1")
49 (defcustom flymake-proc-compilation-prevents-syntax-check t
50 "If non-nil, don't start syntax check if compilation is running."
51 :group 'flymake
52 :type 'boolean)
54 (define-obsolete-variable-alias 'flymake-xml-program
55 'flymake-proc-xml-program "26.1")
57 (defcustom flymake-proc-xml-program
58 (if (executable-find "xmlstarlet") "xmlstarlet" "xml")
59 "Program to use for XML validation."
60 :type 'file
61 :group 'flymake
62 :version "24.4")
64 (define-obsolete-variable-alias 'flymake-master-file-dirs
65 'flymake-proc-master-file-dirs "26.1")
67 (defcustom flymake-proc-master-file-dirs '("." "./src" "./UnitTest")
68 "Dirs where to look for master files."
69 :group 'flymake
70 :type '(repeat (string)))
72 (define-obsolete-variable-alias 'flymake-master-file-count-limit
73 'flymake-proc-master-file-count-limit "26.1")
75 (defcustom flymake-proc-master-file-count-limit 32
76 "Max number of master files to check."
77 :group 'flymake
78 :type 'integer)
80 (define-obsolete-variable-alias 'flymake-allowed-file-name-masks
81 'flymake-proc-allowed-file-name-masks "26.1")
83 (defcustom flymake-proc-allowed-file-name-masks
84 '(("\\.\\(?:c\\(?:pp\\|xx\\|\\+\\+\\)?\\|CC\\)\\'"
85 flymake-proc-simple-make-init
86 nil
87 flymake-proc-real-file-name-considering-includes)
88 ("\\.xml\\'" flymake-proc-xml-init)
89 ("\\.html?\\'" flymake-proc-xml-init)
90 ("\\.cs\\'" flymake-proc-simple-make-init)
91 ;; ("\\.p[ml]\\'" flymake-proc-perl-init)
92 ("\\.php[345]?\\'" flymake-proc-php-init)
93 ("\\.h\\'" flymake-proc-master-make-header-init flymake-proc-master-cleanup)
94 ("\\.java\\'" flymake-proc-simple-make-java-init flymake-proc-simple-java-cleanup)
95 ("[0-9]+\\.tex\\'" flymake-proc-master-tex-init flymake-proc-master-cleanup)
96 ("\\.tex\\'" flymake-proc-simple-tex-init)
97 ("\\.idl\\'" flymake-proc-simple-make-init)
98 ;; ("\\.cpp\\'" 1)
99 ;; ("\\.java\\'" 3)
100 ;; ("\\.h\\'" 2 ("\\.cpp\\'" "\\.c\\'")
101 ;; ("[ \t]*#[ \t]*include[ \t]*\"\\([\w0-9/\\_\.]*[/\\]*\\)\\(%s\\)\"" 1 2))
102 ;; ("\\.idl\\'" 1)
103 ;; ("\\.odl\\'" 1)
104 ;; ("[0-9]+\\.tex\\'" 2 ("\\.tex\\'")
105 ;; ("[ \t]*\\input[ \t]*{\\(.*\\)\\(%s\\)}" 1 2 ))
106 ;; ("\\.tex\\'" 1)
108 "Files syntax checking is allowed for.
109 This is an alist with elements of the form:
110 REGEXP INIT [CLEANUP [NAME]]
111 REGEXP is a regular expression that matches a file name.
112 INIT is the init function to use.
113 CLEANUP is the cleanup function to use, default `flymake-proc-simple-cleanup'.
114 NAME is the file name function to use, default `flymake-proc-get-real-file-name'."
115 :group 'flymake
116 :type '(alist :key-type (regexp :tag "File regexp")
117 :value-type
118 (list :tag "Handler functions"
119 (function :tag "Init function")
120 (choice :tag "Cleanup function"
121 (const :tag "flymake-proc-simple-cleanup" nil)
122 function)
123 (choice :tag "Name function"
124 (const :tag "flymake-proc-get-real-file-name" nil)
125 function))))
127 (defvar-local flymake-proc--current-process nil
128 "Currently active Flymake process for a buffer, if any.")
130 (defvar flymake-proc--report-fn nil
131 "If bound, function used to report back to Flymake's UI.")
133 (defun flymake-proc-reformat-err-line-patterns-from-compile-el (original-list)
134 "Grab error line patterns from ORIGINAL-LIST in compile.el format.
135 Convert it to Flymake internal format."
136 (let* ((converted-list '()))
137 (dolist (item original-list)
138 (setq item (cdr item))
139 (let ((regexp (nth 0 item))
140 (file (nth 1 item))
141 (line (nth 2 item))
142 (col (nth 3 item)))
143 (if (consp file) (setq file (car file)))
144 (if (consp line) (setq line (car line)))
145 (if (consp col) (setq col (car col)))
147 (when (not (functionp line))
148 (setq converted-list (cons (list regexp file line col) converted-list)))))
149 converted-list))
151 (defvar flymake-proc-err-line-patterns ; regexp file-idx line-idx col-idx (optional) text-idx(optional), match-end to end of string is error text
152 (append
154 ;; MS Visual C++ 6.0
155 ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) : \\(\\(error\\|warning\\|fatal error\\) \\(C[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
156 1 3 nil 4)
157 ;; jikes
158 ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\):\\([0-9]+\\):[0-9]+:[0-9]+:[0-9]+: \\(\\(Error\\|Warning\\|Caution\\|Semantic Error\\):[ \t\n]*\\(.+\\)\\)"
159 1 3 nil 4)
160 ;; MS midl
161 ("midl[ ]*:[ ]*\\(command line error .*\\)"
162 nil nil nil 1)
163 ;; MS C#
164 ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\),[0-9]+): \\(\\(error\\|warning\\|fatal error\\) \\(CS[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
165 1 3 nil 4)
166 ;; perl
167 ("\\(.*\\) at \\([^ \n]+\\) line \\([0-9]+\\)[,.\n]" 2 3 nil 1)
168 ;; PHP
169 ("\\(?:Parse\\|Fatal\\) error: \\(.*\\) in \\(.*\\) on line \\([0-9]+\\)" 2 3 nil 1)
170 ;; LaTeX warnings (fileless) ("\\(LaTeX \\(Warning\\|Error\\): .*\\) on input line \\([0-9]+\\)" 20 3 nil 1)
171 ;; ant/javac. Note this also matches gcc warnings!
172 (" *\\(\\[javac\\] *\\)?\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\):\\([0-9]+\\)\\(?::\\([0-9]+\\)\\)?:[ \t\n]*\\(.+\\)"
173 2 4 5 6))
174 ;; compilation-error-regexp-alist)
175 (flymake-proc-reformat-err-line-patterns-from-compile-el compilation-error-regexp-alist-alist))
176 "Patterns for matching error/warning lines. Each pattern has the form
177 \(REGEXP FILE-IDX LINE-IDX COL-IDX ERR-TEXT-IDX).
178 Use `flymake-proc-reformat-err-line-patterns-from-compile-el' to add patterns
179 from compile.el")
181 (define-obsolete-variable-alias 'flymake-warning-re 'flymake-proc-diagnostic-type-pred "26.1")
182 (defvar flymake-proc-diagnostic-type-pred
183 'flymake-proc-default-guess
184 "Predicate matching against diagnostic text to detect its type.
185 Takes a single argument, the diagnostic's text and should return
186 a value suitable for indexing
187 `flymake-diagnostic-types-alist' (which see). If the returned
188 value is nil, a type of `:error' is assumed. For some backward
189 compatibility, if a non-nil value is returned that doesn't
190 index that alist, a type of `:warning' is assumed.
192 Instead of a function, it can also be a string, a regular
193 expression. A match indicates `:warning' type, otherwise
194 `:error'")
196 (defun flymake-proc-default-guess (text)
197 "Guess if TEXT means a warning, a note or an error."
198 (cond ((string-match "^[wW]arning" text)
199 :warning)
200 ((string-match "^[nN]ote" text)
201 :note)
203 :error)))
205 (defun flymake-proc--get-file-name-mode-and-masks (file-name)
206 "Return the corresponding entry from `flymake-proc-allowed-file-name-masks'."
207 (unless (stringp file-name)
208 (error "Invalid file-name"))
209 (let ((fnm flymake-proc-allowed-file-name-masks)
210 (mode-and-masks nil))
211 (while (and (not mode-and-masks) fnm)
212 (if (string-match (car (car fnm)) file-name)
213 (setq mode-and-masks (cdr (car fnm))))
214 (setq fnm (cdr fnm)))
215 (flymake-log 3 "file %s, init=%s" file-name (car mode-and-masks))
216 mode-and-masks))
218 (defun flymake-proc--get-init-function (file-name)
219 "Return init function to be used for the file."
220 (let* ((init-f (nth 0 (flymake-proc--get-file-name-mode-and-masks file-name))))
221 ;;(flymake-log 0 "calling %s" init-f)
222 ;;(funcall init-f (current-buffer))
223 init-f))
225 (defun flymake-proc--get-cleanup-function (file-name)
226 "Return cleanup function to be used for the file."
227 (or (nth 1 (flymake-proc--get-file-name-mode-and-masks file-name))
228 'flymake-proc-simple-cleanup))
230 (defun flymake-proc--get-real-file-name-function (file-name)
231 (or (nth 2 (flymake-proc--get-file-name-mode-and-masks file-name))
232 'flymake-proc-get-real-file-name))
234 (defvar flymake-proc--find-buildfile-cache (make-hash-table :test #'equal))
236 (defun flymake-proc--get-buildfile-from-cache (dir-name)
237 "Look up DIR-NAME in cache and return its associated value.
238 If DIR-NAME is not found, return nil."
239 (gethash dir-name flymake-proc--find-buildfile-cache))
241 (defun flymake-proc--add-buildfile-to-cache (dir-name buildfile)
242 "Associate DIR-NAME with BUILDFILE in the buildfile cache."
243 (puthash dir-name buildfile flymake-proc--find-buildfile-cache))
245 (defun flymake-proc--clear-buildfile-cache ()
246 "Clear the buildfile cache."
247 (clrhash flymake-proc--find-buildfile-cache))
249 (defun flymake-proc--find-buildfile (buildfile-name source-dir-name)
250 "Find buildfile starting from current directory.
251 Buildfile includes Makefile, build.xml etc.
252 Return its file name if found, or nil if not found."
253 (or (flymake-proc--get-buildfile-from-cache source-dir-name)
254 (let* ((file (locate-dominating-file source-dir-name buildfile-name)))
255 (if file
256 (progn
257 (flymake-log 3 "found buildfile at %s" file)
258 (flymake-proc--add-buildfile-to-cache source-dir-name file)
259 file)
260 (progn
261 (flymake-log 3 "buildfile for %s not found" source-dir-name)
262 nil)))))
264 (defun flymake-proc--fix-file-name (name)
265 "Replace all occurrences of `\\' with `/'."
266 (when name
267 (setq name (expand-file-name name))
268 (setq name (abbreviate-file-name name))
269 (setq name (directory-file-name name))
270 name))
272 (defun flymake-proc--same-files (file-name-one file-name-two)
273 "Check if FILE-NAME-ONE and FILE-NAME-TWO point to same file.
274 Return t if so, nil if not."
275 (equal (flymake-proc--fix-file-name file-name-one)
276 (flymake-proc--fix-file-name file-name-two)))
278 ;; This is bound dynamically to pass a parameter to a sort predicate below
279 (defvar flymake-proc--included-file-name)
281 (defun flymake-proc--find-possible-master-files (file-name master-file-dirs masks)
282 "Find (by name and location) all possible master files.
283 Name is specified by FILE-NAME and location is specified by
284 MASTER-FILE-DIRS. Master files include .cpp and .c for .h.
285 Files are searched for starting from the .h directory and max
286 max-level parent dirs. File contents are not checked."
287 (let* ((dirs master-file-dirs)
288 (files nil)
289 (done nil))
291 (while (and (not done) dirs)
292 (let* ((dir (expand-file-name (car dirs) (file-name-directory file-name)))
293 (masks masks))
294 (while (and (file-exists-p dir) (not done) masks)
295 (let* ((mask (car masks))
296 (dir-files (directory-files dir t mask)))
298 (flymake-log 3 "dir %s, %d file(s) for mask %s"
299 dir (length dir-files) mask)
300 (while (and (not done) dir-files)
301 (when (not (file-directory-p (car dir-files)))
302 (setq files (cons (car dir-files) files))
303 (when (>= (length files) flymake-proc-master-file-count-limit)
304 (flymake-log 3 "master file count limit (%d) reached" flymake-proc-master-file-count-limit)
305 (setq done t)))
306 (setq dir-files (cdr dir-files))))
307 (setq masks (cdr masks))))
308 (setq dirs (cdr dirs)))
309 (when files
310 (let ((flymake-proc--included-file-name (file-name-nondirectory file-name)))
311 (setq files (sort files 'flymake-proc--master-file-compare))))
312 (flymake-log 3 "found %d possible master file(s)" (length files))
313 files))
315 (defun flymake-proc--master-file-compare (file-one file-two)
316 "Compare two files specified by FILE-ONE and FILE-TWO.
317 This function is used in sort to move most possible file names
318 to the beginning of the list (File.h -> File.cpp moved to top)."
319 (and (equal (file-name-sans-extension flymake-proc--included-file-name)
320 (file-name-base file-one))
321 (not (equal file-one file-two))))
323 (defvar flymake-proc-check-file-limit 8192
324 "Maximum number of chars to look at when checking possible master file.
325 Nil means search the entire file.")
327 (defun flymake-proc--check-patch-master-file-buffer
328 (master-file-temp-buffer
329 master-file-name patched-master-file-name
330 source-file-name patched-source-file-name
331 include-dirs regexp)
332 "Check if MASTER-FILE-NAME is a master file for SOURCE-FILE-NAME.
333 If yes, patch a copy of MASTER-FILE-NAME to include PATCHED-SOURCE-FILE-NAME
334 instead of SOURCE-FILE-NAME.
336 For example, foo.cpp is a master file if it includes foo.h.
338 When a buffer for MASTER-FILE-NAME exists, use it as a source
339 instead of reading master file from disk."
340 (let* ((source-file-nondir (file-name-nondirectory source-file-name))
341 (source-file-extension (file-name-extension source-file-nondir))
342 (source-file-nonext (file-name-sans-extension source-file-nondir))
343 (found nil)
344 (inc-name nil)
345 (search-limit flymake-proc-check-file-limit))
346 (setq regexp
347 (format regexp ; "[ \t]*#[ \t]*include[ \t]*\"\\(.*%s\\)\""
348 ;; Hack for tex files, where \include often excludes .tex.
349 ;; Maybe this is safe generally.
350 (if (and (> (length source-file-extension) 1)
351 (string-equal source-file-extension "tex"))
352 (format "%s\\(?:\\.%s\\)?"
353 (regexp-quote source-file-nonext)
354 (regexp-quote source-file-extension))
355 (regexp-quote source-file-nondir))))
356 (unwind-protect
357 (with-current-buffer master-file-temp-buffer
358 (if (or (not search-limit)
359 (> search-limit (point-max)))
360 (setq search-limit (point-max)))
361 (flymake-log 3 "checking %s against regexp %s"
362 master-file-name regexp)
363 (goto-char (point-min))
364 (while (and (< (point) search-limit)
365 (re-search-forward regexp search-limit t))
366 (let ((match-beg (match-beginning 1))
367 (match-end (match-end 1)))
369 (flymake-log 3 "found possible match for %s" source-file-nondir)
370 (setq inc-name (match-string 1))
371 (and (> (length source-file-extension) 1)
372 (string-equal source-file-extension "tex")
373 (not (string-match (format "\\.%s\\'" source-file-extension)
374 inc-name))
375 (setq inc-name (concat inc-name "." source-file-extension)))
376 (when (eq t (compare-strings
377 source-file-nondir nil nil
378 inc-name (- (length inc-name)
379 (length source-file-nondir)) nil))
380 (flymake-log 3 "inc-name=%s" inc-name)
381 (when (flymake-proc--check-include source-file-name inc-name
382 include-dirs)
383 (setq found t)
384 ;; replace-match is not used here as it fails in
385 ;; XEmacs with 'last match not a buffer' error as
386 ;; check-includes calls replace-in-string
387 (flymake-proc--replace-region
388 match-beg match-end
389 (file-name-nondirectory patched-source-file-name))))
390 (forward-line 1)))
391 (when found
392 (flymake-proc--save-buffer-in-file patched-master-file-name)))
393 ;;+(flymake-log 3 "killing buffer %s"
394 ;; (buffer-name master-file-temp-buffer))
395 (kill-buffer master-file-temp-buffer))
396 ;;+(flymake-log 3 "check-patch master file %s: %s" master-file-name found)
397 (when found
398 (flymake-log 2 "found master file %s" master-file-name))
399 found))
401 ;;; XXX: remove
402 (defun flymake-proc--replace-region (beg end rep)
403 "Replace text in BUFFER in region (BEG END) with REP."
404 (save-excursion
405 (goto-char end)
406 ;; Insert before deleting, so as to better preserve markers's positions.
407 (insert rep)
408 (delete-region beg end)))
410 (defun flymake-proc--read-file-to-temp-buffer (file-name)
411 "Insert contents of FILE-NAME into newly created temp buffer."
412 (let* ((temp-buffer (get-buffer-create (generate-new-buffer-name (concat "flymake:" (file-name-nondirectory file-name))))))
413 (with-current-buffer temp-buffer
414 (insert-file-contents file-name))
415 temp-buffer))
417 (defun flymake-proc--copy-buffer-to-temp-buffer (buffer)
418 "Copy contents of BUFFER into newly created temp buffer."
419 (with-current-buffer
420 (get-buffer-create (generate-new-buffer-name
421 (concat "flymake:" (buffer-name buffer))))
422 (insert-buffer-substring buffer)
423 (current-buffer)))
425 (defun flymake-proc--check-include (source-file-name inc-name include-dirs)
426 "Check if SOURCE-FILE-NAME can be found in include path.
427 Return t if it can be found via include path using INC-NAME."
428 (if (file-name-absolute-p inc-name)
429 (flymake-proc--same-files source-file-name inc-name)
430 (while (and include-dirs
431 (not (flymake-proc--same-files
432 source-file-name
433 (concat (file-name-directory source-file-name)
434 "/" (car include-dirs)
435 "/" inc-name))))
436 (setq include-dirs (cdr include-dirs)))
437 include-dirs))
439 (defun flymake-proc--find-buffer-for-file (file-name)
440 "Check if there exists a buffer visiting FILE-NAME.
441 Return t if so, nil if not."
442 (let ((buffer-name (get-file-buffer file-name)))
443 (if buffer-name
444 (get-buffer buffer-name))))
446 (defun flymake-proc--create-master-file (source-file-name patched-source-file-name get-incl-dirs-f create-temp-f masks include-regexp)
447 "Save SOURCE-FILE-NAME with a different name.
448 Find master file, patch and save it."
449 (let* ((possible-master-files (flymake-proc--find-possible-master-files source-file-name flymake-proc-master-file-dirs masks))
450 (master-file-count (length possible-master-files))
451 (idx 0)
452 (temp-buffer nil)
453 (master-file-name nil)
454 (patched-master-file-name nil)
455 (found nil))
457 (while (and (not found) (< idx master-file-count))
458 (setq master-file-name (nth idx possible-master-files))
459 (setq patched-master-file-name (funcall create-temp-f master-file-name "flymake_master"))
460 (if (flymake-proc--find-buffer-for-file master-file-name)
461 (setq temp-buffer (flymake-proc--copy-buffer-to-temp-buffer (flymake-proc--find-buffer-for-file master-file-name)))
462 (setq temp-buffer (flymake-proc--read-file-to-temp-buffer master-file-name)))
463 (setq found
464 (flymake-proc--check-patch-master-file-buffer
465 temp-buffer
466 master-file-name
467 patched-master-file-name
468 source-file-name
469 patched-source-file-name
470 (funcall get-incl-dirs-f (file-name-directory master-file-name))
471 include-regexp))
472 (setq idx (1+ idx)))
473 (if found
474 (list master-file-name patched-master-file-name)
475 (progn
476 (flymake-log 3 "none of %d master file(s) checked includes %s" master-file-count
477 (file-name-nondirectory source-file-name))
478 nil))))
480 (defun flymake-proc--save-buffer-in-file (file-name)
481 "Save the entire buffer contents into file FILE-NAME.
482 Create parent directories as needed."
483 (make-directory (file-name-directory file-name) 1)
484 (write-region nil nil file-name nil 566)
485 (flymake-log 3 "saved buffer %s in file %s" (buffer-name) file-name))
487 (defun flymake-proc--diagnostics-for-pattern (proc pattern)
488 (cl-flet ((guess-type
489 (pred message)
490 (cond ((null message)
491 :error)
492 ((stringp pred)
493 (if (string-match pred message)
494 :warning
495 :error))
496 ((functionp pred)
497 (let ((probe (funcall pred message)))
498 (cond ((assoc-default probe
499 flymake-diagnostic-types-alist)
500 probe)
501 (probe
502 :warning)
504 :error)))))))
505 (condition-case-unless-debug err
506 (cl-loop
507 with (regexp file-idx line-idx col-idx message-idx) = pattern
508 while (and
509 (search-forward-regexp regexp nil t)
510 ;; If the preceding search spanned more than one line,
511 ;; move to the start of the line we ended up in. This
512 ;; preserves the usefulness of the patterns in
513 ;; `flymake-proc-err-line-patterns', which were
514 ;; written primarily for flymake's original
515 ;; line-by-line parsing and thus never spanned
516 ;; multiple lines.
517 (if (/= (line-number-at-pos (match-beginning 0))
518 (line-number-at-pos))
519 (goto-char (line-beginning-position))
521 for fname = (and file-idx (match-string file-idx))
522 for message = (and message-idx (match-string message-idx))
523 for line-string = (and line-idx (match-string line-idx))
524 for line-number = (or (and line-string
525 (string-to-number line-string))
527 for col-string = (and col-idx (match-string col-idx))
528 for col-number = (and col-string
529 (string-to-number col-string))
530 for full-file = (with-current-buffer (process-buffer proc)
531 (and fname
532 (funcall
533 (flymake-proc--get-real-file-name-function
534 fname)
535 fname)))
536 for buffer = (and full-file
537 (find-buffer-visiting full-file))
538 if (and (eq buffer (process-buffer proc)) message)
539 collect (pcase-let ((`(,beg . ,end)
540 (flymake-diag-region buffer line-number col-number)))
541 (flymake-make-diagnostic
542 buffer beg end
543 (with-current-buffer buffer
544 (guess-type flymake-proc-diagnostic-type-pred message))
545 message))
546 else
547 do (flymake-log 2 "Reference to file %s is out of scope" fname))
548 (error
549 (flymake-log 1 "Error parsing process output for pattern %s: %s"
550 pattern err)
551 nil))))
553 (defun flymake-proc--process-filter (proc string)
554 "Parse STRING and collect diagnostics info."
555 (flymake-log 3 "received %d byte(s) of output from process %d"
556 (length string) (process-id proc))
557 (let ((output-buffer (process-get proc 'flymake-proc--output-buffer)))
558 (when (and (buffer-live-p (process-buffer proc))
559 output-buffer)
560 (with-current-buffer output-buffer
561 (let ((moving (= (point) (process-mark proc)))
562 (inhibit-read-only t)
563 (unprocessed-mark
564 (or (process-get proc 'flymake-proc--unprocessed-mark)
565 (set-marker (make-marker) (point-min)))))
566 (save-excursion
567 ;; Insert the text, advancing the process marker.
568 (goto-char (process-mark proc))
569 (insert string)
570 (set-marker (process-mark proc) (point)))
571 (if moving (goto-char (process-mark proc)))
573 ;; check for new diagnostics
575 (save-excursion
576 (goto-char unprocessed-mark)
577 (dolist (pattern flymake-proc-err-line-patterns)
578 (let ((new (flymake-proc--diagnostics-for-pattern proc pattern)))
579 (process-put
580 proc
581 'flymake-proc--collected-diagnostics
582 (append new
583 (process-get proc
584 'flymake-proc--collected-diagnostics)))))
585 (process-put proc 'flymake-proc--unprocessed-mark
586 (point-marker))))))))
588 (defun flymake-proc--process-sentinel (proc _event)
589 "Sentinel for syntax check buffers."
590 (let (debug
591 (pid (process-id proc))
592 (source-buffer (process-buffer proc)))
593 (unwind-protect
594 (when (buffer-live-p source-buffer)
595 (with-current-buffer source-buffer
596 (cond ((process-get proc 'flymake-proc--obsolete)
597 (flymake-log 3 "proc %s considered obsolete"
598 pid))
599 ((process-get proc 'flymake-proc--interrupted)
600 (flymake-log 3 "proc %s interrupted by user"
601 pid))
602 ((not (process-live-p proc))
603 (let* ((exit-status (process-exit-status proc))
604 (command (process-command proc))
605 (diagnostics (process-get
606 proc
607 'flymake-proc--collected-diagnostics)))
608 (flymake-log 2 "process %d exited with code %d"
609 pid exit-status)
610 (cond
611 ((equal 0 exit-status)
612 (funcall flymake-proc--report-fn diagnostics
613 :explanation (format "a gift from %s" (process-id proc))
615 (diagnostics
616 ;; non-zero exit but some diagnostics is quite
617 ;; normal...
618 (funcall flymake-proc--report-fn diagnostics
619 :explanation (format "a gift from %s" (process-id proc))))
620 ((null diagnostics)
621 ;; ...but no diagnostics is strange, so panic.
622 (setq debug debug-on-error)
623 (flymake-proc--panic
624 :configuration-error
625 (format "Command %s errored, but no diagnostics"
626 command)))))))))
627 (let ((output-buffer (process-get proc 'flymake-proc--output-buffer)))
628 (cond (debug
629 (flymake-log 3 "Output buffer %s kept alive for debugging"
630 output-buffer))
632 (when (buffer-live-p source-buffer)
633 (with-current-buffer source-buffer
634 (let ((cleanup-f (flymake-proc--get-cleanup-function
635 (buffer-file-name))))
636 (flymake-log 3 "cleaning up using %s" cleanup-f)
637 (funcall cleanup-f))))
638 (kill-buffer output-buffer)))))))
640 (defun flymake-proc--panic (problem explanation)
641 "Tell Flymake UI about a fatal PROBLEM with this backend.
642 May only be called in a dynamic environment where
643 `flymake-proc--report-fn' is bound."
644 (flymake-log 1 "%s: %s" problem explanation)
645 (if (and (boundp 'flymake-proc--report-fn)
646 flymake-proc--report-fn)
647 (funcall flymake-proc--report-fn :panic
648 :explanation (format "%s: %s" problem explanation))
649 (flymake-error "Trouble telling flymake-ui about problem %s(%s)"
650 problem explanation)))
652 (require 'compile)
654 (defun flymake-proc-get-project-include-dirs-imp (basedir)
655 "Include dirs for the project current file belongs to."
656 (if (flymake-proc--get-project-include-dirs-from-cache basedir)
657 (progn
658 (flymake-proc--get-project-include-dirs-from-cache basedir))
659 ;;else
660 (let* ((command-line (concat "make -C "
661 (shell-quote-argument basedir)
662 " DUMPVARS=INCLUDE_DIRS dumpvars"))
663 (output (shell-command-to-string command-line))
664 (lines (split-string output "\n" t))
665 (count (length lines))
666 (idx 0)
667 (inc-dirs nil))
668 (while (and (< idx count) (not (string-match "^INCLUDE_DIRS=.*" (nth idx lines))))
669 (setq idx (1+ idx)))
670 (when (< idx count)
671 (let* ((inc-lines (split-string (nth idx lines) " *-I" t))
672 (inc-count (length inc-lines)))
673 (while (> inc-count 0)
674 (when (not (string-match "^INCLUDE_DIRS=.*" (nth (1- inc-count) inc-lines)))
675 (push (replace-regexp-in-string "\"" "" (nth (1- inc-count) inc-lines)) inc-dirs))
676 (setq inc-count (1- inc-count)))))
677 (flymake-proc--add-project-include-dirs-to-cache basedir inc-dirs)
678 inc-dirs)))
680 (defvar flymake-proc-get-project-include-dirs-function #'flymake-proc-get-project-include-dirs-imp
681 "Function used to get project include dirs, one parameter: basedir name.")
683 (defun flymake-proc--get-project-include-dirs (basedir)
684 (funcall flymake-proc-get-project-include-dirs-function basedir))
686 (defun flymake-proc--get-system-include-dirs ()
687 "System include dirs - from the `INCLUDE' env setting."
688 (let* ((includes (getenv "INCLUDE")))
689 (if includes (split-string includes path-separator t) nil)))
691 (defvar flymake-proc--project-include-dirs-cache (make-hash-table :test #'equal))
693 (defun flymake-proc--get-project-include-dirs-from-cache (base-dir)
694 (gethash base-dir flymake-proc--project-include-dirs-cache))
696 (defun flymake-proc--add-project-include-dirs-to-cache (base-dir include-dirs)
697 (puthash base-dir include-dirs flymake-proc--project-include-dirs-cache))
699 (defun flymake-proc--clear-project-include-dirs-cache ()
700 (clrhash flymake-proc--project-include-dirs-cache))
702 (defun flymake-proc-get-include-dirs (base-dir)
703 "Get dirs to use when resolving local file names."
704 (let* ((include-dirs (append '(".") (flymake-proc--get-project-include-dirs base-dir) (flymake-proc--get-system-include-dirs))))
705 include-dirs))
707 ;; (defun flymake-proc--restore-formatting ()
708 ;; "Remove any formatting made by flymake."
709 ;; )
711 ;; (defun flymake-proc--get-program-dir (buffer)
712 ;; "Get dir to start program in."
713 ;; (unless (bufferp buffer)
714 ;; (error "Invalid buffer"))
715 ;; (with-current-buffer buffer
716 ;; default-directory))
718 (defun flymake-proc--safe-delete-file (file-name)
719 (when (and file-name (file-exists-p file-name))
720 (delete-file file-name)
721 (flymake-log 2 "deleted file %s" file-name)))
723 (defun flymake-proc--safe-delete-directory (dir-name)
724 (condition-case-unless-debug nil
725 (progn
726 (delete-directory dir-name)
727 (flymake-log 2 "deleted dir %s" dir-name))
728 (error
729 (flymake-log 1 "Failed to delete dir %s, error ignored" dir-name))))
732 (defun flymake-proc-legacy-flymake (report-fn &rest args)
733 "Flymake backend based on the original Flymake implementation.
734 This function is suitable for inclusion in
735 `flymake-diagnostic-functions'. For backward compatibility, it
736 can also be executed interactively independently of
737 `flymake-mode'."
738 ;; Interactively, behave as if flymake had invoked us through its
739 ;; `flymake-diagnostic-functions' with a suitable ID so flymake can
740 ;; clean up consistently
741 (interactive (list
742 (lambda (diags &rest args)
743 (apply (flymake-make-report-fn 'flymake-proc-legacy-flymake)
744 diags
745 (append args '(:force t))))
746 :interactive t))
747 (let ((interactive (plist-get args :interactive))
748 (proc flymake-proc--current-process)
749 (flymake-proc--report-fn report-fn))
750 (when (processp proc)
751 (process-put proc 'flymake-proc--obsolete t)
752 (flymake-log 3 "marking %s obsolete" (process-id proc))
753 (when (process-live-p proc)
754 (when interactive
755 (user-error
756 "There's already a Flymake process running in this buffer")
757 (kill-process proc))))
758 (when
759 ;; This particular situation make us not want to error right
760 ;; away (and disable ourselves), in case the situation changes
761 ;; in the near future.
762 (and (or (not flymake-proc-compilation-prevents-syntax-check)
763 (not (flymake-proc--compilation-is-running))))
764 (let ((init-f
765 (and
766 buffer-file-name
767 ;; Since we write temp files in current dir, there's no point
768 ;; trying if the directory is read-only (bug#8954).
769 (file-writable-p (file-name-directory buffer-file-name))
770 (flymake-proc--get-init-function buffer-file-name))))
771 (unless init-f (error "Can't find a suitable init function"))
772 (flymake-proc--clear-buildfile-cache)
773 (flymake-proc--clear-project-include-dirs-cache)
775 (let* ((cleanup-f (flymake-proc--get-cleanup-function buffer-file-name))
776 (cmd-and-args (funcall init-f))
777 (cmd (nth 0 cmd-and-args))
778 (args (nth 1 cmd-and-args))
779 (dir (nth 2 cmd-and-args))
780 (success nil))
781 (unwind-protect
782 (cond
783 ((not cmd-and-args)
784 (flymake-log 1 "init function %s for %s failed, cleaning up"
785 init-f buffer-file-name))
787 (setq proc
788 (let ((default-directory (or dir default-directory)))
789 (when dir
790 (flymake-log 3 "starting process on dir %s" dir))
791 (make-process
792 :name "flymake-proc"
793 :buffer (current-buffer)
794 :command (cons cmd args)
795 :noquery t
796 :filter
797 (lambda (proc string)
798 (let ((flymake-proc--report-fn report-fn))
799 (flymake-proc--process-filter proc string)))
800 :sentinel
801 (lambda (proc event)
802 (let ((flymake-proc--report-fn report-fn))
803 (flymake-proc--process-sentinel proc event))))))
804 (process-put proc 'flymake-proc--output-buffer
805 (generate-new-buffer
806 (format " *flymake output for %s*" (current-buffer))))
807 (setq flymake-proc--current-process proc)
808 (flymake-log 2 "started process %d, command=%s, dir=%s"
809 (process-id proc) (process-command proc)
810 default-directory)
811 (setq success t)))
812 (unless success
813 (funcall cleanup-f))))))))
815 (define-obsolete-function-alias 'flymake-start-syntax-check
816 'flymake-proc-legacy-flymake "26.1")
818 (defun flymake-proc-stop-all-syntax-checks (&optional reason)
819 "Kill all syntax check processes."
820 (interactive (list "Interrupted by user"))
821 (dolist (buf (buffer-list))
822 (with-current-buffer buf
823 (let (p flymake-proc--current-process)
824 (when (process-live-p p)
825 (kill-process p)
826 (process-put p 'flymake-proc--interrupted reason)
827 (flymake-log 2 "killed process %d" (process-id p)))))))
829 (defun flymake-proc--compilation-is-running ()
830 (and (boundp 'compilation-in-progress)
831 compilation-in-progress))
833 (defun flymake-proc-compile ()
834 "Kill all Flymake syntax checks, start compilation."
835 (interactive)
836 (flymake-proc-stop-all-syntax-checks "Stopping for proper compilation")
837 (call-interactively 'compile))
839 ;;;; general init-cleanup and helper routines
840 (defun flymake-proc-create-temp-inplace (file-name prefix)
841 (unless (stringp file-name)
842 (error "Invalid file-name"))
843 (or prefix
844 (setq prefix "flymake"))
845 (let* ((ext (file-name-extension file-name))
846 (temp-name (file-truename
847 (concat (file-name-sans-extension file-name)
848 "_" prefix
849 (and ext (concat "." ext))))))
850 (flymake-log 3 "create-temp-inplace: file=%s temp=%s" file-name temp-name)
851 temp-name))
853 (defun flymake-proc-create-temp-with-folder-structure (file-name _prefix)
854 (unless (stringp file-name)
855 (error "Invalid file-name"))
857 (let* ((dir (file-name-directory file-name))
858 ;; Not sure what this slash-pos is all about, but I guess it's just
859 ;; trying to remove the leading / of absolute file names.
860 (slash-pos (string-match "/" dir))
861 (temp-dir (expand-file-name (substring dir (1+ slash-pos))
862 temporary-file-directory)))
864 (file-truename (expand-file-name (file-name-nondirectory file-name)
865 temp-dir))))
867 (defun flymake-proc--delete-temp-directory (dir-name)
868 "Attempt to delete temp dir created by `flymake-proc-create-temp-with-folder-structure', do not fail on error."
869 (let* ((temp-dir temporary-file-directory)
870 (suffix (substring dir-name (1+ (length temp-dir)))))
872 (while (> (length suffix) 0)
873 (setq suffix (directory-file-name suffix))
874 ;;+(flymake-log 0 "suffix=%s" suffix)
875 (flymake-proc--safe-delete-directory
876 (file-truename (expand-file-name suffix temp-dir)))
877 (setq suffix (file-name-directory suffix)))))
879 (defvar-local flymake-proc--temp-source-file-name nil)
880 (defvar-local flymake-proc--master-file-name nil)
881 (defvar-local flymake-proc--temp-master-file-name nil)
882 (defvar-local flymake-proc--base-dir nil)
884 (defun flymake-proc-init-create-temp-buffer-copy (create-temp-f)
885 "Make a temporary copy of the current buffer, save its name in buffer data and return the name."
886 (let* ((source-file-name buffer-file-name)
887 (temp-source-file-name (funcall create-temp-f source-file-name "flymake")))
889 (flymake-proc--save-buffer-in-file temp-source-file-name)
890 (setq flymake-proc--temp-source-file-name temp-source-file-name)
891 temp-source-file-name))
893 (defun flymake-proc-simple-cleanup ()
894 "Do cleanup after `flymake-proc-init-create-temp-buffer-copy'.
895 Delete temp file."
896 (flymake-proc--safe-delete-file flymake-proc--temp-source-file-name))
898 (defun flymake-proc-get-real-file-name (file-name-from-err-msg)
899 "Translate file name from error message to \"real\" file name.
900 Return full-name. Names are real, not patched."
901 (let* ((real-name nil)
902 (source-file-name buffer-file-name)
903 (master-file-name flymake-proc--master-file-name)
904 (temp-source-file-name flymake-proc--temp-source-file-name)
905 (temp-master-file-name flymake-proc--temp-master-file-name)
906 (base-dirs
907 (list flymake-proc--base-dir
908 (file-name-directory source-file-name)
909 (if master-file-name (file-name-directory master-file-name))))
910 (files (list (list source-file-name source-file-name)
911 (list temp-source-file-name source-file-name)
912 (list master-file-name master-file-name)
913 (list temp-master-file-name master-file-name))))
915 (when (equal 0 (length file-name-from-err-msg))
916 (setq file-name-from-err-msg source-file-name))
918 (setq real-name (flymake-proc--get-full-patched-file-name file-name-from-err-msg base-dirs files))
919 ;; if real-name is nil, than file name from err msg is none of the files we've patched
920 (if (not real-name)
921 (setq real-name (flymake-proc--get-full-nonpatched-file-name file-name-from-err-msg base-dirs)))
922 (if (not real-name)
923 (setq real-name file-name-from-err-msg))
924 (setq real-name (flymake-proc--fix-file-name real-name))
925 (flymake-log 3 "get-real-file-name: file-name=%s real-name=%s" file-name-from-err-msg real-name)
926 real-name))
928 (defun flymake-proc--get-full-patched-file-name (file-name-from-err-msg base-dirs files)
929 (let* ((base-dirs-count (length base-dirs))
930 (file-count (length files))
931 (real-name nil))
933 (while (and (not real-name) (> base-dirs-count 0))
934 (setq file-count (length files))
935 (while (and (not real-name) (> file-count 0))
936 (let* ((this-dir (nth (1- base-dirs-count) base-dirs))
937 (this-file (nth 0 (nth (1- file-count) files)))
938 (this-real-name (nth 1 (nth (1- file-count) files))))
939 ;;+(flymake-log 0 "this-dir=%s this-file=%s this-real=%s msg-file=%s" this-dir this-file this-real-name file-name-from-err-msg)
940 (when (and this-dir this-file (flymake-proc--same-files
941 (expand-file-name file-name-from-err-msg this-dir)
942 this-file))
943 (setq real-name this-real-name)))
944 (setq file-count (1- file-count)))
945 (setq base-dirs-count (1- base-dirs-count)))
946 real-name))
948 (defun flymake-proc--get-full-nonpatched-file-name (file-name-from-err-msg base-dirs)
949 (let* ((real-name nil))
950 (if (file-name-absolute-p file-name-from-err-msg)
951 (setq real-name file-name-from-err-msg)
952 (let* ((base-dirs-count (length base-dirs)))
953 (while (and (not real-name) (> base-dirs-count 0))
954 (let* ((full-name (expand-file-name file-name-from-err-msg
955 (nth (1- base-dirs-count) base-dirs))))
956 (if (file-exists-p full-name)
957 (setq real-name full-name))
958 (setq base-dirs-count (1- base-dirs-count))))))
959 real-name))
961 (defun flymake-proc--init-find-buildfile-dir (source-file-name buildfile-name)
962 "Find buildfile, store its dir in buffer data and return its dir, if found."
963 (let* ((buildfile-dir
964 (flymake-proc--find-buildfile buildfile-name
965 (file-name-directory source-file-name))))
966 (if buildfile-dir
967 (setq flymake-proc--base-dir buildfile-dir)
968 (flymake-proc--panic
969 "NOMK" (format "No buildfile (%s) found for %s"
970 buildfile-name source-file-name)))))
972 (defun flymake-proc--init-create-temp-source-and-master-buffer-copy (get-incl-dirs-f create-temp-f master-file-masks include-regexp)
973 "Find master file (or buffer), create its copy along with a copy of the source file."
974 (let* ((source-file-name buffer-file-name)
975 (temp-source-file-name (flymake-proc-init-create-temp-buffer-copy create-temp-f))
976 (master-and-temp-master (flymake-proc--create-master-file
977 source-file-name temp-source-file-name
978 get-incl-dirs-f create-temp-f
979 master-file-masks include-regexp)))
981 (if (not master-and-temp-master)
982 (progn
983 (flymake-proc--panic
984 "NOMASTER"
985 (format-message "cannot find master file for %s"
986 source-file-name))
987 nil)
988 (setq flymake-proc--master-file-name (nth 0 master-and-temp-master))
989 (setq flymake-proc--temp-master-file-name (nth 1 master-and-temp-master)))))
991 (defun flymake-proc-master-cleanup ()
992 (flymake-proc-simple-cleanup)
993 (flymake-proc--safe-delete-file flymake-proc--temp-master-file-name))
995 ;;;; make-specific init-cleanup routines
996 (defun flymake-proc--get-syntax-check-program-args (source-file-name base-dir use-relative-base-dir use-relative-source get-cmd-line-f)
997 "Create a command line for syntax check using GET-CMD-LINE-F."
998 (funcall get-cmd-line-f
999 (if use-relative-source
1000 (file-relative-name source-file-name base-dir)
1001 source-file-name)
1002 (if use-relative-base-dir
1003 (file-relative-name base-dir
1004 (file-name-directory source-file-name))
1005 base-dir)))
1007 (defun flymake-proc-get-make-cmdline (source base-dir)
1008 (list "make"
1009 (list "-s"
1010 "-C"
1011 base-dir
1012 (concat "CHK_SOURCES=" source)
1013 "SYNTAX_CHECK_MODE=1"
1014 "check-syntax")))
1016 (defun flymake-proc-get-ant-cmdline (source base-dir)
1017 (list "ant"
1018 (list "-buildfile"
1019 (concat base-dir "/" "build.xml")
1020 (concat "-DCHK_SOURCES=" source)
1021 "check-syntax")))
1023 (defun flymake-proc-simple-make-init-impl (create-temp-f use-relative-base-dir use-relative-source build-file-name get-cmdline-f)
1024 "Create syntax check command line for a directly checked source file.
1025 Use CREATE-TEMP-F for creating temp copy."
1026 (let* ((args nil)
1027 (source-file-name buffer-file-name)
1028 (buildfile-dir (flymake-proc--init-find-buildfile-dir source-file-name build-file-name)))
1029 (if buildfile-dir
1030 (let* ((temp-source-file-name (flymake-proc-init-create-temp-buffer-copy create-temp-f)))
1031 (setq args (flymake-proc--get-syntax-check-program-args temp-source-file-name buildfile-dir
1032 use-relative-base-dir use-relative-source
1033 get-cmdline-f))))
1034 args))
1036 (defun flymake-proc-simple-make-init ()
1037 (flymake-proc-simple-make-init-impl 'flymake-proc-create-temp-inplace t t "Makefile" 'flymake-proc-get-make-cmdline))
1039 (defun flymake-proc-master-make-init (get-incl-dirs-f master-file-masks include-regexp)
1040 "Create make command line for a source file checked via master file compilation."
1041 (let* ((make-args nil)
1042 (temp-master-file-name (flymake-proc--init-create-temp-source-and-master-buffer-copy
1043 get-incl-dirs-f 'flymake-proc-create-temp-inplace
1044 master-file-masks include-regexp)))
1045 (when temp-master-file-name
1046 (let* ((buildfile-dir (flymake-proc--init-find-buildfile-dir temp-master-file-name "Makefile")))
1047 (if buildfile-dir
1048 (setq make-args (flymake-proc--get-syntax-check-program-args
1049 temp-master-file-name buildfile-dir nil nil 'flymake-proc-get-make-cmdline)))))
1050 make-args))
1052 (defun flymake-proc--find-make-buildfile (source-dir)
1053 (flymake-proc--find-buildfile "Makefile" source-dir))
1055 ;;;; .h/make specific
1056 (defun flymake-proc-master-make-header-init ()
1057 (flymake-proc-master-make-init
1058 'flymake-proc-get-include-dirs
1059 '("\\.\\(?:c\\(?:pp\\|xx\\|\\+\\+\\)?\\|CC\\)\\'")
1060 "[ \t]*#[ \t]*include[ \t]*\"\\([[:word:]0-9/\\_.]*%s\\)\""))
1062 (defun flymake-proc-real-file-name-considering-includes (scraped)
1063 (flymake-proc-get-real-file-name
1064 (let ((case-fold-search t))
1065 (replace-regexp-in-string "^in file included from[ \t*]"
1067 scraped))))
1069 ;;;; .java/make specific
1070 (defun flymake-proc-simple-make-java-init ()
1071 (flymake-proc-simple-make-init-impl 'flymake-proc-create-temp-with-folder-structure nil nil "Makefile" 'flymake-proc-get-make-cmdline))
1073 (defun flymake-proc-simple-ant-java-init ()
1074 (flymake-proc-simple-make-init-impl 'flymake-proc-create-temp-with-folder-structure nil nil "build.xml" 'flymake-proc-get-ant-cmdline))
1076 (defun flymake-proc-simple-java-cleanup ()
1077 "Cleanup after `flymake-proc-simple-make-java-init' -- delete temp file and dirs."
1078 (flymake-proc--safe-delete-file flymake-proc--temp-source-file-name)
1079 (when flymake-proc--temp-source-file-name
1080 (flymake-proc--delete-temp-directory
1081 (file-name-directory flymake-proc--temp-source-file-name))))
1083 ;;;; perl-specific init-cleanup routines
1084 (defun flymake-proc-perl-init ()
1085 (let* ((temp-file (flymake-proc-init-create-temp-buffer-copy
1086 'flymake-proc-create-temp-inplace))
1087 (local-file (file-relative-name
1088 temp-file
1089 (file-name-directory buffer-file-name))))
1090 (list "perl" (list "-wc " local-file))))
1092 ;;;; php-specific init-cleanup routines
1093 (defun flymake-proc-php-init ()
1094 (let* ((temp-file (flymake-proc-init-create-temp-buffer-copy
1095 'flymake-proc-create-temp-inplace))
1096 (local-file (file-relative-name
1097 temp-file
1098 (file-name-directory buffer-file-name))))
1099 (list "php" (list "-f" local-file "-l"))))
1101 ;;;; tex-specific init-cleanup routines
1102 (defun flymake-proc--get-tex-args (file-name)
1103 ;;(list "latex" (list "-c-style-errors" file-name))
1104 (list "texify" (list "--pdf" "--tex-option=-c-style-errors" file-name)))
1106 (defun flymake-proc-simple-tex-init ()
1107 (flymake-proc--get-tex-args (flymake-proc-init-create-temp-buffer-copy 'flymake-proc-create-temp-inplace)))
1109 ;; Perhaps there should be a buffer-local variable flymake-master-file
1110 ;; that people can set to override this stuff. Could inherit from
1111 ;; the similar AUCTeX variable.
1112 (defun flymake-proc-master-tex-init ()
1113 (let* ((temp-master-file-name (flymake-proc--init-create-temp-source-and-master-buffer-copy
1114 'flymake-proc-get-include-dirs-dot 'flymake-proc-create-temp-inplace
1115 '("\\.tex\\'")
1116 "[ \t]*\\in\\(?:put\\|clude\\)[ \t]*{\\(.*%s\\)}")))
1117 (when temp-master-file-name
1118 (flymake-proc--get-tex-args temp-master-file-name))))
1120 (defun flymake-proc--get-include-dirs-dot (_base-dir)
1121 '("."))
1123 ;;;; xml-specific init-cleanup routines
1124 (defun flymake-proc-xml-init ()
1125 (list flymake-proc-xml-program
1126 (list "val" (flymake-proc-init-create-temp-buffer-copy
1127 'flymake-proc-create-temp-inplace))))
1130 ;;;; Hook onto flymake-ui
1131 (add-hook 'flymake-diagnostic-functions 'flymake-proc-legacy-flymake)
1134 ;;;;
1136 (define-obsolete-variable-alias 'flymake-check-file-limit
1137 'flymake-proc-check-file-limit "26.1")
1138 (define-obsolete-function-alias 'flymake-reformat-err-line-patterns-from-compile-el
1139 'flymake-proc-reformat-err-line-patterns-from-compile-el "26.1")
1140 (define-obsolete-variable-alias 'flymake-err-line-patterns
1141 'flymake-proc-err-line-patterns "26.1")
1142 (define-obsolete-function-alias 'flymake-parse-line
1143 'flymake-proc-parse-line "26.1")
1144 (define-obsolete-function-alias 'flymake-get-include-dirs
1145 'flymake-proc-get-include-dirs "26.1")
1146 (define-obsolete-function-alias 'flymake-stop-all-syntax-checks
1147 'flymake-proc-stop-all-syntax-checks "26.1")
1148 (define-obsolete-function-alias 'flymake-compile
1149 'flymake-proc-compile "26.1")
1150 (define-obsolete-function-alias 'flymake-create-temp-inplace
1151 'flymake-proc-create-temp-inplace "26.1")
1152 (define-obsolete-function-alias 'flymake-create-temp-with-folder-structure
1153 'flymake-proc-create-temp-with-folder-structure "26.1")
1154 (define-obsolete-function-alias 'flymake-init-create-temp-buffer-copy
1155 'flymake-proc-init-create-temp-buffer-copy "26.1")
1156 (define-obsolete-function-alias 'flymake-simple-cleanup
1157 'flymake-proc-simple-cleanup "26.1")
1158 (define-obsolete-function-alias 'flymake-get-real-file-name
1159 'flymake-proc-get-real-file-name "26.1")
1160 (define-obsolete-function-alias 'flymake-master-cleanup
1161 'flymake-proc-master-cleanup "26.1")
1162 (define-obsolete-function-alias 'flymake-get-make-cmdline
1163 'flymake-proc-get-make-cmdline "26.1")
1164 (define-obsolete-function-alias 'flymake-get-ant-cmdline
1165 'flymake-proc-get-ant-cmdline "26.1")
1166 (define-obsolete-function-alias 'flymake-simple-make-init-impl
1167 'flymake-proc-simple-make-init-impl "26.1")
1168 (define-obsolete-function-alias 'flymake-simple-make-init
1169 'flymake-proc-simple-make-init "26.1")
1170 (define-obsolete-function-alias 'flymake-master-make-init
1171 'flymake-proc-master-make-init "26.1")
1172 (define-obsolete-function-alias 'flymake-find-make-buildfile
1173 'flymake-proc--find-make-buildfile "26.1")
1174 (define-obsolete-function-alias 'flymake-master-make-header-init
1175 'flymake-proc-master-make-header-init "26.1")
1176 (define-obsolete-function-alias 'flymake-simple-make-java-init
1177 'flymake-proc-simple-make-java-init "26.1")
1178 (define-obsolete-function-alias 'flymake-simple-ant-java-init
1179 'flymake-proc-simple-ant-java-init "26.1")
1180 (define-obsolete-function-alias 'flymake-simple-java-cleanup
1181 'flymake-proc-simple-java-cleanup "26.1")
1182 (define-obsolete-function-alias 'flymake-perl-init
1183 'flymake-proc-perl-init "26.1")
1184 (define-obsolete-function-alias 'flymake-php-init
1185 'flymake-proc-php-init "26.1")
1186 (define-obsolete-function-alias 'flymake-simple-tex-init
1187 'flymake-proc-simple-tex-init "26.1")
1188 (define-obsolete-function-alias 'flymake-master-tex-init
1189 'flymake-proc-master-tex-init "26.1")
1190 (define-obsolete-function-alias 'flymake-xml-init
1191 'flymake-proc-xml-init "26.1")
1193 (provide 'flymake-proc)
1194 ;;; flymake-proc.el ends here