Add treesit-admin-generate-compatibility-report

This function can generate a HTML report on latest compatible
grammar versions for each major mode.

* admin/tree-sitter/compat-template.html: Update.
* admin/tree-sitter/treesit-admin.el:
(treesit-admin--validate-mode-lang): Change so that emacs 30 can
also run it.
(treesit-admin--find-latest-compatible-revision): Support
running checks with a different Emacs executable.
(treesit-admin--generate-compatibility-report): New function.
This commit is contained in:
Yuan Fu 2024-12-29 00:31:37 -08:00
parent 5ec170985f
commit d9cfe1fe92
No known key found for this signature in database
GPG key ID: 56E19BC57664A442
2 changed files with 85 additions and 15 deletions

View file

@ -3,21 +3,42 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Emacs tree-sitter language grammar version compatibility</title>
<title>Emacs tree-sitter grammar version compatibility report</title>
<style>
body {
width: min(90vw, 40rem);
margin-left: auto;
margin: auto;
margin-top: 2rem;
font-family: ui-serif;
}
thead {
font-weight: bold;
}
table {
margin: auto;
}
table td {
padding: 0.5rem 1rem;
}
.head {
background: lightgreen;
}
</style>
</head>
<body>
<h1>Tree-sitter grammar compatibility for Emacs ___REPLACE_EMACS_VERSION___</h1>
<p>This is an auto-generated report of the latest compatible versions of tree-sitter grammars for each major mode. A <span class="head">green background</span> on the version indicates that the major mode is compatible with the latest commit in the upstream grammar repo.</p>
<p>This report is generated on ___REPLACE_TIME___.</p>
<table>
<thead>
<tr><td>Language</td><td>Version</td></tr>
<tr>
<td>Major mode</td>
<td>Language</td>
<td>Latest compatible version</td>
</tr>
</thead>
<tbody>
REPLACE
___REPLACE_TABLE___
</tbody>
</table>
</body>

View file

@ -228,7 +228,8 @@ Return non-nil if all queries are valid, nil otherwise."
treesit-font-lock-settings)))
(all-queries-valid t))
(dolist (setting settings)
(let* ((query (treesit-font-lock-setting-query setting))
;; `treesit-font-lock-setting-query' isn't available in Emacs 30.
(let* ((query (car setting))
(language (treesit-query-language query)))
;; Validate query.
(when (and (eq lang language)
@ -253,13 +254,20 @@ Return non-nil if all queries are valid, nil otherwise."
settings)))))
(defun treesit-admin--find-latest-compatible-revision
(mode language source-alist grammar-dir)
(mode language source-alist grammar-dir &optional emacs-executable)
"Find the latest revision for LANGUAGE that's compatible with MODE.
MODE, LANGUAGE, SOURCE-ALIST, GRAMMAR-DIR are the same as in
`treesit-admin--verify-major-mode-queries'.
Return a plist (:version VERSION :head-version HEAD-VERSION).
By default, use the Emacs executable that spawned the current Emacs
session to validate grammars, but if EMACS-EXECUTABLE is non-nil, use it
instead.
Return a plist of the form
(:version VERSION :head-version HEAD-VERSION).
HEAD-VERSION is the version of the HEAD, VERSION is the latest
compatible version."
(let ((treesit-extra-load-path (list grammar-dir))
@ -268,7 +276,8 @@ compatible version."
(recipe (alist-get language source-alist))
(workdir (make-temp-file "treesit-validate-workdir" t))
(emacs-executable
(expand-file-name invocation-name invocation-directory))
(or emacs-executable
(expand-file-name invocation-name invocation-directory)))
head-version version exit-code)
(pcase-let ((`(,url ,revision ,source-dir ,cc ,c++ ,commit)
recipe))
@ -301,11 +310,12 @@ compatible version."
(list :version version :head-version head-version)))
(defun treesit-admin--last-compatible-grammar-for-modes
(modes source-alist grammar-dir)
"Generate an HTML page listing latest compatible grammar versions.
(modes source-alist grammar-dir &optional emacs-executable)
"Generate an alist listing latest compatible grammar versions.
MODES, SOURCE-ALIST, GRAMMAR-DIR are the same as
`treesit-admin--verify-major-mode-queries'.
`treesit-admin--verify-major-mode-queries'. If EMACS-EXECUTABLE is
non-nil, use it for validating queries.
Return an alist of an alist of a plist:
@ -320,14 +330,53 @@ VERSION and HEAD-VERSION in the plist are the same as in
(lambda (language)
(cons language
(treesit-admin--find-latest-compatible-revision
mode language source-alist grammar-dir)))
mode language source-alist grammar-dir
emacs-executable)))
(treesit-admin--mode-languages mode))))
modes))
(defun treesit-admin-generate-compatibility-report ()
"Generate a language compatibility report."
(defun treesit-admin--generate-compatibility-report
(modes out-file &optional emacs-executable)
"Generate a language compatibility report for MODES.
If EMACS-EXECUTABLE is non-nil, use it for validating queries. Write
the report to OUT-FILE."
(interactive)
)
(with-temp-buffer
(let ((table (treesit-admin--last-compatible-grammar-for-modes
modes
treesit-admin--builtin-language-sources
"/tmp/treesit-grammar")))
(dolist (entry table)
(let ((mode (car entry)))
(dolist (entry (cdr entry))
(let* ((lang (car entry))
(version (plist-get (cdr entry) :version))
(head-version (plist-get (cdr entry) :head-version))
(classname
(if (equal version head-version) "head" "")))
(insert (format "<tr><td>%s</td><td>%s</td><td class=\"%s\">%s</td></tr>\n"
mode lang classname version)))))))
(let ((time (current-time-string nil t))
(table-text (buffer-string))
(emacs-version
(if emacs-executable
(with-temp-buffer
(call-process emacs-executable nil t nil
"-Q" "--batch"
"--eval" "(princ emacs-version)")
(buffer-string))
emacs-version)))
(erase-buffer)
(insert-file-contents treesit-admin--compat-template-file-name)
(goto-char (point-min))
(search-forward "___REPLACE_EMACS_VERSION___")
(replace-match emacs-version t)
(search-forward "___REPLACE_TIME___")
(replace-match (format "%s UTC" time) t)
(search-forward "___REPLACE_TABLE___")
(replace-match table-text t)
(write-region (point-min) (point-max) out-file))))
(provide 'treesit-admin)