From 300c581370073fbaad025465edc39bcbfe5e7c81 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sun, 6 Dec 2020 22:18:48 -0500 Subject: * lisp/emacs-lisp/lisp-mode.el: Give paren syntax to [...] in lisp-data-mode (lisp-data-mode-syntax-table): Rename from lisp--mode-syntax-table. Adjust all users. Set [...] to have paren syntax. (lisp-data-mode): Don't set `lisp-syntax` arg any more * lisp/progmodes/elisp-mode.el (emacs-lisp-mode-syntax-table): Don't bother setting [...] to have paren syntax any more. * lisp/progmodes/inf-lisp.el (inferior-lisp-mode): Don't use `lisp-syntax` arg of lisp-mode-variables any more. --- lisp/emacs-lisp/lisp-mode.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lisp/emacs-lisp') diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 081ef8d441a..e477ef17000 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -38,7 +38,7 @@ (define-abbrev-table 'lisp-mode-abbrev-table () "Abbrev table for Lisp mode.") -(defvar lisp--mode-syntax-table +(defvar lisp-data-mode-syntax-table (let ((table (make-syntax-table)) (i 0)) (while (< i ?0) @@ -77,11 +77,13 @@ (modify-syntax-entry ?\\ "\\ " table) (modify-syntax-entry ?\( "() " table) (modify-syntax-entry ?\) ")( " table) + (modify-syntax-entry ?\[ "(]" table) + (modify-syntax-entry ?\] ")[" table) table) "Parent syntax table used in Lisp modes.") (defvar lisp-mode-syntax-table - (let ((table (make-syntax-table lisp--mode-syntax-table))) + (let ((table (make-syntax-table lisp-data-mode-syntax-table))) (modify-syntax-entry ?\[ "_ " table) (modify-syntax-entry ?\] "_ " table) (modify-syntax-entry ?# "' 14" table) @@ -669,7 +671,7 @@ font-lock keywords will not be case sensitive." (define-derived-mode lisp-data-mode prog-mode "Lisp-Data" "Major mode for buffers holding data written in Lisp syntax." :group 'lisp - (lisp-mode-variables t t nil) + (lisp-mode-variables nil t nil) (setq-local electric-quote-string t) (setq imenu-case-fold-search nil)) -- cgit v1.2.3 From 0155bd0fdb166c97a2ce76cc5bc64fd195a676d3 Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Mon, 7 Dec 2020 21:41:40 +0100 Subject: Fix bug in how ERT invokes its debugger. The debugger needs to receive a list of the error symbol and data; cf. the documentation of the `debugger' variable. This bug manifested itself in ERT forms such as (should (integerp (ert-fail "Boo"))), which resulted in an incorrect condition object. Note that forms such as (should (ert-fail "Boo")) weren't affected because they wouldn't use the `ert--should-signal-hook'. * test/emacs-lisp/ert.el (ert--should-signal-hook): Call debugger with the right arguments. * test/lisp/emacs-lisp/ert-tests.el (ert-test-fail-inside-should): Add unit test. --- lisp/emacs-lisp/ert.el | 2 +- test/lisp/emacs-lisp/ert-tests.el | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'lisp/emacs-lisp') diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el index 5f29c2665a3..25237feae2a 100644 --- a/lisp/emacs-lisp/ert.el +++ b/lisp/emacs-lisp/ert.el @@ -274,7 +274,7 @@ DATA is displayed to the user and should state the reason for skipping." It should only be stopped when ran from inside ert--run-test-internal." (when (and (not (symbolp debugger)) ; only run on anonymous debugger (memq error-symbol '(ert-test-failed ert-test-skipped))) - (funcall debugger 'error data))) + (funcall debugger 'error (list error-symbol data)))) (defun ert--special-operator-p (thing) "Return non-nil if THING is a symbol naming a special operator." diff --git a/test/lisp/emacs-lisp/ert-tests.el b/test/lisp/emacs-lisp/ert-tests.el index 1f54c8d07e4..a0c56be0cb0 100644 --- a/test/lisp/emacs-lisp/ert-tests.el +++ b/test/lisp/emacs-lisp/ert-tests.el @@ -806,6 +806,16 @@ This macro is used to test if macroexpansion in `should' works." :expected-result :failed ;; FIXME! Bug#11218 (should-not (with-demoted-errors (error "Foo")))) +(ert-deftest ert-test-fail-inside-should () + "Check that `ert-fail' inside `should' works correctly." + (let ((result (ert-run-test + (make-ert-test + :name 'test-1 + :body (lambda () (should (integerp (ert-fail "Boo")))))))) + (should (ert-test-failed-p result)) + (should (equal (ert-test-failed-condition result) + '(ert-test-failed ("Boo")))))) + (provide 'ert-tests) -- cgit v1.2.3 From 67a9ecb4890872c288bda26e954e9c7629d709da Mon Sep 17 00:00:00 2001 From: João Távora Date: Tue, 8 Dec 2020 23:40:13 +0000 Subject: Remove interactive spec from internal eldoc--format-doc-buffer Per bug#43609. * lisp/emacs-lisp/eldoc.el (eldoc--format-doc-buffer): Remove useless interactive spec. --- lisp/emacs-lisp/eldoc.el | 1 - 1 file changed, 1 deletion(-) (limited to 'lisp/emacs-lisp') diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el index d81060ef165..6a976841038 100644 --- a/lisp/emacs-lisp/eldoc.el +++ b/lisp/emacs-lisp/eldoc.el @@ -467,7 +467,6 @@ This holds the results of the last documentation request." (defun eldoc--format-doc-buffer (docs) "Ensure DOCS are displayed in an *eldoc* buffer." - (interactive (list t)) (with-current-buffer (if (buffer-live-p eldoc--doc-buffer) eldoc--doc-buffer (setq eldoc--doc-buffer -- cgit v1.2.3 From c47e6aa1f48fc4417588cef55d96b4e9c1b3fead Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Wed, 9 Dec 2020 14:51:48 +0100 Subject: cl-defmethod doc string clarification * lisp/emacs-lisp/cl-generic.el (cl-defmethod): Clarify the doc string, and give an example (bug#42322). --- lisp/emacs-lisp/cl-generic.el | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'lisp/emacs-lisp') diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 02da07daaf4..b37b05b9a3a 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -410,8 +410,18 @@ the specializer used will be the one returned by BODY." ;;;###autoload (defmacro cl-defmethod (name args &rest body) "Define a new method for generic function NAME. -I.e. it defines the implementation of NAME to use for invocations where the -values of the dispatch arguments match the specified TYPEs. +This it defines an implementation of NAME to use for invocations +of specific types of arguments. + +ARGS is a list of dispatch arguments (see `cl-defun'), but where +each variable element is either just a single variable name VAR, +or a list on the form (VAR TYPE). + +For instance: + + (cl-defmethod foo (bar (format-string string) &optional zot) + (format format-string bar)) + The dispatch arguments have to be among the mandatory arguments, and all methods of NAME have to use the same set of arguments for dispatch. Each dispatch argument and TYPE are specified in ARGS where the corresponding -- cgit v1.2.3 From 004d7e97e2c54c1089a776055ffd173d132fe5ae Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Fri, 11 Dec 2020 14:49:53 +0100 Subject: Add a new command `memory-report' * doc/lispref/internals.texi (Garbage Collection): Document it. * lisp/emacs-lisp/memory-report.el: New package. --- doc/lispref/internals.texi | 13 ++ etc/NEWS | 5 + lisp/emacs-lisp/memory-report.el | 299 ++++++++++++++++++++++++++++ test/lisp/emacs-lisp/memory-report-tests.el | 54 +++++ 4 files changed, 371 insertions(+) create mode 100644 lisp/emacs-lisp/memory-report.el create mode 100644 test/lisp/emacs-lisp/memory-report-tests.el (limited to 'lisp/emacs-lisp') diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi index bb25983aa4b..fb24544c917 100644 --- a/doc/lispref/internals.texi +++ b/doc/lispref/internals.texi @@ -615,6 +615,19 @@ during garbage collection so far in this Emacs session, as a floating-point number. @end defvar +@defun memory-report +It can sometimes be useful to see where Emacs is using memory (in +various variables, buffers, and caches). This command will open a new +buffer (called @samp{"*Memory Report*"}) that will give an overview, +in addition to listing the ``largest'' buffers and variables. + +All the data here is approximate, because there's really no consistent +way to compute the size of a variable. For instance, two variables +may share parts of a data structure, and this will be counted twice, +but this command may still give a useful high-level overview of which +parts of Emacs is using memory. +@end defun + @node Stack-allocated Objects @section Stack-allocated Objects diff --git a/etc/NEWS b/etc/NEWS index 1640e277987..33cc2c30a08 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -275,6 +275,11 @@ preserving markers, properties and overlays. The new variable number of seconds that 'revert-buffer-with-fine-grain' should spend trying to be non-destructive. ++++ +** New command 'memory-report'. +This command opens a new buffer called "*Memory Report*" and gives a +summary of where Emacs is using memory currently. + ** Outline +++ diff --git a/lisp/emacs-lisp/memory-report.el b/lisp/emacs-lisp/memory-report.el new file mode 100644 index 00000000000..58555fa9f0d --- /dev/null +++ b/lisp/emacs-lisp/memory-report.el @@ -0,0 +1,299 @@ +;;; memory-report.el --- Short function summaries -*- lexical-binding: t -*- + +;; Copyright (C) 2020 Free Software Foundation, Inc. + +;; Keywords: lisp, help + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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. + +;; GNU Emacs 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 GNU Emacs. If not, see . + +;;; Commentary: + +;; Todo (possibly): Font cache, regexp cache, bidi cache, various +;; buffer caches (newline cache, free_region_cache, etc), composition +;; cache, face cache. + +;;; Code: + +(require 'seq) +(require 'subr-x) +(eval-when-compile (require 'cl-lib)) + +(defvar memory-report--type-size (make-hash-table)) + +;;;###autoload +(defun memory-report () + "Generate a report of how Emacs is using memory. + +This report is approximate, and will commonly over-count memory +usage by variables, because shared data structures will usually +by counted more than once." + (interactive) + (pop-to-buffer "*Memory Report*") + (special-mode) + (button-mode 1) + (setq truncate-lines t) + (message "Gathering data...") + (let ((reports (append (memory-report--garbage-collect) + (memory-report--image-cache) + (memory-report--buffers) + (memory-report--largest-variables))) + (inhibit-read-only t) + summaries details) + (message "Gathering data...done") + (erase-buffer) + (insert (propertize "Estimated Emacs Memory Usage\n\n" 'face 'bold)) + (dolist (report reports) + (if (listp report) + (push report summaries) + (push report details))) + (dolist (summary (nreverse summaries)) + (insert (format "%s %s\n" + (memory-report--format (cdr summary)) + (car summary)))) + (insert "\n") + (dolist (detail (nreverse details)) + (insert detail "\n"))) + (goto-char (point-min))) + +(defun memory-report-object-size (object) + "Return the size of OBJECT in bytes." + (unless memory-report--type-size + (memory-report--garbage-collect)) + (memory-report--object-size (make-hash-table :test #'eq) object)) + +(defun memory-report--size (type) + (or (gethash type memory-report--type-size) + (gethash 'object memory-report--type-size))) + +(defun memory-report--set-size (elems) + (setf (gethash 'string memory-report--type-size) + (cadr (assq 'strings elems))) + (setf (gethash 'cons memory-report--type-size) + (cadr (assq 'conses elems))) + (setf (gethash 'symbol memory-report--type-size) + (cadr (assq 'symbols elems))) + (setf (gethash 'object memory-report--type-size) + (cadr (assq 'vectors elems))) + (setf (gethash 'float memory-report--type-size) + (cadr (assq 'floats elems))) + (setf (gethash 'buffer memory-report--type-size) + (cadr (assq 'buffers elems)))) + +(defun memory-report--garbage-collect () + (let ((elems (garbage-collect))) + (memory-report--set-size elems) + (let ((data (list + (list 'strings + (+ (memory-report--gc-elem elems 'strings) + (memory-report--gc-elem elems 'string-bytes))) + (list 'vectors + (+ (memory-report--gc-elem elems 'vectors) + (memory-report--gc-elem elems 'vector-slots))) + (list 'floats (memory-report--gc-elem elems 'floats)) + (list 'conses (memory-report--gc-elem elems 'conses)) + (list 'symbols (memory-report--gc-elem elems 'symbols)) + (list 'intervals (memory-report--gc-elem elems 'intervals)) + (list 'buffer-objects + (memory-report--gc-elem elems 'buffers))))) + (list (cons "Overall Object Memory Usage" + (seq-reduce #'+ (mapcar (lambda (elem) + (* (nth 1 elem) (nth 2 elem))) + elems) + 0)) + (cons "Reserved (But Unused) Object Memory" + (seq-reduce #'+ (mapcar (lambda (elem) + (if (nth 3 elem) + (* (nth 1 elem) (nth 3 elem)) + 0)) + elems) + 0)) + (with-temp-buffer + (insert (propertize "Object Storage\n\n" 'face 'bold)) + (dolist (object (seq-sort (lambda (e1 e2) + (> (cadr e1) (cadr e2))) + data)) + (insert (format "%s %s\n" + (memory-report--format (cadr object)) + (capitalize (symbol-name (car object)))))) + (buffer-string)))))) + +(defun memory-report--largest-variables () + (let ((variables nil)) + (mapatoms + (lambda (symbol) + (when (boundp symbol) + (let ((size (memory-report--object-size + (make-hash-table :test #'eq) + (symbol-value symbol)))) + (when (> size 1000) + (push (cons symbol size) variables))))) + obarray) + (list + (cons (propertize "Memory Used By Global Variables" + 'help-echo "Upper bound; mutually overlapping data from different variables are counted several times") + (seq-reduce #'+ (mapcar #'cdr variables) 0)) + (with-temp-buffer + (insert (propertize "Largest Variables\n\n" 'face 'bold)) + (cl-loop for i from 1 upto 20 + for (symbol . size) in (seq-sort (lambda (e1 e2) + (> (cdr e1) (cdr e2))) + variables) + do (insert (memory-report--format size) + " " + (symbol-name symbol) + "\n")) + (buffer-string))))) + +(defun memory-report--object-size (counted value) + (if (gethash value counted) + 0 + (setf (gethash value counted) t) + (memory-report--object-size-1 counted value))) + +(cl-defgeneric memory-report--object-size-1 (_counted _value) + 0) + +(cl-defmethod memory-report--object-size-1 (_ (value symbol)) + ;; Don't count global symbols -- makes sizes of lists of symbols too + ;; heavey. + (if (intern-soft value obarray) + 0 + (memory-report--size 'symbol))) + +(cl-defmethod memory-report--object-size-1 (_ (_value buffer)) + (memory-report--size 'buffer)) + +(cl-defmethod memory-report--object-size-1 (counted (value string)) + (+ (memory-report--size 'string) + (string-bytes value) + (memory-report--interval-size counted (object-intervals value)))) + +(defun memory-report--interval-size (counted intervals) + ;; We get a list back of intervals, but only count the "inner list" + ;; (i.e., the actual text properties), and add the size of the + ;; intervals themselves. + (+ (* (memory-report--size 'interval) (length intervals)) + (seq-reduce #'+ (mapcar + (lambda (interval) + (memory-report--object-size counted (nth 2 interval))) + intervals) + 0))) + +(cl-defmethod memory-report--object-size-1 (counted (value list)) + (let ((total 0) + (size (memory-report--size 'cons))) + (while value + (cl-incf total size) + (setf (gethash value counted) t) + (when (car value) + (cl-incf total (memory-report--object-size counted (car value)))) + (if (cdr value) + (if (consp (cdr value)) + (setq value (cdr value)) + (cl-incf total (memory-report--object-size counted (cdr value))) + (setq value nil)) + (setq value nil))) + total)) + +(cl-defmethod memory-report--object-size-1 (counted (value vector)) + (let ((total (+ (memory-report--size 'vector) + (* (memory-report--size 'object) (length value))))) + (cl-loop for elem across value + do (setf (gethash elem counted) t) + (cl-incf total (memory-report--object-size counted elem))) + total)) + +(cl-defmethod memory-report--object-size-1 (counted (value hash-table)) + (let ((total (+ (memory-report--size 'vector) + (* (memory-report--size 'object) (hash-table-size value))))) + (maphash + (lambda (key elem) + (setf (gethash key counted) t) + (setf (gethash elem counted) t) + (cl-incf total (memory-report--object-size counted key)) + (cl-incf total (memory-report--object-size counted elem))) + value) + total)) + +(defun memory-report--format (bytes) + (setq bytes (/ bytes 1024.0)) + (let ((units '("kB" "MB" "GB" "TB"))) + (while (>= bytes 1024) + (setq bytes (/ bytes 1024.0)) + (setq units (cdr units))) + (format "%5.1f%s" bytes (car units)))) + +(defun memory-report--gc-elem (elems type) + (* (nth 1 (assq type elems)) + (nth 2 (assq type elems)))) + +(defun memory-report--buffers () + (let ((buffers (mapcar (lambda (buffer) + (cons buffer (memory-report--buffer buffer))) + (buffer-list)))) + (list (cons "Total Buffer Memory Usage" + (seq-reduce #'+ (mapcar #'cdr buffers) 0)) + (with-temp-buffer + (insert (propertize "Largest Buffers\n\n" 'face 'bold)) + (cl-loop for i from 1 upto 20 + for (buffer . size) in (seq-sort (lambda (e1 e2) + (> (cdr e1) (cdr e2))) + buffers) + do (insert (memory-report--format size) + " " + (button-buttonize + (buffer-name buffer) + #'memory-report--buffer-details buffer) + "\n")) + (buffer-string))))) + +(defun memory-report--buffer-details (buffer) + (with-current-buffer buffer + (apply + #'message + "Buffer text: %s; variables: %s; text properties: %s; overlays: %s" + (mapcar #'string-trim (mapcar #'memory-report--format + (memory-report--buffer-data buffer)))))) + +(defun memory-report--buffer (buffer) + (seq-reduce #'+ (memory-report--buffer-data buffer) 0)) + +(defun memory-report--buffer-data (buffer) + (with-current-buffer buffer + (list (save-restriction + (widen) + (+ (position-bytes (point-max)) + (- (position-bytes (point-min))) + (gap-size))) + (seq-reduce #'+ (mapcar (lambda (elem) + (if (cdr elem) + (memory-report--object-size + (make-hash-table :test #'eq) + (cdr elem)) + 0)) + (buffer-local-variables buffer)) + 0) + (memory-report--object-size (make-hash-table :test #'eq) + (object-intervals buffer)) + (memory-report--object-size (make-hash-table :test #'eq) + (overlay-lists))))) + +(defun memory-report--image-cache () + (list (cons "Total Image Cache Size" (image-cache-size)))) + +(provide 'memory-report) + +;;; memory-report.el ends here diff --git a/test/lisp/emacs-lisp/memory-report-tests.el b/test/lisp/emacs-lisp/memory-report-tests.el new file mode 100644 index 00000000000..01bcf18423a --- /dev/null +++ b/test/lisp/emacs-lisp/memory-report-tests.el @@ -0,0 +1,54 @@ +;;; memory-report-tests.el --- tests for memory-report.el -*- lexical-binding: t -*- + +;; Copyright (C) 2016-2020 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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. + +;; GNU Emacs 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 GNU Emacs. If not, see . + +(require 'ert) +(require 'memory-report) + +(defun setup-memory-report-tests () + (memory-report--set-size + '((conses 16 499173 99889) + (symbols 48 22244 3) + (strings 32 92719 4559) + (string-bytes 1 40402011) + (vectors 16 31919) + (vector-slots 8 385148 149240) + (floats 8 434 4519) + (intervals 56 24499 997) + (buffers 984 33)))) + +(ert-deftest memory-report-sizes () + (setup-memory-report-tests) + (should (equal (memory-report-object-size (cons nil nil)) 16)) + (should (equal (memory-report-object-size (cons 1 2)) 16)) + + (should (equal (memory-report-object-size (list 1 2)) 32)) + (should (equal (memory-report-object-size (list 1)) 16)) + + (should (equal (memory-report-object-size (list 'foo)) 16)) + + (should (equal (memory-report-object-size (vector 1 2 3 4)) 80)) + + (should (equal (memory-report-object-size "") 32)) + (should (equal (memory-report-object-size "a") 33)) + (should (equal (memory-report-object-size (propertize "a" 'face 'foo)) + 81))) + +(provide 'memory-report-tests) + +;;; memory-report-tests.el ends here -- cgit v1.2.3 From c7c261ebdf0232cc9263e8f8cbcc851a933076e0 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Fri, 11 Dec 2020 18:48:44 +0100 Subject: Tweak memory-report--format * lisp/emacs-lisp/memory-report.el (memory-report--format): Make everything line up, even when there's "1023.4kB". --- lisp/emacs-lisp/memory-report.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lisp/emacs-lisp') diff --git a/lisp/emacs-lisp/memory-report.el b/lisp/emacs-lisp/memory-report.el index 58555fa9f0d..0184c7ed8a5 100644 --- a/lisp/emacs-lisp/memory-report.el +++ b/lisp/emacs-lisp/memory-report.el @@ -234,7 +234,7 @@ by counted more than once." (while (>= bytes 1024) (setq bytes (/ bytes 1024.0)) (setq units (cdr units))) - (format "%5.1f%s" bytes (car units)))) + (format "%6.1f%s" bytes (car units)))) (defun memory-report--gc-elem (elems type) (* (nth 1 (assq type elems)) -- cgit v1.2.3 From b04f322a9bd0e5376eca0d4c2961a8a076eeb9bb Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Fri, 11 Dec 2020 18:58:41 +0100 Subject: Also sort the totals section by size * lisp/emacs-lisp/memory-report.el (memory-report): Sort the totals by size, too. --- lisp/emacs-lisp/memory-report.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lisp/emacs-lisp') diff --git a/lisp/emacs-lisp/memory-report.el b/lisp/emacs-lisp/memory-report.el index 0184c7ed8a5..c88d9f2768a 100644 --- a/lisp/emacs-lisp/memory-report.el +++ b/lisp/emacs-lisp/memory-report.el @@ -59,7 +59,9 @@ by counted more than once." (if (listp report) (push report summaries) (push report details))) - (dolist (summary (nreverse summaries)) + (dolist (summary (seq-sort (lambda (e1 e2) + (> (cdr e1) (cdr e2))) + summaries)) (insert (format "%s %s\n" (memory-report--format (cdr summary)) (car summary)))) -- cgit v1.2.3 From 7660d0359e637301651fe4433c2b9851840db120 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 11 Dec 2020 19:26:43 -0500 Subject: * lisp/emacs-lisp/thunk.el (thunk-let*): Don't modify `bindings` --- lisp/emacs-lisp/thunk.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lisp/emacs-lisp') diff --git a/lisp/emacs-lisp/thunk.el b/lisp/emacs-lisp/thunk.el index c8e483e9a4a..cd42152527e 100644 --- a/lisp/emacs-lisp/thunk.el +++ b/lisp/emacs-lisp/thunk.el @@ -122,7 +122,7 @@ Using `thunk-let' and `thunk-let*' requires `lexical-binding'." (declare (indent 1) (debug let)) (cl-reduce (lambda (expr binding) `(thunk-let (,binding) ,expr)) - (nreverse bindings) + (reverse bindings) :initial-value (macroexp-progn body))) ;; (defalias 'lazy-let #'thunk-let) -- cgit v1.2.3 From 9a7bce6241f5fc9ed982e95084641f3021314829 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sat, 12 Dec 2020 14:13:32 +0100 Subject: Make elint load `require'd packages * lisp/emacs-lisp/elint.el (elint-require-form): New function to load files that are `require'd (bug#27006). (elint-special-forms): Add function. --- lisp/emacs-lisp/elint.el | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'lisp/emacs-lisp') diff --git a/lisp/emacs-lisp/elint.el b/lisp/emacs-lisp/elint.el index ef97c8279d7..79b72ff969f 100644 --- a/lisp/emacs-lisp/elint.el +++ b/lisp/emacs-lisp/elint.el @@ -558,7 +558,8 @@ Return nil if there are no more forms, t otherwise." (when . elint-check-conditional-form) (unless . elint-check-conditional-form) (and . elint-check-conditional-form) - (or . elint-check-conditional-form)) + (or . elint-check-conditional-form) + (require . elint-require-form)) "Functions to call when some special form should be linted.") (defun elint-form (form env &optional nohandler) @@ -953,6 +954,13 @@ Does basic handling of `featurep' tests." (elint-form form env t)))) env) +(defun elint-require-form (form _env) + "Load `require'd files." + (pcase form + (`(require ',x) + (require x))) + nil) + ;;; ;;; Message functions ;;; -- cgit v1.2.3 From 4afef614cd6c93b4d4a57aa5bb211563649abc56 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sat, 12 Dec 2020 14:22:58 +0100 Subject: Alter the "Redundant pcase patter" warning message * lisp/emacs-lisp/pcase.el (pcase--expand): Make the "Redundant pcase pattern" warning less vague (bug#31350). --- lisp/emacs-lisp/pcase.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lisp/emacs-lisp') diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el index e603900b095..206f0dd1a9d 100644 --- a/lisp/emacs-lisp/pcase.el +++ b/lisp/emacs-lisp/pcase.el @@ -409,7 +409,8 @@ of the elements of LIST is performed as if by `pcase-let'. (dolist (case cases) (unless (or (memq case used-cases) (memq (car case) pcase--dontwarn-upats)) - (message "Redundant pcase pattern: %S" (car case)))) + (message "pcase pattern %S shadowed by previous pcase pattern" + (car case)))) (macroexp-let* defs main)))) (defun pcase--macroexpand (pat) -- cgit v1.2.3