edit.el 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. ;;; semantic/edit.el --- Edit Management for Semantic
  2. ;; Copyright (C) 1999-2017 Free Software Foundation, Inc.
  3. ;; Author: Eric M. Ludlam <zappo@gnu.org>
  4. ;; This file is part of GNU Emacs.
  5. ;; GNU Emacs is free software: you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation, either version 3 of the License, or
  8. ;; (at your option) any later version.
  9. ;; GNU Emacs is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;;
  17. ;; In Semantic 1.x, changes were handled in a simplistic manner, where
  18. ;; tags that changed were reparsed one at a time. Any other form of
  19. ;; edit were managed through a full reparse.
  20. ;;
  21. ;; This code attempts to minimize the number of times a full reparse
  22. ;; needs to occur. While overlays and tags will continue to be
  23. ;; recycled in the simple case, new cases where tags are inserted
  24. ;; or old tags removed from the original list are handled.
  25. ;;
  26. ;;; NOTES FOR IMPROVEMENT
  27. ;;
  28. ;; Work done by the incremental parser could be improved by the
  29. ;; following:
  30. ;;
  31. ;; 1. Tags created could have as a property an overlay marking a region
  32. ;; of themselves that can be edited w/out affecting the definition of
  33. ;; that tag.
  34. ;;
  35. ;; 2. Tags w/ positioned children could have a property of an
  36. ;; overlay marking the region in themselves that contain the
  37. ;; children. This could be used to better improve splicing near
  38. ;; the beginning and end of the child lists.
  39. ;;
  40. ;;; BUGS IN INCREMENTAL PARSER
  41. ;;
  42. ;; 1. Changes in the whitespace between tags could extend a
  43. ;; following tag. These will be marked as merely unmatched
  44. ;; syntax instead.
  45. ;;
  46. ;; 2. Incremental parsing while a new function is being typed in
  47. ;; sometimes gets a chance only when lists are incomplete,
  48. ;; preventing correct context identification.
  49. ;;
  50. (require 'semantic)
  51. ;;; Code:
  52. (defvar semantic-after-partial-cache-change-hook nil
  53. "Normal hook run after the buffer cache has been updated.
  54. This hook will run when the cache has been partially reparsed.
  55. Partial reparses are incurred when a user edits a buffer, and only the
  56. modified sections are rescanned.
  57. Hook functions must take one argument, which is the list of tags
  58. updated in the current buffer.
  59. For language specific hooks, make sure you define this as a local hook.")
  60. (define-obsolete-variable-alias 'semantic-change-hooks
  61. 'semantic-change-functions "24.3")
  62. (defvar semantic-change-functions
  63. '(semantic-edits-change-function-handle-changes)
  64. "Abnormal hook run when semantic detects a change in a buffer.
  65. Each hook function must take three arguments, identical to the
  66. common hook `after-change-functions'.")
  67. (defvar semantic-reparse-needed-change-hook nil
  68. "Hooks run when a user edit is detected as needing a reparse.
  69. For language specific hooks, make sure you define this as a local hook.
  70. Not used yet; part of the next generation reparse mechanism.")
  71. (defvar semantic-no-reparse-needed-change-hook nil
  72. "Hooks run when a user edit is detected as not needing a reparse.
  73. If the hook returns non-nil, then declare that a reparse is needed.
  74. For language specific hooks, make sure you define this as a local hook.
  75. Not used yet; part of the next generation reparse mechanism.")
  76. (define-obsolete-variable-alias 'semantic-edits-new-change-hooks
  77. 'semantic-edits-new-change-functions "24.3")
  78. (defvar semantic-edits-new-change-functions nil
  79. "Abnormal hook run when a new change is found.
  80. Functions must take one argument representing an overlay on that change.")
  81. (define-obsolete-variable-alias 'semantic-edits-delete-change-hooks
  82. 'semantic-edits-delete-change-functions "24.3")
  83. (defvar semantic-edits-delete-change-functions nil
  84. "Abnormal hook run before a change overlay is deleted.
  85. Deleted changes occur when multiple changes are merged.
  86. Functions must take one argument representing an overlay being deleted.")
  87. (defvar semantic-edits-move-change-hook nil
  88. "Abnormal hook run after a change overlay is moved.
  89. Changes move when a new change overlaps an old change. The old change
  90. will be moved.
  91. Functions must take one argument representing an overlay being moved.")
  92. (define-obsolete-variable-alias 'semantic-edits-reparse-change-hooks
  93. 'semantic-edits-reparse-change-functions "24.3")
  94. (defvar semantic-edits-reparse-change-functions nil
  95. "Abnormal hook run after a change results in a reparse.
  96. Functions are called before the overlay is deleted, and after the
  97. incremental reparse.")
  98. (defvar semantic-edits-incremental-reparse-failed-hook nil
  99. "Hook run after the incremental parser fails.
  100. When this happens, the buffer is marked as needing a full reparse.")
  101. (semantic-varalias-obsolete 'semantic-edits-incremental-reparse-failed-hooks
  102. 'semantic-edits-incremental-reparse-failed-hook "23.2")
  103. (defcustom semantic-edits-verbose-flag nil
  104. "Non-nil means the incremental parser is verbose.
  105. If nil, errors are still displayed, but informative messages are not."
  106. :group 'semantic
  107. :type 'boolean)
  108. ;;; Change State management
  109. ;;
  110. ;; Manage a series of overlays that define changes recently
  111. ;; made to the current buffer.
  112. ;;;###autoload
  113. (defun semantic-change-function (start end length)
  114. "Provide a mechanism for semantic tag management.
  115. Argument START, END, and LENGTH specify the bounds of the change."
  116. (setq semantic-unmatched-syntax-cache-check t)
  117. (let ((inhibit-point-motion-hooks t)
  118. )
  119. (save-match-data
  120. (run-hook-with-args 'semantic-change-functions start end length)
  121. )))
  122. (defun semantic-changes-in-region (start end &optional buffer)
  123. "Find change overlays which exist in whole or in part between START and END.
  124. Optional argument BUFFER is the buffer to search for changes in."
  125. (save-excursion
  126. (if buffer (set-buffer buffer))
  127. (let ((ol (semantic-overlays-in (max start (point-min))
  128. (min end (point-max))))
  129. (ret nil))
  130. (while ol
  131. (when (semantic-overlay-get (car ol) 'semantic-change)
  132. (setq ret (cons (car ol) ret)))
  133. (setq ol (cdr ol)))
  134. (sort ret #'(lambda (a b) (< (semantic-overlay-start a)
  135. (semantic-overlay-start b)))))))
  136. (defun semantic-edits-change-function-handle-changes (start end length)
  137. "Run whenever a buffer controlled by `semantic-mode' change.
  138. Tracks when and how the buffer is re-parsed.
  139. Argument START, END, and LENGTH specify the bounds of the change."
  140. ;; We move start/end by one so that we can merge changes that occur
  141. ;; just before, or just after. This lets simple typing capture everything
  142. ;; into one overlay.
  143. (let ((changes-in-change (semantic-changes-in-region (1- start) (1+ end)))
  144. )
  145. (semantic-parse-tree-set-needs-update)
  146. (if (not changes-in-change)
  147. (let ((o (semantic-make-overlay start end)))
  148. (semantic-overlay-put o 'semantic-change t)
  149. ;; Run the hooks safely. When hooks blow it, our dirty
  150. ;; function will be removed from the list of active change
  151. ;; functions.
  152. (condition-case nil
  153. (run-hook-with-args 'semantic-edits-new-change-functions o)
  154. (error nil)))
  155. (let ((tmp changes-in-change))
  156. ;; Find greatest bounds of all changes
  157. (while tmp
  158. (when (< (semantic-overlay-start (car tmp)) start)
  159. (setq start (semantic-overlay-start (car tmp))))
  160. (when (> (semantic-overlay-end (car tmp)) end)
  161. (setq end (semantic-overlay-end (car tmp))))
  162. (setq tmp (cdr tmp)))
  163. ;; Move the first found overlay, recycling that overlay.
  164. (semantic-overlay-move (car changes-in-change) start end)
  165. (condition-case nil
  166. (run-hook-with-args 'semantic-edits-move-change-hooks
  167. (car changes-in-change))
  168. (error nil))
  169. (setq changes-in-change (cdr changes-in-change))
  170. ;; Delete other changes. They are now all bound here.
  171. (while changes-in-change
  172. (condition-case nil
  173. (run-hook-with-args 'semantic-edits-delete-change-functions
  174. (car changes-in-change))
  175. (error nil))
  176. (semantic-overlay-delete (car changes-in-change))
  177. (setq changes-in-change (cdr changes-in-change))))
  178. )))
  179. (defsubst semantic-edits-flush-change (change)
  180. "Flush the CHANGE overlay."
  181. (condition-case nil
  182. (run-hook-with-args 'semantic-edits-delete-change-functions
  183. change)
  184. (error nil))
  185. (semantic-overlay-delete change))
  186. (defun semantic-edits-flush-changes ()
  187. "Flush the changes in the current buffer."
  188. (let ((changes (semantic-changes-in-region (point-min) (point-max))))
  189. (while changes
  190. (semantic-edits-flush-change (car changes))
  191. (setq changes (cdr changes))))
  192. )
  193. (defun semantic-edits-change-in-one-tag-p (change hits)
  194. "Return non-nil of the overlay CHANGE exists solely in one leaf tag.
  195. HITS is the list of tags that CHANGE is in. It can have more than
  196. one tag in it if the leaf tag is within a parent tag."
  197. (and (< (semantic-tag-start (car hits))
  198. (semantic-overlay-start change))
  199. (> (semantic-tag-end (car hits))
  200. (semantic-overlay-end change))
  201. ;; Recurse on the rest. If this change is inside all
  202. ;; of these tags, then they are all leaves or parents
  203. ;; of the smallest tag.
  204. (or (not (cdr hits))
  205. (semantic-edits-change-in-one-tag-p change (cdr hits))))
  206. )
  207. ;;; Change/Tag Query functions
  208. ;;
  209. ;; A change (region of space) can effect tags in different ways.
  210. ;; These functions perform queries on a buffer to determine different
  211. ;; ways that a change effects a buffer.
  212. ;;
  213. ;; NOTE: After debugging these, replace below to no longer look
  214. ;; at point and mark (via comments I assume.)
  215. (defsubst semantic-edits-os (change)
  216. "For testing: Start of CHANGE, or smaller of (point) and (mark)."
  217. (if change (semantic-overlay-start change)
  218. (if (< (point) (mark)) (point) (mark))))
  219. (defsubst semantic-edits-oe (change)
  220. "For testing: End of CHANGE, or larger of (point) and (mark)."
  221. (if change (semantic-overlay-end change)
  222. (if (> (point) (mark)) (point) (mark))))
  223. (defun semantic-edits-change-leaf-tag (change)
  224. "A leaf tag which completely encompasses CHANGE.
  225. If change overlaps a tag, but is not encompassed in it, return nil.
  226. Use `semantic-edits-change-overlap-leaf-tag'.
  227. If CHANGE is completely encompassed in a tag, but overlaps sub-tags,
  228. return nil."
  229. (let* ((start (semantic-edits-os change))
  230. (end (semantic-edits-oe change))
  231. (tags (nreverse
  232. (semantic-find-tag-by-overlay-in-region
  233. start end))))
  234. ;; A leaf is always first in this list
  235. (if (and tags
  236. (<= (semantic-tag-start (car tags)) start)
  237. (> (semantic-tag-end (car tags)) end))
  238. ;; Ok, we have a match. If this tag has children,
  239. ;; we have to do more tests.
  240. (let ((chil (semantic-tag-components (car tags))))
  241. (if (not chil)
  242. ;; Simple leaf.
  243. (car tags)
  244. ;; For this type, we say that we encompass it if the
  245. ;; change occurs outside the range of the children.
  246. (if (or (not (semantic-tag-with-position-p (car chil)))
  247. (> start (semantic-tag-end (nth (1- (length chil)) chil)))
  248. (< end (semantic-tag-start (car chil))))
  249. ;; We have modifications to the definition of this parent
  250. ;; so we have to reparse the whole thing.
  251. (car tags)
  252. ;; We actually modified an area between some children.
  253. ;; This means we should return nil, as that case is
  254. ;; calculated by someone else.
  255. nil)))
  256. nil)))
  257. (defun semantic-edits-change-between-tags (change)
  258. "Return a cache list of tags surrounding CHANGE.
  259. The returned list is the CONS cell in the master list pointing to
  260. a tag just before CHANGE. The CDR will have the tag just after CHANGE.
  261. CHANGE cannot encompass or overlap a leaf tag.
  262. If CHANGE is fully encompassed in a tag that has children, and
  263. this change occurs between those children, this returns non-nil.
  264. See `semantic-edits-change-leaf-tag' for details on parents."
  265. (let* ((start (semantic-edits-os change))
  266. (end (semantic-edits-oe change))
  267. (tags (nreverse
  268. (semantic-find-tag-by-overlay-in-region
  269. start end)))
  270. (list-to-search nil)
  271. (found nil))
  272. (if (not tags)
  273. (setq list-to-search semantic--buffer-cache)
  274. ;; A leaf is always first in this list
  275. (if (and (< (semantic-tag-start (car tags)) start)
  276. (> (semantic-tag-end (car tags)) end))
  277. ;; We are completely encompassed in a tag.
  278. (if (setq list-to-search
  279. (semantic-tag-components (car tags)))
  280. ;; Ok, we are completely encompassed within the first tag
  281. ;; entry, AND that tag has children. This means that change
  282. ;; occurred outside of all children, but inside some tag
  283. ;; with children.
  284. (if (or (not (semantic-tag-with-position-p (car list-to-search)))
  285. (> start (semantic-tag-end
  286. (nth (1- (length list-to-search))
  287. list-to-search)))
  288. (< end (semantic-tag-start (car list-to-search))))
  289. ;; We have modifications to the definition of this parent
  290. ;; and not between it's children. Clear the search list.
  291. (setq list-to-search nil)))
  292. ;; Search list is nil.
  293. ))
  294. ;; If we have a search list, let's go. Otherwise nothing.
  295. (while (and list-to-search (not found))
  296. (if (cdr list-to-search)
  297. ;; We end when the start of the CDR is after the end of our
  298. ;; asked change.
  299. (if (< (semantic-tag-start (cadr list-to-search)) end)
  300. (setq list-to-search (cdr list-to-search))
  301. (setq found t))
  302. (setq list-to-search nil)))
  303. ;; Return it. If it is nil, there is a logic bug, and we need
  304. ;; to avoid this bit of logic anyway.
  305. list-to-search
  306. ))
  307. (defun semantic-edits-change-over-tags (change)
  308. "Return a cache list of tags surrounding a CHANGE encompassing tags.
  309. CHANGE must not only include all overlapped tags (excepting possible
  310. parent tags) in their entirety. In this case, the change may be deleting
  311. or moving whole tags.
  312. The return value is a vector.
  313. Cell 0 is a list of all tags completely encompassed in change.
  314. Cell 1 is the cons cell into a master parser cache starting with
  315. the cell which occurs BEFORE the first position of CHANGE.
  316. Cell 2 is the parent of cell 1, or nil for the buffer cache.
  317. This function returns nil if any tag covered by change is not
  318. completely encompassed.
  319. See `semantic-edits-change-leaf-tag' for details on parents."
  320. (let* ((start (semantic-edits-os change))
  321. (end (semantic-edits-oe change))
  322. (tags (nreverse
  323. (semantic-find-tag-by-overlay-in-region
  324. start end)))
  325. (parent nil)
  326. (overlapped-tags nil)
  327. inner-start inner-end
  328. (list-to-search nil))
  329. ;; By the time this is already called, we know that it is
  330. ;; not a leaf change, nor a between tag change. That leaves
  331. ;; an overlap, and this condition.
  332. ;; A leaf is always first in this list.
  333. ;; Is the leaf encompassed in this change?
  334. (if (and tags
  335. (>= (semantic-tag-start (car tags)) start)
  336. (<= (semantic-tag-end (car tags)) end))
  337. (progn
  338. ;; We encompass one whole change.
  339. (setq overlapped-tags (list (car tags))
  340. inner-start (semantic-tag-start (car tags))
  341. inner-end (semantic-tag-end (car tags))
  342. tags (cdr tags))
  343. ;; Keep looping while tags are inside the change.
  344. (while (and tags
  345. (>= (semantic-tag-start (car tags)) start)
  346. (<= (semantic-tag-end (car tags)) end))
  347. ;; Check if this new all-encompassing tag is a parent
  348. ;; of that which went before. Only check end because
  349. ;; we know that start is less than inner-start since
  350. ;; tags was sorted on that.
  351. (if (> (semantic-tag-end (car tags)) inner-end)
  352. ;; This is a parent. Drop the children found
  353. ;; so far.
  354. (setq overlapped-tags (list (car tags))
  355. inner-start (semantic-tag-start (car tags))
  356. inner-end (semantic-tag-end (car tags))
  357. )
  358. ;; It is not a parent encompassing tag
  359. (setq overlapped-tags (cons (car tags)
  360. overlapped-tags)
  361. inner-start (semantic-tag-start (car tags))))
  362. (setq tags (cdr tags)))
  363. (if (not tags)
  364. ;; There are no tags left, and all tags originally
  365. ;; found are encompassed by the change. Setup our list
  366. ;; from the cache
  367. (setq list-to-search semantic--buffer-cache);; We have a tag outside the list. Check for
  368. ;; We know we have a parent because it would
  369. ;; completely cover the change. A tag can only
  370. ;; do that if it is a parent after we get here.
  371. (when (and tags
  372. (< (semantic-tag-start (car tags)) start)
  373. (> (semantic-tag-end (car tags)) end))
  374. ;; We have a parent. Stuff in the search list.
  375. (setq parent (car tags)
  376. list-to-search (semantic-tag-components parent))
  377. ;; If the first of TAGS is a parent (see above)
  378. ;; then clear out the list. All other tags in
  379. ;; here must therefore be parents of the car.
  380. (setq tags nil)
  381. ;; One last check, If start is before the first
  382. ;; tag or after the last, we may have overlap into
  383. ;; the characters that make up the definition of
  384. ;; the tag we are parsing.
  385. (when (or (semantic-tag-with-position-p (car list-to-search))
  386. (< start (semantic-tag-start
  387. (car list-to-search)))
  388. (> end (semantic-tag-end
  389. (nth (1- (length list-to-search))
  390. list-to-search))))
  391. ;; We have a problem
  392. (setq list-to-search nil
  393. parent nil))))
  394. (when list-to-search
  395. ;; Ok, return the vector only if all TAGS are
  396. ;; confirmed as the lineage of `overlapped-tags'
  397. ;; which must have a value by now.
  398. ;; Loop over the search list to find the preceding CDR.
  399. ;; Fortunately, (car overlapped-tags) happens to be
  400. ;; the first tag positionally.
  401. (let ((tokstart (semantic-tag-start (car overlapped-tags))))
  402. (while (and list-to-search
  403. ;; Assume always (car (cdr list-to-search)).
  404. ;; A thrown error will be captured nicely, but
  405. ;; that case shouldn't happen.
  406. ;; We end when the start of the CDR is after the
  407. ;; end of our asked change.
  408. (cdr list-to-search)
  409. (< (semantic-tag-start (car (cdr list-to-search)))
  410. tokstart)
  411. (setq list-to-search (cdr list-to-search)))))
  412. ;; Create the return vector
  413. (vector overlapped-tags
  414. list-to-search
  415. parent)
  416. ))
  417. nil)))
  418. ;;; Default Incremental Parser
  419. ;;
  420. ;; Logic about how to group changes for effective reparsing and splicing.
  421. (defun semantic-parse-changes-failed (&rest args)
  422. "Signal that Semantic failed to parse changes.
  423. That is, display a message by passing all ARGS to `format-message', then throw
  424. a 'semantic-parse-changes-failed exception with value t."
  425. (when semantic-edits-verbose-flag
  426. (message "Semantic parse changes failed: %S"
  427. (apply #'format-message args)))
  428. (throw 'semantic-parse-changes-failed t))
  429. (defsubst semantic-edits-incremental-fail ()
  430. "When the incremental parser fails, we mark that we need a full reparse."
  431. ;;(debug)
  432. (semantic-parse-tree-set-needs-rebuild)
  433. (when semantic-edits-verbose-flag
  434. (message "Force full reparse (%s)"
  435. (buffer-name (current-buffer))))
  436. (run-hooks 'semantic-edits-incremental-reparse-failed-hook))
  437. ;;;###autoload
  438. (defun semantic-edits-incremental-parser ()
  439. "Incrementally reparse the current buffer.
  440. Incremental parser allows semantic to only reparse those sections of
  441. the buffer that have changed. This function depends on
  442. `semantic-edits-change-function-handle-changes' setting up change
  443. overlays in the current buffer. Those overlays are analyzed against
  444. the semantic cache to see what needs to be changed."
  445. (let ((changed-tags
  446. ;; Don't use `semantic-safe' here to explicitly catch errors
  447. ;; and reset the parse tree.
  448. (catch 'semantic-parse-changes-failed
  449. (if debug-on-error
  450. (semantic-edits-incremental-parser-1)
  451. (condition-case err
  452. (semantic-edits-incremental-parser-1)
  453. (error
  454. (message "incremental parser error: %S"
  455. (error-message-string err))
  456. t))))))
  457. (when (eq changed-tags t)
  458. ;; Force a full reparse.
  459. (semantic-edits-incremental-fail)
  460. (setq changed-tags nil))
  461. changed-tags))
  462. (defmacro semantic-edits-assert-valid-region ()
  463. "Assert that parse-start and parse-end are sorted correctly."
  464. ;;; (if (> parse-start parse-end)
  465. ;;; (error "Bug is %s !> %d! Buff min/max = [ %d %d ]"
  466. ;;; parse-start parse-end
  467. ;;; (point-min) (point-max)))
  468. )
  469. (defun semantic-edits-incremental-parser-1 ()
  470. "Incrementally reparse the current buffer.
  471. Return the list of tags that changed.
  472. If the incremental parse fails, throw a 'semantic-parse-changes-failed
  473. exception with value t, that can be caught to schedule a full reparse.
  474. This function is for internal use by `semantic-edits-incremental-parser'."
  475. (let* ((changed-tags nil)
  476. (debug-on-quit t) ; try to find this annoying bug!
  477. (changes (semantic-changes-in-region
  478. (point-min) (point-max)))
  479. (tags nil) ;tags found at changes
  480. (newf-tags nil) ;newfound tags in change
  481. (parse-start nil) ;location to start parsing
  482. (parse-end nil) ;location to end parsing
  483. (parent-tag nil) ;parent of the cache list.
  484. (cache-list nil) ;list of children within which
  485. ;we incrementally reparse.
  486. (reparse-symbol nil) ;The ruled we start at for reparse.
  487. (change-group nil) ;changes grouped in this reparse
  488. (last-cond nil) ;track the last case used.
  489. ;query this when debugging to find
  490. ;source of bugs.
  491. )
  492. (or changes
  493. ;; If we were called, and there are no changes, then we
  494. ;; don't know what to do. Force a full reparse.
  495. (semantic-parse-changes-failed "Don't know what to do"))
  496. ;; Else, we have some changes. Loop over them attempting to
  497. ;; patch things up.
  498. (while changes
  499. ;; Calculate the reparse boundary.
  500. ;; We want to take some set of changes, and group them
  501. ;; together into a small change group. One change forces
  502. ;; a reparse of a larger region (the size of some set of
  503. ;; tags it encompasses.) It may contain several tags.
  504. ;; That region may have other changes in it (several small
  505. ;; changes in one function, for example.)
  506. ;; Optimize for the simple cases here, but try to handle
  507. ;; complex ones too.
  508. (while (and changes ; we still have changes
  509. (or (not parse-start)
  510. ;; Below, if the change we are looking at
  511. ;; is not the first change for this
  512. ;; iteration, and it starts before the end
  513. ;; of current parse region, then it is
  514. ;; encompassed within the bounds of tags
  515. ;; modified by the previous iteration's
  516. ;; change.
  517. (< (semantic-overlay-start (car changes))
  518. parse-end)))
  519. ;; REMOVE LATER
  520. (if (eq (car changes) (car change-group))
  521. (semantic-parse-changes-failed
  522. "Possible infinite loop detected"))
  523. ;; Store this change in this change group.
  524. (setq change-group (cons (car changes) change-group))
  525. (cond
  526. ;; Is this is a new parse group?
  527. ((not parse-start)
  528. (setq last-cond "new group")
  529. (let (tmp)
  530. (cond
  531. ;;;; Are we encompassed all in one tag?
  532. ((setq tmp (semantic-edits-change-leaf-tag (car changes)))
  533. (setq last-cond "Encompassed in tag")
  534. (setq tags (list tmp)
  535. parse-start (semantic-tag-start tmp)
  536. parse-end (semantic-tag-end tmp)
  537. )
  538. (semantic-edits-assert-valid-region))
  539. ;;;; Did the change occur between some tags?
  540. ((setq cache-list (semantic-edits-change-between-tags
  541. (car changes)))
  542. (setq last-cond "Between and not overlapping tags")
  543. ;; The CAR of cache-list is the tag just before
  544. ;; our change, but wasn't modified. Hmmm.
  545. ;; Bound our reparse between these two tags
  546. (setq tags nil
  547. parent-tag
  548. (car (semantic-find-tag-by-overlay
  549. parse-start)))
  550. (cond
  551. ;; A change at the beginning of the buffer.
  552. ;; Feb 06 -
  553. ;; IDed when the first cache-list tag is after
  554. ;; our change, meaning there is nothing before
  555. ;; the change.
  556. ((> (semantic-tag-start (car cache-list))
  557. (semantic-overlay-end (car changes)))
  558. (setq last-cond "Beginning of buffer")
  559. (setq parse-start
  560. ;; Don't worry about parents since
  561. ;; there there would be an exact
  562. ;; match in the tag list otherwise
  563. ;; and the routine would fail.
  564. (point-min)
  565. parse-end
  566. (semantic-tag-start (car cache-list)))
  567. (semantic-edits-assert-valid-region)
  568. )
  569. ;; A change stuck on the first surrounding tag.
  570. ((= (semantic-tag-end (car cache-list))
  571. (semantic-overlay-start (car changes)))
  572. (setq last-cond "Beginning of Tag")
  573. ;; Reparse that first tag.
  574. (setq parse-start
  575. (semantic-tag-start (car cache-list))
  576. parse-end
  577. (semantic-overlay-end (car changes))
  578. tags
  579. (list (car cache-list)))
  580. (semantic-edits-assert-valid-region)
  581. )
  582. ;; A change at the end of the buffer.
  583. ((not (car (cdr cache-list)))
  584. (setq last-cond "End of buffer")
  585. (setq parse-start (semantic-tag-end
  586. (car cache-list))
  587. parse-end (point-max))
  588. (semantic-edits-assert-valid-region)
  589. )
  590. (t
  591. (setq last-cond "Default")
  592. (setq parse-start
  593. (semantic-tag-end (car cache-list))
  594. parse-end
  595. (semantic-tag-start (car (cdr cache-list)))
  596. )
  597. (semantic-edits-assert-valid-region))))
  598. ;;;; Did the change completely overlap some number of tags?
  599. ((setq tmp (semantic-edits-change-over-tags
  600. (car changes)))
  601. (setq last-cond "Overlap multiple tags")
  602. ;; Extract the information
  603. (setq tags (aref tmp 0)
  604. cache-list (aref tmp 1)
  605. parent-tag (aref tmp 2))
  606. ;; We can calculate parse begin/end by checking
  607. ;; out what is in TAGS. The one near start is
  608. ;; always first. Make sure the reparse includes
  609. ;; the `whitespace' around the snarfed tags.
  610. ;; Since cache-list is positioned properly, use it
  611. ;; to find that boundary.
  612. (if (eq (car tags) (car cache-list))
  613. ;; Beginning of the buffer!
  614. (let ((end-marker (nth (length tags)
  615. cache-list)))
  616. (setq parse-start (point-min))
  617. (if end-marker
  618. (setq parse-end
  619. (semantic-tag-start end-marker))
  620. (setq parse-end (semantic-overlay-end
  621. (car changes))))
  622. (semantic-edits-assert-valid-region)
  623. )
  624. ;; Middle of the buffer.
  625. (setq parse-start
  626. (semantic-tag-end (car cache-list)))
  627. ;; For the end, we need to scoot down some
  628. ;; number of tags. We 1+ the length of tags
  629. ;; because we want to skip the first tag
  630. ;; (remove 1-) then want the tag after the end
  631. ;; of the list (1+)
  632. (let ((end-marker (nth (1+ (length tags)) cache-list)))
  633. (if end-marker
  634. (setq parse-end (semantic-tag-start end-marker))
  635. ;; No marker. It is the last tag in our
  636. ;; list of tags. Only possible if END
  637. ;; already matches the end of that tag.
  638. (setq parse-end
  639. (semantic-overlay-end (car changes)))))
  640. (semantic-edits-assert-valid-region)
  641. ))
  642. ;;;; Unhandled case.
  643. ;; Throw error, and force full reparse.
  644. ((semantic-parse-changes-failed "Unhandled change group")))
  645. ))
  646. ;; Is this change inside the previous parse group?
  647. ;; We already checked start.
  648. ((< (semantic-overlay-end (car changes)) parse-end)
  649. (setq last-cond "in bounds")
  650. nil)
  651. ;; This change extends the current parse group.
  652. ;; Find any new tags, and see how to append them.
  653. ((semantic-parse-changes-failed
  654. (setq last-cond "overlap boundary")
  655. "Unhandled secondary change overlapping boundary"))
  656. )
  657. ;; Prepare for the next iteration.
  658. (setq changes (cdr changes)))
  659. ;; By the time we get here, all TAGS are children of
  660. ;; some parent. They should all have the same start symbol
  661. ;; since that is how the multi-tag parser works. Grab
  662. ;; the reparse symbol from the first of the returned tags.
  663. ;;
  664. ;; Feb '06 - If reparse-symbol is nil, then they are top level
  665. ;; tags. (I'm guessing.) Is this right?
  666. (setq reparse-symbol
  667. (semantic--tag-get-property (car (or tags cache-list))
  668. 'reparse-symbol))
  669. ;; Find a parent if not provided.
  670. (and (not parent-tag) tags
  671. (setq parent-tag
  672. (semantic-find-tag-parent-by-overlay
  673. (car tags))))
  674. ;; We can do the same trick for our parent and resulting
  675. ;; cache list.
  676. (unless cache-list
  677. (if parent-tag
  678. (setq cache-list
  679. ;; We need to get all children in case we happen
  680. ;; to have a mix of positioned and non-positioned
  681. ;; children.
  682. (semantic-tag-components parent-tag))
  683. ;; Else, all the tags since there is no parent.
  684. ;; It sucks to have to use the full buffer cache in
  685. ;; this case because it can be big. Failure to provide
  686. ;; however results in a crash.
  687. (setq cache-list semantic--buffer-cache)
  688. ))
  689. ;; Use the boundary to calculate the new tags found.
  690. (setq newf-tags (semantic-parse-region
  691. parse-start parse-end reparse-symbol))
  692. ;; Make sure all these tags are given overlays.
  693. ;; They have already been cooked by the parser and just
  694. ;; need the overlays.
  695. (let ((tmp newf-tags))
  696. (while tmp
  697. (semantic--tag-link-to-buffer (car tmp))
  698. (setq tmp (cdr tmp))))
  699. ;; See how this change lays out.
  700. (cond
  701. ;;;; Whitespace change
  702. ((and (not tags) (not newf-tags))
  703. ;; A change that occurred outside of any existing tags
  704. ;; and there are no new tags to replace it.
  705. (when semantic-edits-verbose-flag
  706. (message "White space changes"))
  707. nil
  708. )
  709. ;;;; New tags in old whitespace area.
  710. ((and (not tags) newf-tags)
  711. ;; A change occurred outside existing tags which added
  712. ;; a new tag. We need to splice these tags back
  713. ;; into the cache at the right place.
  714. (semantic-edits-splice-insert newf-tags parent-tag cache-list)
  715. (setq changed-tags
  716. (append newf-tags changed-tags))
  717. (when semantic-edits-verbose-flag
  718. (message "Inserted tags: (%s)"
  719. (semantic-format-tag-name (car newf-tags))))
  720. )
  721. ;;;; Old tags removed
  722. ((and tags (not newf-tags))
  723. ;; A change occurred where pre-existing tags were
  724. ;; deleted! Remove the tag from the cache.
  725. (semantic-edits-splice-remove tags parent-tag cache-list)
  726. (setq changed-tags
  727. (append tags changed-tags))
  728. (when semantic-edits-verbose-flag
  729. (message "Deleted tags: (%s)"
  730. (semantic-format-tag-name (car tags))))
  731. )
  732. ;;;; One tag was updated.
  733. ((and (= (length tags) 1) (= (length newf-tags) 1))
  734. ;; One old tag was modified, and it is replaced by
  735. ;; One newfound tag. Splice the new tag into the
  736. ;; position of the old tag.
  737. ;; Do the splice.
  738. (semantic-edits-splice-replace (car tags) (car newf-tags))
  739. ;; Add this tag to our list of changed toksns
  740. (setq changed-tags (cons (car tags) changed-tags))
  741. ;; Debug
  742. (when semantic-edits-verbose-flag
  743. (message "Update Tag Table: %s"
  744. (semantic-format-tag-name (car tags) nil t)))
  745. ;; Flush change regardless of above if statement.
  746. )
  747. ;;;; Some unhandled case.
  748. ((semantic-parse-changes-failed "Don't know what to do")))
  749. ;; We got this far, and we didn't flag a full reparse.
  750. ;; Clear out this change group.
  751. (while change-group
  752. (semantic-edits-flush-change (car change-group))
  753. (setq change-group (cdr change-group)))
  754. ;; Don't increment change here because an earlier loop
  755. ;; created change-groups.
  756. (setq parse-start nil)
  757. )
  758. ;; Mark that we are done with this glop
  759. (semantic-parse-tree-set-up-to-date)
  760. ;; Return the list of tags that changed. The caller will
  761. ;; use this information to call hooks which can fix themselves.
  762. changed-tags))
  763. ;; Make it the default changes parser
  764. ;;;###autoload
  765. (defalias 'semantic-parse-changes-default
  766. 'semantic-edits-incremental-parser)
  767. ;;; Cache Splicing
  768. ;;
  769. ;; The incremental parser depends on the ability to parse up sections
  770. ;; of the file, and splice the results back into the cache. There are
  771. ;; three types of splices. A REPLACE, an ADD, and a REMOVE. REPLACE
  772. ;; is one of the simpler cases, as the starting cons cell representing
  773. ;; the old tag can be used to auto-splice in. ADD and REMOVE
  774. ;; require scanning the cache to find the correct location so that the
  775. ;; list can be fiddled.
  776. (defun semantic-edits-splice-remove (oldtags parent cachelist)
  777. "Remove OLDTAGS from PARENT's CACHELIST.
  778. OLDTAGS are tags in the current buffer, preferably linked
  779. together also in CACHELIST.
  780. PARENT is the parent tag containing OLDTAGS.
  781. CACHELIST should be the children from PARENT, but may be
  782. pre-positioned to a convenient location."
  783. (let* ((first (car oldtags))
  784. (last (nth (1- (length oldtags)) oldtags))
  785. (chil (if parent
  786. (semantic-tag-components parent)
  787. semantic--buffer-cache))
  788. (cachestart cachelist)
  789. (cacheend nil)
  790. )
  791. ;; First in child list?
  792. (if (eq first (car chil))
  793. ;; First tags in the cache are being deleted.
  794. (progn
  795. (when semantic-edits-verbose-flag
  796. (message "To Remove First Tag: (%s)"
  797. (semantic-format-tag-name first)))
  798. ;; Find the last tag
  799. (setq cacheend chil)
  800. (while (and cacheend (not (eq last (car cacheend))))
  801. (setq cacheend (cdr cacheend)))
  802. ;; The spliceable part is after cacheend.. so move cacheend
  803. ;; one more tag.
  804. (setq cacheend (cdr cacheend))
  805. ;; Splice the found end tag into the cons cell
  806. ;; owned by the current top child.
  807. (setcar chil (car cacheend))
  808. (setcdr chil (cdr cacheend))
  809. (when (not cacheend)
  810. ;; No cacheend.. then the whole system is empty.
  811. ;; The best way to deal with that is to do a full
  812. ;; reparse
  813. (semantic-parse-changes-failed "Splice-remove failed. Empty buffer?")
  814. ))
  815. (when semantic-edits-verbose-flag
  816. (message "To Remove Middle Tag: (%s)"
  817. (semantic-format-tag-name first))))
  818. ;; Find in the cache the preceding tag
  819. (while (and cachestart (not (eq first (car (cdr cachestart)))))
  820. (setq cachestart (cdr cachestart)))
  821. ;; Find the last tag
  822. (setq cacheend cachestart)
  823. (while (and cacheend (not (eq last (car cacheend))))
  824. (setq cacheend (cdr cacheend)))
  825. ;; Splice the end position into the start position.
  826. ;; If there is no start, then this whole section is probably
  827. ;; gone.
  828. (if cachestart
  829. (setcdr cachestart (cdr cacheend))
  830. (semantic-parse-changes-failed "Splice-remove failed."))
  831. ;; Remove old overlays of these deleted tags
  832. (while oldtags
  833. (semantic--tag-unlink-from-buffer (car oldtags))
  834. (setq oldtags (cdr oldtags)))
  835. ))
  836. (defun semantic-edits-splice-insert (newtags parent cachelist)
  837. "Insert NEWTAGS into PARENT using CACHELIST.
  838. PARENT could be nil, in which case CACHELIST is the buffer cache
  839. which must be updated.
  840. CACHELIST must be searched to find where NEWTAGS are to be inserted.
  841. The positions of NEWTAGS must be synchronized with those in
  842. CACHELIST for this to work. Some routines pre-position CACHELIST at a
  843. convenient location, so use that."
  844. (let* ((start (semantic-tag-start (car newtags)))
  845. (newtagendcell (nthcdr (1- (length newtags)) newtags))
  846. (end (semantic-tag-end (car newtagendcell)))
  847. )
  848. (if (> (semantic-tag-start (car cachelist)) start)
  849. ;; We are at the beginning.
  850. (let* ((pc (if parent
  851. (semantic-tag-components parent)
  852. semantic--buffer-cache))
  853. (nc (cons (car pc) (cdr pc))) ; new cons cell.
  854. )
  855. ;; Splice the new cache cons cell onto the end of our list.
  856. (setcdr newtagendcell nc)
  857. ;; Set our list into parent.
  858. (setcar pc (car newtags))
  859. (setcdr pc (cdr newtags)))
  860. ;; We are at the end, or in the middle. Find our match first.
  861. (while (and (cdr cachelist)
  862. (> end (semantic-tag-start (car (cdr cachelist)))))
  863. (setq cachelist (cdr cachelist)))
  864. ;; Now splice into the list!
  865. (setcdr newtagendcell (cdr cachelist))
  866. (setcdr cachelist newtags))))
  867. (defun semantic-edits-splice-replace (oldtag newtag)
  868. "Replace OLDTAG with NEWTAG in the current cache.
  869. Do this by recycling OLDTAG's first CONS cell. This effectively
  870. causes the new tag to completely replace the old one.
  871. Make sure that all information in the overlay is transferred.
  872. It is presumed that OLDTAG and NEWTAG are both cooked.
  873. When this routine returns, OLDTAG is raw, and the data will be
  874. lost if not transferred into NEWTAG."
  875. (let* ((oo (semantic-tag-overlay oldtag))
  876. (o (semantic-tag-overlay newtag))
  877. (oo-props (semantic-overlay-properties oo)))
  878. (while oo-props
  879. (semantic-overlay-put o (car oo-props) (car (cdr oo-props)))
  880. (setq oo-props (cdr (cdr oo-props)))
  881. )
  882. ;; Free the old overlay(s)
  883. (semantic--tag-unlink-from-buffer oldtag)
  884. ;; Recover properties
  885. (semantic--tag-copy-properties oldtag newtag)
  886. ;; Splice into the main list.
  887. (setcdr oldtag (cdr newtag))
  888. (setcar oldtag (car newtag))
  889. ;; This important bit is because the CONS cell representing
  890. ;; OLDTAG is now pointing to NEWTAG, but the NEWTAG
  891. ;; cell is about to be abandoned. Here we update our overlay
  892. ;; to point at the updated state of the world.
  893. (semantic-overlay-put o 'semantic oldtag)
  894. ))
  895. (add-hook 'semantic-before-toplevel-cache-flush-hook
  896. #'semantic-edits-flush-changes)
  897. (provide 'semantic/edit)
  898. ;; Local variables:
  899. ;; generated-autoload-file: "loaddefs.el"
  900. ;; generated-autoload-load-name: "semantic/edit"
  901. ;; End:
  902. ;;; semantic/edit.el ends here