]> git.eshelyaron.com Git - emacs.git/commit
Indent JSX as parsed in a JS context
authorJackson Ray Hamilton <jackson@jacksonrayhamilton.com>
Sat, 23 Mar 2019 21:22:35 +0000 (14:22 -0700)
committerJackson Ray Hamilton <jackson@jacksonrayhamilton.com>
Tue, 9 Apr 2019 05:48:22 +0000 (22:48 -0700)
commit1a1ef2851844a9ae2edcfe0346fc457e90c24bc7
treea4ed2aba89154761ea3a80066d11fee820d8f683
parent2bedd23358d2d7378eec78d526ba1435d3b4d122
Indent JSX as parsed in a JS context

Fixes the following issues (and re-fixes indentation issues initially
fixed but later re-broken by previous commits in the process of adding
comprehensive JSX support):

- https://github.com/mooz/js2-mode/issues/389#issuecomment-390766873
- https://github.com/mooz/js2-mode/issues/482
- Bug#32158
- https://github.com/mooz/js2-mode/issues/462

Previously, we delegated to sgml-mode functions for JSX indentation.
However, there were some problems with this approach:

- sgml-mode does not anticipate tags inside attributes when indenting,
  which compromises JSX indentation inside JSXExpressionContainers
  inside JSXAttributes.

- In previous iterations to provide comprehensive JSX support, it
  proved tedious to disambiguate “<” and “>” as JS inequality
  operators and arrow functions from opening and closing angle
  brackets as part of SGML tags.  That code evolved into a more
  complete JSX parsing implementation for syntax-propertize rules for
  font-locking, discarding the superfluous “<”/“>” disambiguation in
  anticipation of using the improved JSX analysis for indentation.

- Using sgml-mode functions, we controlled JSX indentation using SGML
  variables.  However, JSX is a different thing than SGML; referencing
  SGML in JS was a leaky abstraction.

To resolve these issues, use the text properties added by the JSX
syntax-propertize code to determine the boundaries of various aspects
of JSX syntax, and reimplement the sgml-mode indentation code in
js-mode with better respect to JSX indentation conventions.

* lisp/progmodes/js.el (js-jsx-attribute-offset): New variable to
provide a way for users to still control JSX attribute offsets as they
could with sgml-attribute-offset before.  The value of this feature is
dubious IMO, but it’s trivial to keep it, so let’s do it just in case.

(js-jsx--goto-outermost-enclosing-curly): New function.

(js-jsx--enclosing-tag-pos): Refactor to be unbounded by curlies, so
this function can be used to find JSXExpressionContainers within JSX.
Fix bug where an enclosing JSXElement couldn’t be found when point was
at the start of its JSXClosingElement.  Return the JSXClosingElement’s
position as well, so the JSXClosingElement can be indentified when
indenting and be indented like the matching JSXOpeningElement.

(js-jsx--at-enclosing-tag-child-p): js-jsx--enclosing-tag-pos now
returns a list rather than a cons, so retrieve the JSXOpeningElement’s
end position from a list.

(js-jsx--context, js-jsx--indenting): New function and variable.
(js-jsx--indentation): New function replacing the prior
js-jsx--indent* functions and js-jsx-indent-line’s implementation.
Use the JSX parsing performed in a JS context to more accurately
calculate JSX indentation than by delegating to sgml-mode functions.
(js--proper-indentation): Use js-jsx--indentation as yet another type
of indentation.
(js-jsx--as-sgml, js-jsx--outermost-enclosing-tag-pos)
(js-jsx--indentation-type, js-jsx--indent-line-in-expression)
(js-jsx--indent-n+1th-line): Remove obsolete functions.

(js-jsx-indent-line): Refactor nearly-obsolete function to behave the
same as it usually would before these changes, without respect to the
binding of js-jsx-syntax.

(js-jsx-mode): Remove obsolete documentation about the use of SGML
variables to control indentation, and don’t bind indent-line-function
any more, because it is no longer necessary given the new
implementation of js-jsx-indent-line.
lisp/progmodes/js.el