org-element: Record origin buffer when parsing

* lisp/org-element.el (org-element-parse-buffer): Resolve all the
deferred values in the string.  If not, we might leave pointers to
killed buffer.
(org-element--parse-elements): Resolve deferred in objects.
(org-element--object-lex): Store :buffer property.
* lisp/org-macro.el (org-macro--find-date): Do not try to print
:buffer property.
* lisp/org-element.el (org-element--cache-persist-before-write):
(org-element--cache-persist-after-read): Clear and restore
non-printable buffer objects in :buffer property.
This commit is contained in:
Ihor Radchenko 2023-05-16 13:16:35 +02:00
parent f4aa3747e1
commit a8286a5a9e
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
2 changed files with 309 additions and 285 deletions

View File

@ -545,7 +545,8 @@ value of DATUM `:parent' property."
(defconst org-element--cache-element-properties (defconst org-element--cache-element-properties
'(:cached '(:cached
:org-element--cache-sync-key) :org-element--cache-sync-key
:buffer)
"List of element properties used internally by cache.") "List of element properties used internally by cache.")
(defvar org-element--string-cache (obarray-make) (defvar org-element--string-cache (obarray-make)
@ -1157,7 +1158,8 @@ parser (e.g. `:end' and :END:). Return value is a plist."
:post-blank (count-lines pos-before-blank end) :post-blank (count-lines pos-before-blank end)
:post-affiliated begin :post-affiliated begin
:path (buffer-file-name) :path (buffer-file-name)
:mode 'org-data) :mode 'org-data
:buffer (current-buffer)))
properties))))) properties)))))
(defun org-element-org-data-interpreter (_ contents) (defun org-element-org-data-interpreter (_ contents)
@ -4212,6 +4214,7 @@ element it has to parse."
;; Default element: Paragraph. ;; Default element: Paragraph.
(t (org-element-paragraph-parser limit affiliated))))))) (t (org-element-paragraph-parser limit affiliated)))))))
(when result (when result
(org-element-put-property result :buffer (current-buffer))
(org-element-put-property result :mode mode) (org-element-put-property result :mode mode)
(org-element-put-property result :granularity granularity)) (org-element-put-property result :granularity granularity))
result))) result)))
@ -4680,6 +4683,9 @@ Elements are accumulated into ACC."
RESTRICTION is a list of object types, as symbols, that should be RESTRICTION is a list of object types, as symbols, that should be
looked after. This function assumes that the buffer is narrowed looked after. This function assumes that the buffer is narrowed
to an appropriate container (e.g., a paragraph)." to an appropriate container (e.g., a paragraph)."
(let (result)
(setq
result
(cond (cond
((memq 'table-cell restriction) (org-element-table-cell-parser)) ((memq 'table-cell restriction) (org-element-table-cell-parser))
((memq 'citation-reference restriction) ((memq 'citation-reference restriction)
@ -4791,6 +4797,7 @@ to an appropriate container (e.g., a paragraph)."
(limit (forward-char -1) (limit (forward-char -1)
(org-element-link-parser)) ;radio link (org-element-link-parser)) ;radio link
(t nil))))))) (t nil)))))))
(org-element-put-property result :buffer (current-buffer))))
(defun org-element--parse-objects (beg end acc restriction &optional parent) (defun org-element--parse-objects (beg end acc restriction &optional parent)
"Parse objects between BEG and END and return recursive structure. "Parse objects between BEG and END and return recursive structure.
@ -7049,10 +7056,15 @@ The element is: %S\n The real element is: %S\n Cache around :begin:\n%S\n%S\n%S"
(org-with-wide-buffer (org-with-wide-buffer
(org-element--cache-sync (current-buffer) (point-max)) (org-element--cache-sync (current-buffer) (point-max))
;; Cleanup cache request keys to avoid collisions during next ;; Cleanup cache request keys to avoid collisions during next
;; Emacs session. ;; Emacs session. Cleanup known non-printable objects.
(avl-tree-mapc (avl-tree-mapc
(lambda (el) (lambda (el)
(org-element-put-property el :org-element--cache-sync-key nil)) (org-element-put-property el :org-element--cache-sync-key nil)
(org-element-map el t
(lambda (el2)
(unless (eq 'plain-text (org-element-type el2))
(org-element-put-property el2 :buffer nil)))
nil nil nil 'with-affiliated 'no-undefer))
org-element--cache) org-element--cache)
nil) nil)
'forbid)) 'forbid))
@ -7079,6 +7091,15 @@ The element is: %S\n The real element is: %S\n Cache around :begin:\n%S\n%S\n%S"
(with-current-buffer (get-file-buffer (plist-get associated :file)) (with-current-buffer (get-file-buffer (plist-get associated :file))
(when (and org-element-use-cache org-element-cache-persistent) (when (and org-element-use-cache org-element-cache-persistent)
(when (and (equal container '(elisp org-element--cache)) org-element--cache) (when (and (equal container '(elisp org-element--cache)) org-element--cache)
;; Restore `:buffer' property.
(avl-tree-mapc
(lambda (el)
(org-element-map el t
(lambda (el2)
(unless (eq 'plain-text (org-element-type el2))
(org-element-put-property el2 :buffer (current-buffer))))
nil nil nil 'with-affiliated 'no-undefer))
org-element--cache)
(setq-local org-element--cache-size (avl-tree-size org-element--cache))) (setq-local org-element--cache-size (avl-tree-size org-element--cache)))
(when (and (equal container '(elisp org-element--headline-cache)) org-element--headline-cache) (when (and (equal container '(elisp org-element--headline-cache)) org-element--headline-cache)
(setq-local org-element--headline-cache-size (avl-tree-size org-element--headline-cache))))))) (setq-local org-element--headline-cache-size (avl-tree-size org-element--headline-cache)))))))

View File

@ -369,7 +369,10 @@ Return value as a string."
(eq 'timestamp (org-element-type (car date)))) (eq 'timestamp (org-element-type (car date))))
(format "(eval (if (org-string-nw-p $1) %s %S))" (format "(eval (if (org-string-nw-p $1) %s %S))"
(format "(org-format-timestamp '%S $1)" (format "(org-format-timestamp '%S $1)"
(org-element-copy (car date))) (org-element-put-property
(org-element-copy (car date))
;; Remove non-printable.
:buffer nil))
value) value)
value))) value)))