[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] master 9a0b20d: Add proper Flymake support to cc-mode.el
From: |
João Távora |
Subject: |
[Emacs-diffs] master 9a0b20d: Add proper Flymake support to cc-mode.el |
Date: |
Sun, 3 Jun 2018 20:47:13 -0400 (EDT) |
branch: master
commit 9a0b20d5b33e3e3282b597c3d0c836396071a547
Author: João Távora <address@hidden>
Commit: João Távora <address@hidden>
Add proper Flymake support to cc-mode.el
Except for the important detail that it doesn't make temporary files,
the new flymake-cc backend doesn't yet behave much differently from
the old flymake-proc-legacy-flymake, i.e. it still needs a special
`check-syntax' Makefile target to provide the compiler and compilation
flags. However, the new infrastructure created should allow less
intrusive cleverer flag guessers (yet to be written) to replace that
mechanism.
* lisp/progmodes/cc-mode.el (c-mode, c++-mode): Add to
flymake-diagnostic-functions.
* lisp/progmodes/flymake-cc.el: New file.
---
lisp/progmodes/cc-mode.el | 2 +
lisp/progmodes/flymake-cc.el | 140 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 142 insertions(+)
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 49c9171..a1411ad 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -2039,6 +2039,7 @@ Key bindings:
(c-common-init 'c-mode)
(easy-menu-add c-c-menu)
(cc-imenu-init cc-imenu-c-generic-expression)
+ (add-hook 'flymake-diagnostic-functions 'flymake-cc nil t)
(c-run-mode-hooks 'c-mode-common-hook))
(defconst c-or-c++-mode--regexp
@@ -2126,6 +2127,7 @@ Key bindings:
(c-common-init 'c++-mode)
(easy-menu-add c-c++-menu)
(cc-imenu-init cc-imenu-c++-generic-expression)
+ (add-hook 'flymake-diagnostic-functions 'flymake-cc nil t)
(c-run-mode-hooks 'c-mode-common-hook))
diff --git a/lisp/progmodes/flymake-cc.el b/lisp/progmodes/flymake-cc.el
new file mode 100644
index 0000000..ebcfd7d
--- /dev/null
+++ b/lisp/progmodes/flymake-cc.el
@@ -0,0 +1,140 @@
+;;; flymake-cc.el --- Flymake support for GNU tools for C/C++ -*-
lexical-binding: t; -*-
+
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+
+;; Author: João Távora <address@hidden>
+;; Keywords: languages, c
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Flymake support for C/C++.
+
+;;; Code:
+
+(require 'cl-lib)
+
+(defcustom flymake-cc-command 'flymake-cc-use-special-make-target
+ "Command used by the `flymake-cc' backend.
+A list of strings, or a symbol naming a function that produces one
+such list when called with no arguments in the buffer where the
+variable `flymake-mode' is active.
+
+The command should invoke a GNU-style compiler that checks the
+syntax of a (Obj)C(++) program passed to it via its standard
+input and prints the result on its standard output."
+ :type '(choice
+ (symbol :tag "Function")
+ ((repeat :) string))
+ :group 'flymake-cc)
+
+(defun flymake-cc--make-diagnostics (source)
+ "Parse GNU-compatible compilation messages in current buffer.
+Return a list of Flymake diagnostic objects for the source buffer
+SOURCE."
+ ;; TODO: if you can understand it, use `compilation-mode's regexps
+ ;; or even some of its machinery here.
+ ;;
+ ;; (set (make-local-variable 'compilation-locs)
+ ;; (make-hash-table :test 'equal :weakness 'value))
+ ;; (compilation-parse-errors (point-min) (point-max)
+ ;; 'gnu 'gcc-include)
+ ;; (while (next-single-property-change 'compilation-message)
+ ;; ...)
+ ;;
+ ;; For now, this works minimally well.
+ (cl-loop
+ while
+ (search-forward-regexp
+ "^\\(In file included from
\\)?<stdin>:\\([0-9]+\\):\\([0-9]+\\):\n?\\(.*\\): \\(.*\\)$"
+ nil t)
+ for msg = (match-string 5)
+ for (beg . end) = (flymake-diag-region
+ source
+ (string-to-number (match-string 2))
+ (string-to-number (match-string 3)))
+ for type = (if (match-string 1)
+ :error
+ (assoc-default
+ (match-string 4)
+ '(("error" . :error)
+ ("note" . :note)
+ ("warning" . :warning))
+ #'string-match))
+ collect (flymake-make-diagnostic source beg end type msg)))
+
+(defun flymake-cc-use-special-make-target ()
+ "Command for checking a file via a CHK_SOURCES Make target."
+ (unless (executable-find "make") (error "Make not found"))
+ `("make" "check-syntax" "CHK_SOURCES=-x c -"))
+
+(defvar-local flymake-cc--proc nil "Internal variable for `flymake-gcc'")
+
+;; forward declare this to shoosh compiler (instead of requiring
+;; flymake-proc)
+;;
+(defvar flymake-proc-allowed-file-name-masks)
+
+;;;###autoload
+(defun flymake-cc (report-fn &rest _args)
+ "Flymake backend for GNU-style C compilers.
+This backend uses `flymake-cc-command' (which see) to launch a
+process that is passed the current buffer's contents via stdin.
+REPORT-FN is Flymake's callback."
+ ;; HACK: XXX: Assuming this backend function is run before it in
+ ;; `flymake-diagnostic-functions', very hackingly convince the other
+ ;; backend `flymake-proc-legacy-backend', which is on by default, to
+ ;; disable itself.
+ ;;
+ (setq-local flymake-proc-allowed-file-name-masks nil)
+ (when (process-live-p flymake-cc--proc)
+ (kill-process flymake-cc--proc))
+ (let ((source (current-buffer)))
+ (save-restriction
+ (widen)
+ (setq
+ flymake-cc--proc
+ (make-process
+ :name "gcc-flymake"
+ :buffer (generate-new-buffer "*gcc-flymake*")
+ :command (if (symbolp flymake-cc-command)
+ (funcall flymake-cc-command)
+ flymake-cc-command)
+ :noquery t :connection-type 'pipe
+ :sentinel
+ (lambda (p _ev)
+ (when (eq 'exit (process-status p))
+ (unwind-protect
+ (when (with-current-buffer source (eq p flymake-cc--proc))
+ (with-current-buffer (process-buffer p)
+ (goto-char (point-min))
+ (let ((diags
+ (flymake-cc--make-diagnostics source)))
+ (if (or diags (zerop (process-exit-status p)))
+ (funcall report-fn diags)
+ ;; non-zero exit with no diags is cause
+ ;; for alarm
+ (funcall report-fn
+ :panic :explanation
+ (buffer-substring
+ (point-min) (progn (goto-char (point-min))
+ (line-end-position))))))))
+ ;; (display-buffer (process-buffer p)) ; uncomment to debug
+ (kill-buffer (process-buffer p)))))))
+ (process-send-region flymake-cc--proc (point-min) (point-max))
+ (process-send-eof flymake-cc--proc))))
+
+(provide 'flymake-cc)
+;;; flymake-cc.el ends here
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] master 9a0b20d: Add proper Flymake support to cc-mode.el,
João Távora <=