swift-emacs / swift-mode

Emacs support for Apple's Swift programming language.
GNU General Public License v3.0
372 stars 47 forks source link

Emacs hangs when using unknown keywords #125

Closed proger closed 8 years ago

proger commented 8 years ago

To reproduce, type the following to the empty buffer:

indirect enum Tree {
         case Node(Int, Tree)
         case Leaf(Int)
         }

Note that swift-mode doesn't currently support indirect (#96)

After pressing } you will observe Emacs eat 100% of the cpu (so don't do it when on battery power!). It's hard to make it stop using C-g (tried setting debug-on-quit too), sending USR2 to the process yields this backtrace:

Debugger entered--Lisp error: (quit)
  looking-at("\\([\n     ]\\|.\\)+?\\(where.*[,]\\|:\\)")
  #[0 "`\303`[!\210\211\304 V\203\305 \203\306\2023`Sf\307=\203%\310u\210\311\2023`Sf\312=\2034\310u\210\313\2023`Sf\314=\203C\310u\210\315\2023`Sf\316=\203\\\310u\210\317\320!\203X\321\2023\322\2023\317\323`\324Z\325#\203n\326\224b\210\323\2023`Sf\327=\203\207\310u\210\330\331!\203\203\332\2023\333\2023\317\334`\324Z\325#\203\245\326\224b\210\317\335\336\325#\203\241\337\2023\340\2023\317\34!`\342Z\325#\203\273\326\224b\210\343\326!\2023\317  `\344Z\325#\203\315\336\224b\210\345\2023\317\n`\344Z\325#\203\337\326\224b\210\346\2023\317\347`\342Z\325#\203\361\326\224b\210\350\2023\317\351`\352Z\325#\203\326\224b\210\353\2023\354 \211\350\232\203\330\355!\203\350\2021\356\2021\211\357\232\2030\317\360\361 \325#\203,\362\2021\357\2021\211\262\207" [swift-mode--type-decl-keywords swift-smie--decl-specifier-regexp swift-smie--access-modifier-regexp forward-comment line-end-position swift-smie--implicit-semi-p ";" 123 -1 "{" 125 "}" 44 "," 58 looking-back "\\(case[\n   ][^:{;]+\\|default[\n   ]*\\)" "case-:" ":" "->" 2 t 0 60 looking-at "<[[:upper:]]" "<T" "<" ">[?!]?" "[[:space:]]" 1 ">" "T>" regexp-opt 9 match-string-no-properties 8 "DECSPEC" "ACCESSMOD" "\\<default\\>" "case" "else if" 7 "elseif" smie-default-backward-token "\\([\n  ]\\|.\\)+?\\(where.*[,]\\|:\\)" "ecase" "else" "\\(guard.*\\)" line-beginning-position ...] 6 "\n\n(fn)"]()
\"A\211\204X\310G!\203$\311\312\313\314\315\316\317\301!\320\"\321\322%D\323\312\313\324\325\316\317
                                                                                                    !\326\"\327\330%\311EDC\217\210`=\203$\331\332\333`D\"\210\202$\303!\247\204t\302!\247\204l\334\335\336C\"\210\211B\262\202$\203\212\303!\302@!W\203\212A\262\202t\204\266\304\242\203\242\302!\247\203\242\211B\262\202$\331\332\302!\206\253\333`Eb\210\"\210\202$\211\203\313\303!\302@!U\203\313A\262\203\336\302!\247\203#B\262\202#\302!\247\204\361\331\332\307`E\"\210\202#\337!\204\377B\262\202#\211\203 \337@!\203 \331\332\302!\206\333`Eb\210\"\210\202#\211\262\210\266\203\2051\304\307\240\210\202\207" [#[0 "`\303`[!\210\211\304 V\203\305 \203\306\2023`Sf\307=\203%\310u\210\311\2023`Sf\312=\2034\310u\210\313\2023`Sf\314=\203C\310u\210\315\2023`Sf\316=\203\\\310u\210\317\320!\203X\321\2023\322\2023\317\323`\324Z\325#\203n\326\224b\210\323\2023`Sf\327=\203\207\310u\210\330\331!\203\203\332\2023\333\2023\317\334`\324Z\325#\203\245\326\224b\210\317\335\336\325#\203\241\337\2023\340\2023\317\34!`\342Z\325#\203\273\326\224b\210\343\326!\2023\317   `\344Z\325#\203\315\336\224b\210\345\2023\317\n`\344Z\325#\203\337\326\224b\210\346\2023\317\347`\342Z\325#\203\361\326\224b\210\350\2023\317\351`\352Z\325#\203\326\224b\210\353\2023\354 \211\350\232\203\330\355!\203\350\2021\356\2021\211\357\232\2030\317\360\361 \325#\203,\362\2021\357\2021\211\262\207" [swift-mode--type-decl-keywords swift-smie--decl-specifier-regexp swift-smie--access-modifier-regexp forward-comment line-end-position swift-smie--implicit-semi-p ";" 123 -1 "{" 125 "}" 44 "," 58 looking-back "\\(case[\n   ][^:{;]+\\|default[\n   ]*\\)" "case-:" ":" "->" 2 t 0 60 looking-at "<[[:upper:]]" "<T" "<" ">[?!]?" "[[:space:]]" 1 ">" "T>" regexp-opt 9 match-string-no-properties 8 "DECSPEC" "ACCESSMOD" "\\<default\\>" "case" "else if" 7 "elseif" smie-default-backward-token "\\([\n  ]\\|.\\)+?\\(where.*[,]\\|:\\)" "ecase" "else" "\\(guard.*\\)" line-beginning-position ...] 6 "\n\n(fn)"] #[256 "\211\204\300\262\301[!\207" [1 forward-sexp] 3 2388086 "^p"] #<subr car> #[257 "\211A@\207" [] 2 1634943] (nil) smie-grammar assoc nil zerop err funcall make-byte-code 0 "\300\301!\210\302\207" vconcat vector [1 nil] 2 "\n\n(fn)" scan-error 257 "\3018`X\203\3028\202\211\300b\210\303\304\305\306\211W\203%\307\202&\310\\\"E\"\207" [2 3 throw return t buffer-substring-no-properties -1 1] 12 "\n\n(fn ERR)" throw return t signal cl-assertion-failed (numberp (funcall op-forw toklevels)) smie--associative-p] 14 "\n\n(fn)"]()
\"A\211\204X\310G!\203$\311\312\313\314\315\316\317\301!\320\"\321\322%D\323\312\313\324\325\316\317
                                                                                                    !\326\"\327\330%\311EDC\217\210`=\203$\331\332\333`D\"\210\202$\303!\247\204t\302!\247\204l\334\335\336C\"\210\211B\262\202$\203\212\303!\302@!W\203\212A\262\202t\204\266\304\242\203\242\302!\247\203\242\211B\262\202$\331\332\302!\206\253\333`Eb\210\"\210\202$\211\203\313\303!\302@!U\203\313A\262\203\336\302!\247\203#B\262\202#\302!\247\204\361\331\332\307`E\"\210\202#\337!\204\377B\262\202#\211\203 \337@!\203 \331\332\302!\206\333`Eb\210\"\210\202#\211\262\210\266\203\2051\304\307\240\210\202\207" [#[0 "`\303`[!\210\211\304 V\203\305 \203\306\2023`Sf\307=\203%\310u\210\311\2023`Sf\312=\2034\310u\210\313\2023`Sf\314=\203C\310u\210\315\2023`Sf\316=\203\\\310u\210\317\320!\203X\321\2023\322\2023\317\323`\324Z\325#\203n\326\224b\210\323\2023`Sf\327=\203\207\310u\210\330\331!\203\203\332\2023\333\2023\317\334`\324Z\325#\203\245\326\224b\210\317\335\336\325#\203\241\337\2023\340\2023\317\34!`\342Z\325#\203\273\326\224b\210\343\326!\2023\317   `\344Z\325#\203\315\336\224b\210\345\2023\317\n`\344Z\325#\203\337\326\224b\210\346\2023\317\347`\342Z\325#\203\361\326\224b\210\350\2023\317\351`\352Z\325#\203\326\224b\210\353\2023\354 \211\350\232\203\330\355!\203\350\2021\356\2021\211\357\232\2030\317\360\361 \325#\203,\362\2021\357\2021\211\262\207" [swift-mode--type-decl-keywords swift-smie--decl-specifier-regexp swift-smie--access-modifier-regexp forward-comment line-end-position swift-smie--implicit-semi-p ";" 123 -1 "{" 125 "}" 44 "," 58 looking-back "\\(case[\n   ][^:{;]+\\|default[\n   ]*\\)" "case-:" ":" "->" 2 t 0 60 looking-at "<[[:upper:]]" "<T" "<" ">[?!]?" "[[:space:]]" 1 ">" "T>" regexp-opt 9 match-string-no-properties 8 "DECSPEC" "ACCESSMOD" "\\<default\\>" "case" "else if" 7 "elseif" smie-default-backward-token "\\([\n  ]\\|.\\)+?\\(where.*[,]\\|:\\)" "ecase" "else" "\\(guard.*\\)" line-beginning-position ...] 6 "\n\n(fn)"] #[256 "\211\204\300\262\301[!\207" [1 forward-sexp] 3 2388086 "^p"] #<subr car> #[257 "\211A@\207" [] 2 1634943] (nil) smie-grammar assoc nil zerop err funcall make-byte-code 0 "\300\301!\210\302\207" vconcat vector [1 nil] 2 "\n\n(fn)" scan-error 257 "\3018`X\203\3028\202\211\300b\210\303\304\305\306\211W\203%\307\202&\310\\\"E\"\207" [2 3 throw return t buffer-substring-no-properties -1 1] 12 "\n\n(fn ERR)" throw return t signal cl-assertion-failed (numberp (funcall op-forw toklevels)) smie--associative-p] 14 "\n\n(fn)"])
  smie-next-sexp(#[0 "`\303`[!\210\211\304 V\203\305 \203\306\2023`Sf\307=\203%\310u\210\311\2023`Sf\312=\2034\310u\210\313\2023`Sf\314=\203C\310u\210\315\2023`Sf\316=\203\\\310u\210\317\320!\203X\321\2023\322\2023\317\323`\324Z\325#\203n\326\224b\210\323\2023`Sf\327=\203\207\310u\210\330\331!\203\203\332\2023\333\2023\317\334`\324Z\325#\203\245\326\224b\210\317\335\336\325#\203\241\337\2023\340\2023\317\34!`\342Z\325#\203\273\326\224b\210\343\326!\2023\317   `\344Z\325#\203\315\336\224b\210\345\2023\317\n`\344Z\325#\203\337\326\224b\210\346\2023\317\347`\342Z\325#\203\361\326\224b\210\350\2023\317\351`\352Z\325#\203\326\224b\210\353\2023\354 \211\350\232\203\330\355!\203\350\2021\356\2021\211\357\232\2030\317\360\361 \325#\203,\362\2021\357\2021\211\262\207" [swift-mode--type-decl-keywords swift-smie--decl-specifier-regexp swift-smie--access-modifier-regexp forward-comment line-end-position swift-smie--implicit-semi-p ";" 123 -1 "{" 125 "}" 44 "," 58 looking-back "\\(case[\n   ][^:{;]+\\|default[\n   ]*\\)" "case-:" ":" "->" 2 t 0 60 looking-at "<[[:upper:]]" "<T" "<" ">[?!]?" "[[:space:]]" 1 ">" "T>" regexp-opt 9 match-string-no-properties 8 "DECSPEC" "ACCESSMOD" "\\<default\\>" "case" "else if" 7 "elseif" smie-default-backward-token "\\([\n  ]\\|.\\)+?\\(where.*[,]\\|:\\)" "ecase" "else" "\\(guard.*\\)" line-beginning-position ...] 6 "\n\n(fn)"] #[256 "\211\204\300\262\301[!\207" [1 forward-sexp] 3 2388086 "^p"] #<subr car> #[257 "\211A@\207" [] 2 1634943] halfsexp)
  smie-backward-sexp(halfsexp)
  #[0 "\306 \211\205\24\204 \211@\203\307\202\310\311A@ \"8\247?\205\243\211@\203C\312\313!`@?\205>\n \210A@\3108B
                                                                                                                  \235`E\266\202\202\216\314\313!A@@\203|\310\311   \"8\3108\311    \"A@\247\205w=\205wA@b\210`\f \210\315`E\262\266\203\202\214`\f \210\3108B
                                                                                                                          \235`E\26\3108\3168A@\3108@?\257\241\262\207" [smie-blink-matching-inners smie-grammar smie-backward-token-function smie-closer-alist smie-forward-token-function smie--matching-block-data-cache smie--opener/closer-at-point 1 2 assoc smie-forward-sexp halfsexp smie-backward-sexp t 3] 10 "\n\n(fn)"]()
  funcall(#[0 "\306 \211\205\24\204 \211@\203\307\202\310\311A@ \"8\247?\205\243\211@\203C\312\313!`@?\205>\n \210A@\3108B
                                                                                                                          \235`E\266\202\202\216\314\313!A@@\203|\310\311   \"8\3108\311    \"A@\247\205w=\205wA@b\210`\f \210\315`E\262\266\203\202\214`\f \210\3108B
                                                                                                                                  \\3108\3168A@\3108@?\257\241\262\207" [smie-blink-matching-inners smie-grammar smie-backward-token-function smie-closer-alist smie-forward-token-function smie--matching-block-data-cache smie--opener/closer-at-point 1 2 assoc smie-forward-sexp halfsexp smie-backward-sexp t 3] 10 "\n\n(fn)"])
  smie--matching-block-data(#[128 "\301\302\300!\"\207" [show-paren-data-function apply default-value] 4 "\n\n(fn &rest ARGS)"])
  apply(smie--matching-block-data #[128 "\301\302\300!\"\207" [show-paren-data-function apply default-value] 4 "\n\n(fn &rest ARGS)"] nil)
  #[128 "\300\301\302#\207" [apply smie--matching-block-data #[128 "\301\302\300!\"\207" [show-paren-data-function apply default-value] 4 "\n\n(fn &rest ARGS)"] nil] 5 nil]()
  show-paren-function()
  apply(show-paren-function nil)
  byte-code("r\30\302\303H\"\210)\301\207" [timer apply 5 6] 4)
  timer-event-handler([t 0 0 125000 t show-paren-function nil idle 0])

I've captured a profile for master code too: https://gist.github.com/proger/56cc097bd9f47a4bafc7 (started with an empty buffer, turned it on, triggered the bug, let it run for some time while reading about USR2 :) )

proger commented 8 years ago

Out of curiosity, I've tried simplify_smie which doesn't exhibit that problem, but indents code like:

indirect enum Tree {
case Node(Int, Tree)
case Leaf(Int)
         }
taku0 commented 8 years ago

I have updated my personal branch to support Swift 2.1 https://github.com/taku0/swift-mode/tree/swift-2-indentation. This branch supports indirect keyword and other Swift 2.1 features.

tautologico commented 8 years ago

Why aren't @taku0's changes integrated? This mode is almost useless right now because of this issue, and things will get worse when Swift 3 is released.

krzysztof-magosa commented 8 years ago

Anybody here? Or it's dead project?

taku0 commented 8 years ago

I made a fork with a new indentation engine for Swift 3. https://github.com/taku0/swift3-mode

Apple also made their own swift-mode.el but seems still in very early stage for now. https://github.com/apple/swift/blob/master/utils/swift-mode.el

taku0 commented 8 years ago

Fixed by the new indentation logic.