branch: elpa/flycheck
commit b254cd0a5ea0df644ce3a7b1a8c3c92d8f96c775
Author: takeokunn <[email protected]>
Commit: takeokunn <[email protected]>

    fix(org-lint): run org-lint in current Emacs process
    
    Rewrite the org-lint checker from a command-based subprocess checker
    (emacs -Q --batch) to an in-process generic checker using
    flycheck-define-generic-checker.  The subprocess approach lacks
    external packages, causing false "Unknown source block language"
    warnings for languages like nix-mode.  Running in-process gives
    org-lint access to all installed packages, eliminating the issue at
    its root.
    
    Fixes #2144
---
 CHANGES.rst       |  3 ++
 doc/languages.rst | 18 +++--------
 flycheck.el       | 92 ++++++++++++++++++++-----------------------------------
 3 files changed, 41 insertions(+), 72 deletions(-)

diff --git a/CHANGES.rst b/CHANGES.rst
index e247dc35eb..2f8730959a 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -17,6 +17,9 @@ Bugs fixed
 
 - [#2086]: Fix the name of the PyMarkdown config.
 - [#2036]: Fix ``awk-gawk`` checker passing spurious quotes to ``gawk 
--source``.
+- [#2144]: Rewrite ``org-lint`` checker to run in the current Emacs process
+  instead of a ``-Q --batch`` subprocess. This eliminates false "Unknown source
+  block language" warnings for languages from external packages.
 
 35.0 (2025-04-23)
 ======================
diff --git a/doc/languages.rst b/doc/languages.rst
index bc694df12e..17714fc13a 100644
--- a/doc/languages.rst
+++ b/doc/languages.rst
@@ -924,8 +924,8 @@ to view the docstring of the syntax checker.  Likewise, you 
may use
 
       An Org mode syntax and style checker using ``org-lint``.
 
-      The checker runs ``org-lint`` in an Emacs subprocess to detect issues 
such
-      as:
+      The checker runs ``org-lint`` in the current Emacs process to detect
+      issues such as:
 
       - Invalid links
       - Dead links
@@ -934,11 +934,9 @@ to view the docstring of the syntax checker.  Likewise, 
you may use
       - Special characters in links
       - And more...
 
-      The checker automatically inherits your Org mode configuration, including
-      ``org-directory`` and ``org-id-locations-file``. Note that ``load-path`` 
is
-      not inherited for security reasons to prevent potential code injection.
-      Org should be installed in a standard location that Emacs can find 
without
-      a custom ``load-path``.
+      Because the checker runs in the current Emacs process, it has access to
+      all installed packages and user configuration, avoiding false positives
+      for source block languages provided by external packages.
 
       The checker is enabled by default when ``org-lint`` is available (Org 
mode
       9.0 or later).
@@ -946,12 +944,6 @@ to view the docstring of the syntax checker.  Likewise, 
you may use
       See the ``org-lint`` documentation in Org mode for details about the 
checks
       performed.
 
-      .. note::
-
-         The checker does not inherit ``org-id-locations`` because this 
variable
-         can contain thousands of entries and exceed shell argument limits. The
-         ``org-id-locations-file`` is used instead.
-
 .. supported-language:: Opam
 
    .. syntax-checker:: opam
diff --git a/flycheck.el b/flycheck.el
index 135c2ad14a..37bd8acc31 100644
--- a/flycheck.el
+++ b/flycheck.el
@@ -91,6 +91,7 @@
 
 ;; Tell the byte compiler about autoloaded functions from packages
 (declare-function pkg-info-version-info "pkg-info" (package))
+(declare-function org-lint "org-lint" (&optional arg))
 
 
 ;;; Customization
@@ -8970,23 +8971,10 @@ Variables are taken from 
`flycheck-emacs-lisp-checkdoc-variables'."
      ,@(seq-map (lambda (opt) `(setq-default ,opt ',(symbol-value opt)))
                 (seq-filter #'boundp flycheck-emacs-lisp-checkdoc-variables))))
 
-(defconst flycheck-org-lint-variables
-  '(org-directory
-    org-id-locations-file)  ; File path only, not contents
-  "Variables inherited by the org-lint subprocess.
-
-Note: We do NOT include `load-path' to prevent potential code injection
-and information disclosure. Org should be installed in a standard
-location that Emacs can find without a custom load-path.
-
-We also do not include `org-id-locations' because it can contain
-thousands of entries and exceed shell argument limits (ARG_MAX).")
-
-(defun flycheck-org-lint-variables-form ()
-  "Make a sexp to pass relevant variables to an org-lint subprocess."
-  `(progn
-     ,@(seq-map (lambda (opt) `(setq-default ,opt ',(symbol-value opt)))
-                (seq-filter #'boundp flycheck-org-lint-variables))))
+(defun flycheck-org-lint-available-p ()
+  "Check if org-lint is available."
+  (and (fboundp 'org-lint)
+       (require 'org nil 'no-error)))
 
 (flycheck-define-checker emacs-lisp-checkdoc
   "An Emacs Lisp style checker using CheckDoc.
@@ -9002,61 +8990,47 @@ The checker runs `checkdoc-current-buffer'."
   :modes (emacs-lisp-mode)
   :enabled flycheck--emacs-lisp-checkdoc-enabled-p)
 
-(defconst flycheck-org-lint-form
-  (flycheck-prepare-emacs-lisp-form
-    (with-demoted-errors "Org-lint error: %S"
-      (require 'org)
-      (let ((source (car command-line-args-left))
-            (process-default-directory default-directory))
-        (with-temp-buffer
-          (insert-file-contents source 'visit)
-          (setq buffer-file-name source)
-          (setq default-directory process-default-directory)
-          (delay-mode-hooks (org-mode))
-          (setq delayed-mode-hooks nil)
-          (dolist (err (org-lint))
-            (pcase err
-              (`(,_n [,line ,_trust ,desc ,_checker])
-               (princ (format "%s:%s: %s\n" source line desc)))
-              (_
-               (princ (format "%s:1: Unexpected org-lint format: %S\n" source 
err))))))))))
-
-(defun flycheck-org-lint-available-p ()
-  "Check if org-lint is available."
-  (and (fboundp 'org-lint)
-       (require 'org nil 'no-error)))
-
 (dolist (checker '(emacs-lisp emacs-lisp-checkdoc))
   (setf (car (flycheck-checker-get checker 'command))
         flycheck-this-emacs-executable))
 
-(flycheck-define-checker org-lint
+(flycheck-define-generic-checker 'org-lint
   "An Org mode syntax checker using `org-lint'.
 
-The checker runs `org-lint' in an Emacs subprocess."
-  :command ("emacs" (eval flycheck-emacs-args)
-            "--eval" (eval (flycheck-sexp-to-string
-                            (flycheck-org-lint-variables-form)))
-            "--eval" (eval flycheck-org-lint-form)
-            "--" source)
-  :error-patterns
-  ((info line-start (file-name) ":" line ": " (message) line-end))
-  :modes (org-mode)
-  :enabled (lambda () (flycheck-org-lint-available-p))
+The checker runs `org-lint' in the current Emacs process, so it
+has access to all installed packages and user configuration."
+  :start (lambda (checker callback)
+           (condition-case err
+               (let ((errors
+                      (delq nil
+                            (mapcar
+                             (lambda (e)
+                               (pcase e
+                                 (`(,_n [,line ,_trust ,desc ,_checker])
+                                  (flycheck-error-new-at
+                                   line nil 'info desc
+                                   :checker checker))
+                                 (_
+                                  (flycheck-error-new-at
+                                   1 nil 'warning
+                                   (format "Unexpected org-lint format: %S" e)
+                                   :checker checker))))
+                             (org-lint)))))
+                 (funcall callback 'finished errors))
+             (error (funcall callback 'errored
+                             (error-message-string err)))))
+  :modes '(org-mode)
+  :enabled #'flycheck-org-lint-available-p
   :verify (lambda (_)
             (let ((org-version (when (require 'org nil 'no-error)
-                                  (org-version))))
+                                 (org-version))))
               (list (flycheck-verification-result-new
                      :label "Org-lint available"
                      :message (if (fboundp 'org-lint)
-                                 (format "yes (Org %s)" org-version)
-                               "no")
+                                  (format "yes (Org %s)" org-version)
+                                "no")
                      :face (if (fboundp 'org-lint) 'success 'warning))))))
 
-;; Set org-lint to use the current Emacs
-(setf (car (flycheck-checker-get 'org-lint 'command))
-      flycheck-this-emacs-executable)
-
 (defun flycheck-ember-template--check-for-config (&rest _ignored)
   "Check the required config file is available up the file system."
   (and buffer-file-name

Reply via email to