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