[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Flymake refactored

From: João Távora
Subject: Re: Flymake refactored
Date: Thu, 05 Oct 2017 11:57:32 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.0.60 (gnu/linux)

Mark Oteiza <address@hidden> writes:

> Modeled after your example and bits from flycheck[0] and syntastic[1], I
> have attached humble beginnings to a clang checker (errors only).

Looks great.

> Something is probably very broken, as using it to check Emacs C at this
> point triggers the following:
>   funcall-interactively: binding stack not balanced (serious byte compiler 
> bug)

Sounds serious indeed. I've seen this too, once or twice, no idea how to
debug it.

> I also seem to have problems using the column number (match-string 2)
> and so it is left unused.

The problem is that you are calling flymake-diag-region in the wrong
buffer. It has to be the source buffer, so in your case you need a
(with-current-buffer source ...) around it.

But that inconvenience has been fixed in the very latest code emacs-26
branch. In that version, you just pass 'source' (the c/c++ buffer) to

>              :sentinel
>              (lambda (p _ev)

One of the things you must do here is check if your process is obsolete,
i.e. if Flymake decided to launch another one in the meantime. A good
way to do this is to check if 'p' is 'eq' to the buffer-local value of

>                       for (beg . end) = (flymake-diag-region
>                                          (string-to-number
>                                          (match-string 1)))

This is the bit where you would pass 'source' to flymake-diag-region

I've built a backend very similar to yours but base on gcc (clang is
500MB and no time for that right now). Have a look, below my sig.

I've also noticed, there's a lot of repetition building up in these
examples. Later it's probably useful to invent an abstraction that hides
it away.


;;; test-gcc-backend.el --- naive gcc Flymake backend -*- lexical-binding: t; 

(defvar-local gcc--flymake-proc nil)

(defvar gcc-program "gcc")

(defun gcc-flymake (report-fn &rest _args)
  (unless (executable-find gcc-program)
    (error "Cannot find a suitable gcc"))
  (when (process-live-p gcc--flymake-proc)
    (kill-process gcc--flymake-proc))
  (let ((source (current-buffer)))
      (setq gcc--flymake-proc
             :name "gcc-flymake"
             :buffer (generate-new-buffer "*gcc-flymake*")
             :command `(,gcc-program
                        "-fsyntax-only" "-Wextra" "-Wall"
                        "-x" "c" "-")
             :noquery t :connection-type 'pipe
             (lambda (p _ev)
                   (when (eq p gcc--flymake-proc)
                     (with-current-buffer (process-buffer p)
                       (goto-char (point-min))
                        while (search-forward-regexp
                               "^<stdin>:\\([0-9]+\\):\\([0-9]+\\): \\(.*\\): 
                               nil t)
                        for msg = (match-string 4)
                        for (beg . end) = (flymake-diag-region source
(string-to-number (match-string 1))
(string-to-number (match-string 2)))
                        for type = (assoc-default (match-string 3)
                                                  '(("error" . :error)
                                                    ("note" . :note)
                                                    ("warning" . :warning))
                        collect (flymake-make-diagnostic source beg end type 
                        into diags
                        finally (funcall report-fn diags))))
                 (display-buffer (process-buffer p)) ; use this instead of the 
next one for debug
                 ;; (kill-buffer (process-buffer p))
      (process-send-region gcc--flymake-proc (point-min) (point-max))
      (process-send-eof gcc--flymake-proc))))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]