branch: externals/phps-mode commit b6cf3a4564a784766fc5fb49b69ac8e529e369b8 Author: Christian Johansson <christ...@cvj.se> Commit: Christian Johansson <christ...@cvj.se>
Started on new algorithm for indentation calculation based on stack Passes tests for complex if expressions --- phps-mode-functions.el | 127 ++++++++++++++++++++++++++++++-------------- phps-mode-test-functions.el | 50 ++++++++++------- 2 files changed, 119 insertions(+), 58 deletions(-) diff --git a/phps-mode-functions.el b/phps-mode-functions.el index 8723980..ce834d0 100644 --- a/phps-mode-functions.el +++ b/phps-mode-functions.el @@ -88,7 +88,9 @@ (token-start-line-number 0) (token-end-line-number) (tokens (nreverse phps-mode-lexer-tokens)) - (nesting-stack '())) + (nesting-stack nil) + (changed-nesting-stack-in-line nil) + (after-class-declaration nil)) (push `(END_PARSE ,(point-max) . ,(point-max)) tokens) @@ -298,8 +300,13 @@ (setq in-class-declaration nil) (setq in-class-declaration-level 0) (when first-token-on-line + (setq after-class-declaration t) (setq first-token-is-nesting-increase nil) - (setq first-token-is-nesting-decrease t))) + (setq first-token-is-nesting-decrease t)) + + (setq nesting-end (+ round-bracket-level square-bracket-level curly-bracket-level alternative-control-structure-level inline-control-structure-level in-assignment-level in-class-declaration-level)) + + ) (when first-token-on-line (setq in-class-declaration-level 1))) (when (equal token 'T_CLASS) @@ -314,16 +321,16 @@ ;; Line logic (progn - ;; Calculate indentation level at end of line + ;; Calculate nesting (setq nesting-end (+ round-bracket-level square-bracket-level curly-bracket-level alternative-control-structure-level inline-control-structure-level in-assignment-level in-class-declaration-level)) - ;; Is line ending indentation lesser than line beginning indentation? + ;; Has nesting increased? (when (and nesting-stack - (<= nesting-end (car nesting-stack))) + (<= nesting-end (car (car nesting-stack)))) (when phps-mode-functions-verbose - (message "Popping %s from nesting-stack since %s is lesser" (car nesting-stack) nesting-end)) - + ;; (message "\nPopping %s from nesting-stack since %s is lesser or equal to %s, next value is: %s\n" (car nesting-stack) nesting-end (car (car nesting-stack)) (nth 1 nesting-stack)) + ) (pop nesting-stack) ;; Decrement column @@ -337,30 +344,43 @@ (when (< column-level 0) (setq column-level 0))) - ;; Start indentation might differ from ending indentation in cases like } else { + + ;; ;; Start indentation might differ from ending indentation in cases like } else { (setq column-level-start column-level) - (when (= nesting-end nesting-start) - ;; Handle cases like: } else { - (when (and first-token-is-nesting-decrease - (not first-token-is-nesting-increase) - (> column-level-start 0)) - (setq column-level-start (1- column-level-start))) + ;; (when (= nesting-end nesting-start) - ;; Handle cases like if (blaha)\n echo 'blaha'; - (when (and first-token-is-nesting-increase - (not first-token-is-nesting-decrease)) - (setq column-level-start (1+ column-level-start)))) + ;; (when (and after-class-declaration + ;; (> column-level-start 0)) + ;; (setq column-level-start (1- column-level-start))) + + ;; ;; ;; Handle cases like: } else { + ;; ;; (when (and first-token-is-nesting-decrease + ;; ;; (not first-token-is-nesting-increase) + ;; ;; (> column-level-start 0)) + ;; ;; (setq column-level-start (1- column-level-start))) + + ;; ;; ;; Handle cases like if (blaha)\n echo 'blaha'; + ;; ;; (when (and first-token-is-nesting-increase + ;; ;; (not first-token-is-nesting-decrease)) + ;; ;; (setq column-level-start (1+ column-level-start))) + + ;; ) (when phps-mode-functions-verbose (message "Process line ending. nesting: %s-%s, line-number: %s-%s, indent: %s.%s, token: %s" nesting-start nesting-end token-start-line-number token-end-line-number column-level-start tuning-level token)) ;; (message "new line %s or last token at %s, %s %s.%s (%s - %s) = %s %s %s %s %s [%s %s] %s %s %s" token-start-line-number token next-token column-level tuning-level nesting-start nesting-end round-bracket-level square-bracket-level curly-bracket-level alternative-control-structure-level inline-control-structure-level first-token-is-nesting-decrease first-token-is-nesting-increase in-assignment in-assignment-level in-class-declaration-level) - ;; Put indent-level to hash-table (when (> token-start-line-number 0) + + ;; Save line indentation (puthash token-start-line-number `(,column-level-start ,tuning-level) line-indents)) + ;; TODO Handle case were current line number is more than 1 above last line number and then fill lines in-between with indentation + + + ;; Does token span over several lines? (when (> token-end-line-number token-start-line-number) ;; (message "Token %s starts at %s and ends at %s indent %s %s" next-token token-start-line-number token-end-line-number column-level tuning-level) @@ -378,27 +398,39 @@ ;; Rest tuning-level used for comments (setq tuning-level 0)) - ;; Is line ending indentation higher than line beginning indentation? - (when (> nesting-end nesting-start) - - ;; Increase indentation - (if allow-custom-column-increment - (progn - (setq column-level (+ column-level (- nesting-end nesting-start))) - (setq allow-custom-column-increment nil)) - (setq column-level (1+ column-level))) - (when phps-mode-functions-verbose - (message "Pushing %s to nesting-stack since is lesser than %s" nesting-start nesting-end)) - (push nesting-start nesting-stack)) + ;; Has nesting decreased? + ;; If nesting-end > 0 AND (!nesting-stack OR nesting-end > nesting-stack-end), push stack, increase indent + (when (and (> nesting-end 0) + (or (not nesting-stack) + (> nesting-end (car (cdr (car nesting-stack)))))) + (let ((nesting-stack-end 0)) + (when nesting-stack + (setq nesting-stack-end (car (cdr (car nesting-stack))))) - ;; When nesting decreases but ends with a nesting increase, increase indent by one - (when (and (< nesting-end nesting-start) - line-contained-nesting-increase) - (setq column-level (1+ column-level)) - (when phps-mode-functions-verbose - (message "Pushing %s to nesting-stack since is lesser than %s" nesting-start nesting-end)) - (push nesting-start nesting-stack)) + ;; Increase indentation + (if allow-custom-column-increment + (progn + (setq column-level (+ column-level (- nesting-end nesting-start))) + (setq allow-custom-column-increment nil)) + (setq column-level (1+ column-level))) + + (when phps-mode-functions-verbose + ;; (message "\nPushing (%s %s) to nesting-stack since %s is greater than %s or stack is empty" nesting-start nesting-end nesting-end (car (cdr (car nesting-stack)))) + ) + (push `(,nesting-stack-end ,nesting-end) nesting-stack) + (when phps-mode-functions-verbose + ;; (message "New stack %s, start: %s end: %s\n" nesting-stack (car (car nesting-stack)) (car (cdr (car nesting-stack)))) + ))) + + ;; ;; When nesting decreases but ends with a nesting increase, increase indent by one + ;; (when (and (< nesting-end nesting-start) + ;; line-contained-nesting-increase) + ;; (setq column-level (1+ column-level)) + ;; (when phps-mode-functions-verbose + ;; (message "Pushing %s to nesting-stack since is lesser than %s" nesting-start nesting-end)) + ;; (push `(,nesting-start nesting-end) nesting-stack) + ;; (message "New stack %s, start: %s end: %s" nesting-stack (car (car nesting-stack)) (car (cdr (car nesting-stack))))) ;; Calculate indentation level at start of line (setq nesting-start (+ round-bracket-level square-bracket-level curly-bracket-level alternative-control-structure-level inline-control-structure-level in-assignment-level in-class-declaration-level)) @@ -409,12 +441,29 @@ (setq first-token-is-nesting-increase nil) (setq first-token-is-nesting-decrease nil) (setq in-assignment-level 0) + (setq after-class-declaration nil) (setq in-class-declaration-level 0) (setq line-contained-nesting-increase nil) (setq line-contained-nesting-decrease nil) - (setq in-assignment-started-this-line nil))) + (setq in-assignment-started-this-line nil) + (setq changed-nesting-stack-in-line nil))) + + ;; Current token is not first (setq first-token-on-line nil) + ;; Calculate nesting + (setq nesting-end (+ round-bracket-level square-bracket-level curly-bracket-level alternative-control-structure-level inline-control-structure-level in-assignment-level in-class-declaration-level)) + + ;; Is current nesting-level equal or below stack-value? (#0) + (when (and nesting-stack + (<= nesting-end (car (car nesting-stack)))) + (setq column-level (1- column-level)) + (when phps-mode-functions-verbose + ;; (message "\nPopping %s from nesting-stack since %s is lesser somewhere on line, next is: %s, new column is: %s, new stack-value is: %s\n" (car nesting-stack) nesting-end (nth 1 nesting-stack) column-level (nth 1 nesting-stack)) + ) + (pop nesting-stack) + (setq changed-nesting-stack-in-line t)) + (when (> token-end-line-number token-start-line-number) ;; (message "Token not first on line %s starts at %s and ends at %s" token token-start-line-number token-end-line-number) (when (equal token 'T_DOC_COMMENT) diff --git a/phps-mode-test-functions.el b/phps-mode-test-functions.el index 2180dfc..346e30e 100644 --- a/phps-mode-test-functions.el +++ b/phps-mode-test-functions.el @@ -46,11 +46,6 @@ (defun phps-mode-test-functions-get-lines-indent () "Test `phps-mode-functions-get-lines-indent' function." - - (phps-mode-test-with-buffer - "<?php\nnamespace myNamespace\n{\n class myClass\n {\n public function myFunction()\n {\n echo 'my statement';\n }\n }\n}\n" - "Regular PHP with namespaces, classes and functions" - (should (equal '((1 (0 0)) (2 (0 0)) (3 (0 0)) (4 (1 0)) (5 (1 0)) (6 (2 0)) (7 (2 0)) (8 (3 0)) (9 (2 0)) (10 (1 0)) (11 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) (phps-mode-test-with-buffer "<html><head><title><?php\nif ($myCondition) {\n if ($mySecondCondition) {\n echo $title;\n } else if ($mySecondCondition) {\n echo $title4;\n } else {\n echo $title2;\n echo $title3;\n }\n} ?></title><body>Bla bla</body></html>" @@ -113,12 +108,6 @@ (should (equal '((1 (0 0)) (2 (0 0)) (3 (0 0)) (4 (0 0)) (5 (0 0)) (6 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) (phps-mode-test-with-buffer - "<?php\nclass MyClass extends MyAbstract implements\n myInterface,\n myInterface2\n{\n}\n" - "Class multi-line implements" - ;; (message "Tokens: %s" phps-mode-lexer-tokens) - (should (equal '((1 (0 0)) (2 (0 0)) (3 (1 0)) (4 (1 0)) (5 (0 0)) (6 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) - - (phps-mode-test-with-buffer "<?php\n$var = \"A line\nmore text here\nlast line here\";" "Multi-line double-quoted string" ;; (message "Tokens: %s" phps-mode-lexer-tokens) @@ -169,11 +158,6 @@ (should (equal '((1 (0 0)) (2 (0 0)) (3 (0 1)) (4 (0 1)) (5 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) (phps-mode-test-with-buffer - "<?php\n/**\n *\n */\nnamespace Aomebo\n{\n /**\n *\n */\n class Base\n {\n }\n}\n" - "Namespace and class with doc-comments" - (should (equal '((1 (0 0)) (2 (0 0)) (3 (0 1)) (4 (0 1)) (5 (0 0)) (6 (0 0)) (7 (1 0)) (8 (1 1)) (9 (1 1)) (10 (1 0)) (11 (1 0)) (12 (1 0)) (13 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) - - (phps-mode-test-with-buffer "<?php\n/** @define _SYSTEM_START_TIME_ Startup time for system */\ndefine('_SYSTEM_START_TIME_', microtime(true));\necho 'statement';\n" "Statement after a define() with a doc-comment" (should (equal '((1 (0 0)) (2 (0 0)) (3 (0 0)) (4 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) @@ -184,6 +168,32 @@ ;; (message "Tokens: %s" phps-mode-lexer-tokens) (should (equal '((1 (0 0)) (2 (0 0)) (3 (0 0)) (4 (1 0)) (5 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) + ) + +(defun phps-mode-test-function-get-lines-indent-classes () + "Test for class indent." + + (phps-mode-test-with-buffer + "<?php\nnamespace myNamespace\n{\n class myClass\n {\n public function myFunction()\n {\n echo 'my statement';\n }\n }\n}\n" + "Regular PHP with namespaces, classes and functions" + (should (equal '((1 (0 0)) (2 (0 0)) (3 (0 0)) (4 (1 0)) (5 (1 0)) (6 (2 0)) (7 (2 0)) (8 (3 0)) (9 (2 0)) (10 (1 0)) (11 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) + + (phps-mode-test-with-buffer + "<?php\nclass MyClass extends MyAbstract implements\n myInterface,\n myInterface2\n{\n}\n" + "Class multi-line implements" + ;; (message "Tokens: %s" phps-mode-lexer-tokens) + (should (equal '((1 (0 0)) (2 (0 0)) (3 (1 0)) (4 (1 0)) (5 (0 0)) (6 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) + + (phps-mode-test-with-buffer + "<?php\n/**\n *\n */\nnamespace Aomebo\n{\n /**\n *\n */\n class Base\n {\n }\n}\n" + "Namespace and class with doc-comments" + (should (equal '((1 (0 0)) (2 (0 0)) (3 (0 1)) (4 (0 1)) (5 (0 0)) (6 (0 0)) (7 (1 0)) (8 (1 1)) (9 (1 1)) (10 (1 0)) (11 (1 0)) (12 (1 0)) (13 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) + +) + +(defun phps-mode-test-functions-get-lines-lindent-if () + "Test for multi-line if expressions." + (phps-mode-test-with-buffer "<?php\nif (\n true\n && true\n) {\n echo 'was here';\n}\n" "If expression spanning multiple lines 1" @@ -197,7 +207,7 @@ (should (equal '((1 (0 0)) (2 (0 0)) (3 (0 0)) (4 (1 0)) (5 (1 0)) (6 (1 0)) (7 (1 0)) (8 (0 0)) (9 (1 0)) (10 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) (phps-mode-test-with-buffer - "<?php\nif (true) {\n if ($configuration::load(\n self::getParameter(self::PARAMETER_CONFIGURATION_INTERNAL_FILENAME),\n self::getParameter(self::PARAMETER_CONFIGURATION_EXTERNAL_FILENAME),\n self::getParameter(self::PARAMETER_STRUCTURE_INTERNAL_FILENAME),\n self::getParameter(self::PARAMETER_STRUCTURE_EXTERNAL_FILENAME)\n )) {\n echo 'was here';\n }\n}\n" + "<?php\nif (true) {\n if ($configuration::load(\n self::getParameter(self::PARAMETER_CONFIGURATION_INTERNAL_FILENAME),\n self::getParameter(self::PARAMETER_CONFIGURATION_EXTERNAL_FILENAME),\n self::getParameter(self::PARAMETER_STRUCTURE_INTERNAL_FILENAME),\n self::getParameter(self::PARAMETER_STRUCTURE_EXTERNAL_FILENAME))\n ) {\n echo 'was here';\n }\n}\n" "If expression spanning multiple lines 3" ;; (message "Tokens: %s" phps-mode-lexer-tokens) (should (equal '((1 (0 0)) (2 (0 0)) (3 (1 0)) (4 (2 0)) (5 (2 0)) (6 (2 0)) (7 (2 0)) (8 (1 0)) (9 (2 0)) (10 (1 0)) (11 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) @@ -212,7 +222,7 @@ "<?php\nif (myFunction(\ntrue)\n) {\n echo 'was here';\n}\n" "If expression spanning multiple lines 5" ;; (message "Tokens: %s" phps-mode-lexer-tokens) - (should (equal '((1 (0 0)) (2 (0 0)) (3 (0 0)) (4 (0 0)) (5 (1 0)) (6 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) + (should (equal '((1 (0 0)) (2 (0 0)) (3 (1 0)) (4 (0 0)) (5 (1 0)) (6 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) (phps-mode-test-with-buffer "<?php\nif (true) {\n if (myFunction(\n true)\n ) {\n echo 'was here';\n }\n}\n" @@ -220,7 +230,6 @@ ;; (message "Tokens: %s" phps-mode-lexer-tokens) (should (equal '((1 (0 0)) (2 (0 0)) (3 (1 0)) (4 (2 0)) (5 (1 0)) (6 (2 0)) (7 (1 0)) (8 (0 0))) (phps-mode-test-functions--hash-to-list (phps-mode-functions-get-lines-indent))))) - ) (defun phps-mode-test-functions-indent-line () @@ -463,7 +472,10 @@ (defun phps-mode-test-functions () "Run test for functions." + ;; (setq debug-on-error t) (setq phps-mode-functions-verbose t) + (phps-mode-test-functions-get-lines-lindent-if) + (phps-mode-test-function-get-lines-indent-classes) (phps-mode-test-functions-get-lines-indent) (phps-mode-test-functions-indent-line))