AdamNiederer/vue-mode

Indentation in script lang="ts" sections fails with emacs 27 nightly

garyo opened this issue · 5 comments

garyo commented

I'm using emacs 27 recent nightly. I've been using vue-mode with typescript for a while, and everything was fine until switching from an older emacs 27 (from sometime in spring 2019) to current HEAD.
Now, nothing indents with TAB. Indent is 0.

There's at least one problem I can find: typescript-indent-line in this emacs calls (widen), and vue-mode/mmm-mode have narrowed the buffer to the current sub-mode and they're not expecting it to get widened again.

But even after creating my own typescript-indent-line that doesn't call (widen) I still get no indentation, and indeed (syntax-ppss (point-at-bol)) returns (0 nil 2381 nil nil nil 0 nil nil nil nil) even in a deeply nested function in a narrowed vue buffer. That first number should be the indent level, not 0.

This could certainly be an mmm-mode issue rather than a vue-mode issue, but I figured I should start here.

Maybe a clue: if I modify the buffer and then do M-x normal-mode to reparse it, I get this error:

Assertion failed: (>= (cadr sgml--syntax-propertize-ppss) 0)

with this backtrace:

Debugger entered--Lisp error: (cl-assertion-failed ((>= (cadr sgml--syntax-propertize-ppss) 0) nil))
  cl--assertion-failed((>= (cadr sgml--syntax-propertize-ppss) 0))
  sgml-syntax-propertize(6186 6205)
  #f(compiled-function (elt) #<bytecode 0x22c1d45>)((vue-mode 6186 6205 nil))
  mapc(#f(compiled-function (elt) #<bytecode 0x22c1d45>) ((vue-mode 1 407 nil) (vue-html-mode 407 1142 #<overlay from 407 to 1142 in KeyframeGraph.vue>) (vue-mode 1142 1174 nil) (typescript-mode 1174 6186 #<overlay from 1174 to 6186 in KeyframeGraph.vue>) (vue-mode 6186 6205 nil) (css-mode 6205 6338 #<overlay from 6205 to 6338 in KeyframeGraph.vue>) (vue-mode 6338 6347 nil)))
  mmm-syntax-propertize-function(1 6347)
  syntax-propertize(6347)
  mmm-apply-all()
  mmm-mode-on()
  mmm-mode-on-maybe()
  mmm-run-major-mode-hook()
  mmm-check-changed-buffers()

(but I note that if I globally turn off font-lock-mode, I don't see that error when invoking normal-mode so maybe that's a different issue.)

I note that in my file the region (6186 6205) is from just before the </script> tag to just after the <style> tag.

In a plain typescript-mode buffer, indent works fine.

garyo commented

Emacs bug report submitted: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=37751
although I'm still not 100% certain whether it's an Emacs 27 bug or a vue-mode bug. Some interaction, most likely.

Hey, thanks for the detailed bug report! vue-mode does narrow the buffer to prevent remote parts of the file from interfering with each mode's indent function - not narrowing can cause quite a few issues with older indent functions. However, removing the narrowing for the sake of debugging this should be safe.

The latter issue looks like it might be out of my hands - I'm limited to simply telling mmm-mode that I want the toplevel mode to be html-mode, and it fontifies that portion of the buffer as it sees fit.

As for the former, I also have very little control over the syntax properties of each submode, but I'd be happy to hack in one which works while we figure out what's going on. It could be anywhere in my mode, typescript-mode, mmm-mode, or Emacs, although I'd be most suspicious of the first three.

Have you been able to get any other modes (js-mode, scss-mode, etc) to break in this way?

garyo commented

The widen thing may be an issue, but it's not the core one (as you suspected) -- if I use vue-mode with only the Typescript part of the buffer (delete everything else) the bug still happens.

Since the emacs commit that caused this (emacs-mirror/emacs@0b3982b) uses syntax-ppss-table in more situations, I suspect it's related to caching incorrectly when switching major modes or something. There is a cache-flushing function syntax-ppss-flush-cache but I'm not sure how it would be hooked in.

The problem does not happen in a plain typescript-mode buffer. I haven't tried the modes you mention, I will today. But it seems likely to be related to whatever mmm-mode does to switch modes (just my best guess).

garyo commented

Yes, js-mode within vue-mode breaks in the same way, as does scss-mode. No indentation in either one.
But the main HTML mode within vue-mode is fine indentation-wise. It's only the sub-modes that show the problem.

garyo commented

Most recent mmm-mode has a fix for this. Closing.