We add a symbol property 'elisp-scope-variable-spec', which
holds a specification for the values of a variable with that
property. For example, (put 'foo '(symbol . face)) says
that the value of variable 'foo' is a face name.
This allows elisp-scope.el to analyze forms such as
(setq foo 'bar) and (let ((foo 'bar)) ...) more accurately.
This is also used for analyzing macros that let-bind (one of)
their arguments to a specific special variable, such as
'with-connection-local-application-variables'.
We initially add this new property to some common variables.
* lisp/emacs-lisp/elisp-scope.el: Add
'elisp-scope-variable-spec' property to
'coding-system-for-read/write' and 'major-mode'.
(elisp-scope--variable-spec): New defsubst.
(elisp-scope--let-1, elisp-scope-let*, elisp-scope-setq):
Use it.
* test/lisp/progmodes/elisp-mode-resources/semantic-highlighting.el:
Add test form.
Replace the use of 'elisp-scope-face(-1)' for analyzing face
specifications with 'elisp-scope-1' calls with an
appropriate OUTSPEC argument. This allows us to analyze
face specifications even when they are not passed directly
to relevant functions, but rather appear in a tail position
of a form that evaluates to a face specification.
* lisp/emacs-lisp/elisp-scope.el
(elisp-scope--match-spec-to-arg): Add new 'face' spec.
Use it instead of...
(elisp-scope-face, elisp-scope-face-1): ...these functions.
Remove them, no longer used.
* test/lisp/progmodes/elisp-mode-resources/semantic-highlighting.el:
Add test.
So far, 'scope-elisp-analyze-form' would disable
'read-symbol-shorthands' while reading a source form in
order to obtain the "original" length of symbols and pass
that length to the callback called for each analyzed symbol.
However, 'scope-elisp-analyze-form' could report an
incorrect length when a symbol was written with redundant
escaping (e.g. 'f\oo'). Moreover, disabling
'read-symbol-shorthands' breaks macro-expansion during
analysis, because macros may expect "expanded" symbols,
without shorthands.
In this commit we address these issues by leaving
'scope-elisp-analyze-form' enabled (so we get expended
symbols for macro-expansion) and recovering the original
length lazily in the callback, if needed, by going to the
beginning of the symbol and searching forward for its end.
* lisp/emacs-lisp/elisp-scope.el (elisp-scope--report):
Replace LEN argument with SYM, the analyzed symbol itself.
Adapt all callers.
(elisp-scope-analyze-form): Cease let-binding
'read-symbol-shorthands' to nil while reading. Wrap
analysis in 'save-excursion' when reading from current
buffer. Update docstring.
* lisp/progmodes/elisp-mode.el (elisp-local-references)
(elisp-fontify-symbol): Obtain symbol length from buffer.
* test/lisp/progmodes/elisp-mode-resources/semantic-highlighting.el:
Add test that incorporates 'read-symbol-shorthands'.
* test/lisp/progmodes/elisp-mode-tests.el (elisp-test-font-lock):
Set up 'read-symbol-shorthands' in test file.
Use argument specs to analyze complex widget types.
* lisp/emacs-lisp/elisp-scope.el (elisp-scope-widget-type)
(elisp-scope-widget-type-1)
(elisp-scope-widget-type-keyword-arguments)
(elisp-scope-widget-type-arguments)
(elisp-scope-widget-type-arguments-1): Delete, no longer used.
(custom-declare-variable, define-widget): Simplify analyzers.
(elisp-scope--match-spec-to-arg): Add new 'list', 'and', and
'plist-and-then' parametric specs, and add 'widget-type' as a
new recursive spec.
* test/lisp/progmodes/elisp-mode-resources/semantic-highlighting.el
Add test.
Rename a couple of faces to solidify the convention that the
face name 'elisp-foo' implies "references to foo", not "foo
definitions". For definitions we use 'elisp-deffoo' if foo is
only one word, or 'elisp-bar-baz-definition' otherwise.
* lisp/progmodes/elisp-mode.el (elisp-function-reference):
Rename to 'elisp-function'.
(elisp-macro-call): Rename to 'elisp-macro'.
(elisp-non-local-exit):
(elisp-unknown-call):
(elisp-special-form):
* lisp/emacs-lisp/elisp-scope.el:
* test/lisp/progmodes/elisp-mode-resources/semantic-highlighting.el:
Update references to renamed faces.
* lisp/emacs-lisp/elisp-scope.el (elisp-scope-if-let): Fix
handling of a plain symbol as one the bindings in an
'if-let*' form, as in (if-let* (foo) 'bar).
* test/lisp/progmodes/elisp-mode-resources/semantic-highlighting.el:
Test it.
* test/lisp/progmodes/elisp-mode-resources/semantic-highlighting.el:
Add test form with 'when-let*'.
* test/lisp/progmodes/elisp-mode-tests.el (elisp-test-font-lock):
Trust temporary test buffer.
* test/lisp/progmodes/elisp-mode-tests.el
(elisp-test-font-lock): New test.
* test/lisp/progmodes/elisp-mode-resources/semantic-highlighting.el:
New resource file.
* lisp/emacs-lisp/lisp-mode.el (lisp--local-defform-body-p): Preserve
the point.
* test/lisp/progmodes/elisp-mode-resources/flet.erts: Add corresponding
test example (bug#9622).
* doc/lispref/keymaps.texi (Changing Key Bindings): Document
define-keymap and defvar-keymap.
* lisp/subr.el (define-keymap): New function.
(define-keymap--define): New function.
(defvar-keymap): New macro.
* lisp/emacs-lisp/lisp-mode.el (lisp-indent--defvar-keymap): New
function.
(lisp-indent-function): Use it to indent defvar-keymap.
The new name fits better in the family of variables that affect
the Lisp reader.
Suggested-by: Po Lu <luangruo@yahoo.com>
* doc/lispref/symbols.texi (Shorthands): Mention read-symbol-shorthands
* lisp/shorthands.el (hack-read-symbol-shorthands)
(hack-read-symbol-shorthands)
(shorthands-font-lock-shorthands): Use read-symbol-shorthands
* lisp/progmodes/elisp-mode.el (elisp--completion-local-symbols)
(elisp--completion-local-symbols)
(elisp-shorthands): Use read-symbol-shorthands
* src/lread.c:
(syms_of_lread): Define Vread_symbol_shorthands
(oblookup_considering_shorthand): Use Vread_symbol_shorthands.
* test/lisp/progmodes/elisp-mode-tests.el (elisp-shorthand-read-buffer):
(elisp-shorthand-read-from-string): Use read-symbol-shorthands
* test/lisp/progmodes/elisp-mode-resources/simple-shorthand-test.el
Use new symbol name read-symbol-shorthands.
Only the shorthanded prefix is font-locked. This allows the remainder
of the font-lock logic to subsist (e.g. for macro-defining symbols).
* lisp/shorthands.el (cl-lib): Require it when compiling.
(elisp-shorthand-font-lock-face): New face.
(shorthands--mismatch-from-end): New helper.
(shorthands-font-lock-shorthands): New helper.
* test/lisp/progmodes/elisp-mode-resources/simple-shorthand-test.el:
Add some dummy test code.