emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/phps-mode b869339: Re-organization and improvements in


From: Christian Johansson
Subject: [elpa] externals/phps-mode b869339: Re-organization and improvements in usability
Date: Mon, 30 Sep 2019 11:48:36 -0400 (EDT)

branch: externals/phps-mode
commit b869339c62d501190c5902bf275fbee163791248
Author: Christian Johansson <address@hidden>
Commit: Christian Johansson <address@hidden>

    Re-organization and improvements in usability
---
 Makefile                                           |   14 +-
 README.md                                          |   17 +-
 .../phps-mode-automation-header.wy                 |    0
 .../phps-mode-automation.el                        |    0
 .../alternative-control-structure.php              |    0
 .../sample-php-files}/class.php                    |    0
 .../sample-php-files}/functions.php                |    0
 .../inline-control-structures.php                  |    0
 .../sample-php-files}/interfaces.php               |    0
 .../sample-php-files}/namespace.php                |    0
 .../sample-php-files}/namespaces.php               |    0
 .../sample-php-files}/navigation.php               |    0
 docs/development.md                                |   71 +
 docs/heuristics.md                                 |   23 +-
 docs/todo.md                                       |    3 +-
 phps-mode-lexer.el => phps-mode-analyzer.el        | 1406 +++++++++++++++++++-
 phps-mode-flymake.el                               |    2 -
 phps-mode-functions.el                             | 1379 -------------------
 phps-mode.el                                       |  100 +-
 .../phps-mode-test-functions.el                    |   44 +-
 .../phps-mode-test-integration.el                  |    3 +-
 .../phps-mode-test-lexer.el                        |    1 -
 .../phps-mode-test-parser.el                       |    0
 .../phps-mode-test-syntax-table.el                 |    2 +-
 phps-mode-test.el => test/phps-mode-test.el        |    6 +-
 25 files changed, 1542 insertions(+), 1529 deletions(-)

diff --git a/Makefile b/Makefile
index 6a0d0c9..f1baa3d 100644
--- a/Makefile
+++ b/Makefile
@@ -2,9 +2,9 @@ EMACS = emacs
 ifdef emacs
        EMACS = $(emacs)
 endif
-EMACS_CMD := $(EMACS) -Q -batch -L .
+EMACS_CMD := $(EMACS) -Q -batch -L . -L test/
 
-EL  := phps-mode-automation.el phps-mode-flymake.el phps-mode-functions.el 
phps-mode-lexer.el phps-mode-semantic.el phps-mode-syntax-table.el 
phps-mode-tags.el phps-mode-test-functions.el phps-mode-test-integration.el 
phps-mode-test-lexer.el phps-mode-test-parser.el phps-mode-test-syntax-table.el 
phps-mode-test.el phps-mode.el
+EL  := admin/phps-mode-automation.el phps-mode-analyzer.el 
phps-mode-flymake.el phps-mode-semantic.el phps-mode-syntax-table.el 
phps-mode-tags.el test/phps-mode-test-functions.el 
test/phps-mode-test-integration.el test/phps-mode-test-lexer.el 
test/phps-mode-test-parser.el test/phps-mode-test-syntax-table.el 
test/phps-mode-test.el phps-mode.el
 ELC := $(EL:.el=.elc)
 
 .PHONY: clean
@@ -20,20 +20,20 @@ tests: test-functions test-integration test-lexer 
test-parser test-syntax-table
 
 .PHONY: test-functions
 test-functions:
-       $(EMACS_CMD) -l phps-mode-test-functions.el
+       $(EMACS_CMD) -l test/phps-mode-test-functions.el
 
 .PHONY: test-integration
 test-integration:
-       $(EMACS_CMD) -l phps-mode-test-integration.el
+       $(EMACS_CMD) -l test/phps-mode-test-integration.el
 
 .PHONY: test-lexer
 test-lexer:
-       $(EMACS_CMD) -l phps-mode-test-lexer.el
+       $(EMACS_CMD) -l test/phps-mode-test-lexer.el
 
 .PHONY: test-parser
 test-parser:
-       $(EMACS_CMD) -l phps-mode-test-parser.el
+       $(EMACS_CMD) -l test/phps-mode-test-parser.el
 
 .PHONY: test-syntax-table
 test-syntax-table:
-       $(EMACS_CMD) -l phps-mode-test-syntax-table.el
+       $(EMACS_CMD) -l test/phps-mode-test-syntax-table.el
diff --git a/README.md b/README.md
index 4f5fe70..7066415 100644
--- a/README.md
+++ b/README.md
@@ -10,9 +10,9 @@ This mode does not require PHP installed on your computer 
because it has a built
 ## Features
 
 * GPLv3 license
-* Flycheck support
+* Flycheck support with `(phps-mode-flycheck-setup)`
 * Semantic lexer based on official PHP re2c lexer
-* Syntax coloring based on lexer tokens, make it easier to spot invalid code
+* Syntax coloring based on lexer tokens, makes it easier to spot invalid code
 * PSR-1 and PSR-2 indentation based on lexer tokens
 * Integration with `(electric-pair)`
 * Incremental lexer and syntax coloring after buffer changes
@@ -28,12 +28,8 @@ This mode does not require PHP installed on your computer 
because it has a built
 
 ## Keymap
 
-* `C-c /` Comment region
-* `C-c DEL` Uncomment region
 * `C-c C-r` Rescan buffer
 * `C-c C-f` Format buffer
-* `C-c C-r` Lex buffer
-* `C-c C-p` Process buffer
 
 ## Installation
 
@@ -55,7 +51,9 @@ You can install via ELPA (`M-x package-install` + `RET` + 
`phps-mode` + `RET`),
 (use-package phps-mode
     :after flycheck
     :ensure t
-    :mode ("\\.php\\'" "\\.phtml\\'"))
+    :mode ("\\.php\\'" "\\.phtml\\'")
+    :config
+    (phps-mode-flycheck-setup))
 ```
 
 ### Load and configure using use-package
@@ -63,13 +61,16 @@ You can install via ELPA (`M-x package-install` + `RET` + 
`phps-mode` + `RET`),
 ``` emacs-lisp
 (use-package phps-mode
     :after flycheck
-    :mode ("\\.php\\'" "\\.phtml\\'"))
+    :mode ("\\.php\\'" "\\.phtml\\'")
+    :config
+    (phps-mode-flycheck-setup))
 ```
 
 ### Load and configure using regular emacs-lisp
 ``` emacs-lisp
 (require 'phps-mode)
 (add-to-list 'auto-mode-alist '("\\.\\(php\\|phtml\\)\\'" . phps-mode))
+(phps-mode-flycheck-setup)
 ```
 
 ## Read more
diff --git a/phps-mode-automation-header.wy 
b/admin/phps-mode-automation-header.wy
similarity index 100%
rename from phps-mode-automation-header.wy
rename to admin/phps-mode-automation-header.wy
diff --git a/phps-mode-automation.el b/admin/phps-mode-automation.el
similarity index 100%
rename from phps-mode-automation.el
rename to admin/phps-mode-automation.el
diff --git a/sample-php-files/alternative-control-structure.php 
b/admin/sample-php-files/alternative-control-structure.php
similarity index 100%
rename from sample-php-files/alternative-control-structure.php
rename to admin/sample-php-files/alternative-control-structure.php
diff --git a/sample-php-files/class.php b/admin/sample-php-files/class.php
similarity index 100%
rename from sample-php-files/class.php
rename to admin/sample-php-files/class.php
diff --git a/sample-php-files/functions.php 
b/admin/sample-php-files/functions.php
similarity index 100%
rename from sample-php-files/functions.php
rename to admin/sample-php-files/functions.php
diff --git a/sample-php-files/inline-control-structures.php 
b/admin/sample-php-files/inline-control-structures.php
similarity index 100%
rename from sample-php-files/inline-control-structures.php
rename to admin/sample-php-files/inline-control-structures.php
diff --git a/sample-php-files/interfaces.php 
b/admin/sample-php-files/interfaces.php
similarity index 100%
rename from sample-php-files/interfaces.php
rename to admin/sample-php-files/interfaces.php
diff --git a/sample-php-files/namespace.php 
b/admin/sample-php-files/namespace.php
similarity index 100%
rename from sample-php-files/namespace.php
rename to admin/sample-php-files/namespace.php
diff --git a/sample-php-files/namespaces.php 
b/admin/sample-php-files/namespaces.php
similarity index 100%
rename from sample-php-files/namespaces.php
rename to admin/sample-php-files/namespaces.php
diff --git a/sample-php-files/navigation.php 
b/admin/sample-php-files/navigation.php
similarity index 100%
rename from sample-php-files/navigation.php
rename to admin/sample-php-files/navigation.php
diff --git a/docs/development.md b/docs/development.md
new file mode 100644
index 0000000..ea2df5e
--- /dev/null
+++ b/docs/development.md
@@ -0,0 +1,71 @@
+# Development
+
+Make pull requests to `develop` branch or branches forked from develop branch. 
Tested changes that are considered improvements are merged to master. Make sure 
to sign the FSF-papers as well.
+
+## Tests
+
+If you have emacs at a customized location prefix the commands with your path, 
i.e.
+
+`export emacs="~/Documents/emacs/src/emacs" && make tests`
+
+Run all tests with `make tests`.
+
+### Functions
+
+Indentations, incremental processes, Imenu-support.
+
+``` bash
+make test-functions
+```
+
+### Integration
+
+This should test all other parts in collaboration.
+
+``` bash
+make test-integration
+```
+
+### Lexer
+
+Lexer token generation.
+
+``` bash
+make test-lexer
+```
+
+### Parser
+
+Semantic grammar. Not ready yet.
+
+``` bash
+make test-parser
+```
+
+### Syntax-table
+
+Basic point and region behaviour.
+
+``` bash
+make test-syntax-table
+```
+
+## Byte-compilation
+
+Plug-in should support byte-compilation and it is recommended.
+
+### Compile
+
+``` bash
+make compile
+```
+
+### Clean
+
+``` bash
+make clean
+```
+
+
+
+[Back to start](../../../)
diff --git a/docs/heuristics.md b/docs/heuristics.md
index bbfab08..7a75ecc 100644
--- a/docs/heuristics.md
+++ b/docs/heuristics.md
@@ -1,19 +1,22 @@
-## Heuristics
+# Heuristics
 
-These should solve the problem of freezing editor for too long when making 
white-space changes to code in large files. Otherwise a full incremental 
re-parse would be triggered more often than necessary.
+These should solve the problem of freezing editor for too long when making 
small changes to large files. Otherwise a full incremental re-parse would be 
triggered more often than necessary.
 
-### Return
-When pressing return when the rest of the current line after cursor is only 
white-space, move indexes of tokens, lexer states, indentation and imenu 
forward one point
+## Indenting
 
+When indenting a line, calculate difference in white-space and change indexes 
of buffer after point correspondingly.
 
-### Backspace
-When pressing backspace when the rest of the current line before cursor is 
only white-space, move indexes of tokens, lexer states, indentation and imenu 
backward one pint
+## Incremental
 
-### Indenting
-When indenting a line, calculate difference in white-space and change indexes 
of buffer after point correspondingly
+When user has done other changes, determine unchanged previous position R, 
determine changed maximum position X, determine new buffer length L. Do 
incremental lex from R to X.
 
-### Other changes
-When user has done none-whitespace changes, determine unchanged previous 
position R, determine changed maximum position X, determine new buffer length 
L. Do incremental lex from R to X, if new states at X equals old states at X 
just move indexes with delta X, otherwise do incremental lex of rest of buffer.
+### State preserving changes
+
+If new states at X equals old states at X just move all indexes with delta X, 
otherwise do incremental lex of rest of buffer.
+
+### State disrupting changes
+
+Otherwise continue with incremental lex of rest of buffer.
 
 
 [Back to start](../../../)
diff --git a/docs/todo.md b/docs/todo.md
index 81e042a..d69500b 100644
--- a/docs/todo.md
+++ b/docs/todo.md
@@ -2,8 +2,9 @@
 
 *With current progress estimates:*
 
+* Got imenu items were there are only a namespace, namespace class, or class
+
 * Add to MELPA package archive (50%)
-* A set of heuristics to improve large-file incremental change handling (75%)
 * Wisent LALR parser based on official PHP yacc parser automatically converted 
grammar (50%)
 * mmm-mode support (50%)
 * Full integration with Emacs Semantic subsystem (30%)
diff --git a/phps-mode-lexer.el b/phps-mode-analyzer.el
similarity index 54%
rename from phps-mode-lexer.el
rename to phps-mode-analyzer.el
index a922012..cc0ef26 100644
--- a/phps-mode-lexer.el
+++ b/phps-mode-analyzer.el
@@ -1,4 +1,4 @@
-;;; phps-mode-lexer.el -- Lexer for PHPs -*- lexical-binding: t -*-
+;;; phps-mode-analyzer.el -- Lexer and helper functions for PHPs -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 2018-2019  Free Software Foundation, Inc.
 
@@ -20,40 +20,25 @@
 
 ;;; Commentary:
 
-;; Based on the Zend PHP Lexer and Parser 
https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l
+;; *Define the lexer for this grammar
+;; based on the Zend PHP Lexer at
+;; `https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l'
 ;; which is using re2c.
 ;;
-;; NOTE Files of interest:
-;; - zend_language_scanner.l
-
+;; * Also supply logic for indentation and imenu-handling
+;; Change detection and incremental lexer
+;;
+;; * Syntax coloring based on lexer tokens
 
 ;;; Code:
 
-;; NOTE We use autoload here to circumvent recursive require
-(autoload 'phps-mode-functions--reset-changes "phps-mode-functions")
-(autoload 'phps-mode-functions--cancel-idle-timer "phps-mode-functions")
-(autoload 'phps-mode-functions--get-changes "phps-mode-functions")
-(autoload 'phps-mode-get-syntax-table "phps-mode")
-(autoload 'phps-mode-functions-processed-buffer "phps-mode-functions")
-(autoload 'phps-mode-functions-reset-processed-buffer "phps-mode-functions")
-(autoload 'phps-mode-runtime-debug-message "phps-mode")
+
+(require 'phps-mode-macros)
 
 (require 'semantic)
 (require 'semantic/lex)
-
-;; NOTE This line is required to pass byte-compilation
 (require 'semantic/wisent)
 
-(require 'phps-mode-macros)
-
-
-;; Fix for byte-compilation warnings
-
-
-;; Define the lexer for this grammar
-
-;; Make sure `semantic-lex-syntax-modifications' is correct since lexer is 
dependent on Emacs syntax-table
-
 
 (defvar phps-mode-lexer-tokens nil
   "Last lexer tokens.")
@@ -385,8 +370,10 @@
   "Push TOKEN to list with START and END."
 
   ;; Colourize token
-  (when-let (token-syntax-color (phps-mode-lexer-get-token-syntax-color token))
-    (phps-mode-lexer-set-region-syntax-color start end token-syntax-color))
+  (let ((token-syntax-color (phps-mode-lexer-get-token-syntax-color token)))
+    (if token-syntax-color
+        (phps-mode-lexer-set-region-syntax-color start end token-syntax-color)
+      (phps-mode-lexer-clear-region-syntax-color start end)))
 
   ;; Push token start, end, lexer state and state stack to variable
   (push
@@ -444,7 +431,12 @@
     (if phps-mode-lexer-tokens
         (progn
           ;; Add all updated tokens to semantic
-          (phps-mode-debug-message (message "Updating semantic lexer tokens 
from point %s, tokens: %s, point-max: %s" old-start phps-mode-lexer-tokens 
(point-max)))
+          (phps-mode-debug-message
+           (message
+            "Updating semantic lexer tokens from point %s, tokens: %s, 
point-max: %s"
+            old-start
+            phps-mode-lexer-tokens
+            (point-max)))
           (dolist (token phps-mode-lexer-tokens)
             (let ((start (car (cdr token)))
                   (end (cdr (cdr token)))
@@ -1669,7 +1661,6 @@
 (defun phps-mode-lexer-run-incremental (buffer)
   "Run incremental lexer on BUFFER."
   (phps-mode-debug-message (message "Run incremental lexer on buffer '%s'" 
buffer))
-  (phps-mode-runtime-debug-message (format "Run incremental lexer on buffer 
'%s'" buffer))
   (with-current-buffer buffer
     (let ((changes (phps-mode-functions--get-changes))
           (run-full-lexer nil)
@@ -1698,7 +1689,6 @@
             (setq-local phps-mode-lexer-STATE nil)
             (setq-local phps-mode-lexer-state_stack nil)
 
-            (phps-mode-runtime-debug-message "Processing incremental changes")
             (phps-mode-debug-message (message "Processing incremental changes: 
%s" changes))
             (setq run-full-lexer t)
 
@@ -1707,10 +1697,6 @@
                     (change-stop (nth 1 change))
                     (buffer-length-new (1- (nth 3 change)))
                     (buffer-contents-new (nth 4 change)))
-                (phps-mode-runtime-debug-message
-                 (format "Running incremental lexer %s - %s" change-start 
change-stop))
-                (phps-mode-debug-message
-                 (message "Running incremental lexer %s - %s" change-start 
change-stop))
 
                 (when (and change-start
                            change-stop)
@@ -1825,7 +1811,6 @@
 
                               (if head-states
                                   (progn
-                                    (phps-mode-runtime-debug-message "Found 
head states")
                                     (phps-mode-debug-message (message "Found 
head states"))
 
                                     ;; Flag that we should not run ful lexer
@@ -1850,8 +1835,10 @@
                                         (setq-local 
phps-mode-lexer-state_stack incremental-state-stack)
 
                                         ;; Setup lexer
-                                        (setq-local semantic-lex-analyzer 
#'phps-mode-lexer-lex)
-                                        (setq-local semantic-lex-syntax-table 
(phps-mode-get-syntax-table))
+                                        (when (fboundp 'phps-mode-lexer-lex)
+                                          (setq-local semantic-lex-analyzer 
#'phps-mode-lexer-lex))
+                                        (when (boundp 'phps-mode-syntax-table)
+                                          (setq-local 
semantic-lex-syntax-table phps-mode-syntax-table))
 
                                         (phps-mode-debug-message
                                          (message "Incremental buffer 
contents: \n%s" (buffer-substring-no-properties (point-min) (point-max)))
@@ -1869,7 +1856,6 @@
                                              (equal 
phps-mode-lexer-state_stack incremental-state-stack))
                                         (progn
 
-                                          (phps-mode-runtime-debug-message 
"Found matching state and state-stack, copying old state and tokens")
                                           (phps-mode-debug-message (message 
"Found matching state and state-stack, copying old state and tokens"))
 
                                           (unless (= buffer-length-delta 0)
@@ -1899,7 +1885,6 @@
                                           (setq appended-tokens (append 
appended-tokens tail-tokens))
                                           (phps-mode-debug-message (message 
"New tokens from incremental lex are: %s" appended-tokens)))
 
-                                      (phps-mode-runtime-debug-message "Did 
not find matching state and state-stack, lexing rest of buffer")
                                       (phps-mode-debug-message (message "Did 
not find matching state and state-stack, lexing rest of buffer"))
 
                                       (phps-mode-debug-message
@@ -1915,10 +1900,8 @@
                                       (phps-mode-debug-message (message "New 
states from full lex are: %s" phps-mode-lexer-states))
                                       (phps-mode-debug-message (message "New 
tokens from full lex are: %s" appended-tokens)))
 
-                                    (phps-mode-runtime-debug-message (format 
"Final tokens: %s" appended-tokens))
                                     (phps-mode-debug-message (message "Final 
tokens: %s" appended-tokens))
                                     (setq-local phps-mode-lexer-tokens 
appended-tokens))
-                                (phps-mode-runtime-debug-message "Did not find 
head states")
                                 (phps-mode-debug-message (message "Did not 
find head states"))))
                           (phps-mode-debug-message (message "Did not find 
positive incremental-start or head-tokens"))))
                     (phps-mode-debug-message (message "Change start not above 
one or lacking tokens or states"))))
@@ -1927,11 +1910,9 @@
 
             (setq-local phps-mode-lexer-buffer-length (1- (point-max)))
             (setq-local phps-mode-lexer-buffer-contents 
(buffer-substring-no-properties (point-min) (point-max))))
-        (phps-mode-runtime-debug-message "Found no changes")
         (phps-mode-debug-message (message "Found no changes")))
 
       (when run-full-lexer
-        (phps-mode-runtime-debug-message "Running full lexer")
         (phps-mode-debug-message (message "Running full lexer"))
         (phps-mode-lexer-run)))))
 
@@ -1940,6 +1921,1341 @@
   phps-mode-lexer-lex-analyzer
   semantic-lex-default-action)
 
-(provide 'phps-mode-lexer)
+(require 'subr-x)
+
+(defvar phps-mode-functions-allow-after-change t
+  "Flag to tell us whether after change detection is enabled or not.")
+
+(defvar phps-mode-functions-buffer-changes nil
+  "A stack of buffer changes.")
+
+(defvar phps-mode-functions-idle-timer nil
+  "Timer object of idle timer.")
+
+(defvar phps-mode-functions-imenu nil
+  "The Imenu alist for current buffer, nil if none.")
+
+(defvar phps-mode-functions-lines-indent nil
+  "The indentation of each line in buffer, nil if none.")
+
+(defvar phps-mode-functions-processed-buffer nil
+  "Flag whether current buffer is processed or not.")
+
+(defun phps-mode-functions-get-processed-buffer ()
+  "Get flag for whether buffer is processed or not."
+  phps-mode-functions-processed-buffer)
+
+(defun phps-mode-functions-reset-processed-buffer ()
+  "Reset flag for whether buffer is processed or not."
+  (setq-local phps-mode-functions-processed-buffer nil))
+
+(defun phps-mode-functions-process-current-buffer ()
+  "Process current buffer, generate indentations and Imenu, trigger 
incremental lexer if we have change."
+  (interactive)
+  (phps-mode-debug-message (message "Process current buffer"))
+  (when phps-mode-functions-idle-timer
+    (phps-mode-debug-message (message "Trigger incremental lexer"))
+    (phps-mode-lexer-run-incremental (current-buffer))
+    (setq-local phps-mode-functions-processed-buffer nil))
+  (if (not phps-mode-functions-processed-buffer)
+      (progn
+        (phps-mode-debug-message (message "Buffer is not processed"))
+        (let ((processed (phps-mode-functions--process-tokens-in-string 
phps-mode-lexer-tokens (buffer-substring-no-properties (point-min) 
(point-max)))))
+          (phps-mode-debug-message (message "Processed result: %s" processed))
+          (setq-local phps-mode-functions-imenu (nth 0 processed))
+          (setq-local phps-mode-functions-lines-indent (nth 1 processed)))
+        (setq-local phps-mode-functions-processed-buffer t))
+    (phps-mode-debug-message (message "Buffer is already processed"))))
+
+(defun phps-mode-functions-get-moved-lines-indent (old-lines-indents 
start-line-number diff)
+  "Move OLD-LINES-INDENTS from START-LINE-NUMBER with DIFF points."
+  (let ((lines-indents (make-hash-table :test 'equal))
+        (line-number 1))
+    (when old-lines-indents
+      (let ((line-indent (gethash line-number old-lines-indents))
+            (new-line-number))
+        (while line-indent
+
+          (when (< line-number start-line-number)
+            ;; (message "Added new indent 3 %s from %s to %s" line-indent 
line-number line-number)
+            (puthash line-number line-indent lines-indents))
+
+          (when (and (> diff 0)
+                     (>= line-number start-line-number)
+                     (< line-number (+ start-line-number diff)))
+            ;; (message "Added new indent 2 %s from %s to %s" line-indent 
line-number line-number)
+            (puthash line-number (gethash start-line-number old-lines-indents) 
lines-indents))
+
+          (when (>= line-number start-line-number)
+            (setq new-line-number (+ line-number diff))
+            ;; (message "Added new indent %s from %s to %s" line-indent 
line-number new-line-number)
+            (puthash new-line-number line-indent lines-indents))
+
+          (setq line-number (1+ line-number))
+          (setq line-indent (gethash line-number old-lines-indents))))
+      lines-indents)))
+
+(defun phps-mode-functions-move-imenu-index (start diff)
+  "Moved imenu from START by DIFF points."
+  (when phps-mode-functions-imenu
+    (setq-local phps-mode-functions-imenu (phps-mode-functions-get-moved-imenu 
phps-mode-functions-imenu start diff))))
+
+(defun phps-mode-functions-move-lines-indent (start-line-number diff)
+  "Move lines indent from START-LINE-NUMBER with DIFF points."
+  (when phps-mode-functions-lines-indent
+    ;; (message "Moving line-indent index from %s with %s" start-line-number 
diff)
+    (setq-local phps-mode-functions-lines-indent 
(phps-mode-functions-get-moved-lines-indent phps-mode-functions-lines-indent 
start-line-number diff))))
+
+(defun phps-mode-functions-get-lines-indent ()
+  "Return lines indent, process buffer if not done already."
+  (phps-mode-functions-process-current-buffer)
+  phps-mode-functions-lines-indent)
+
+(defun phps-mode-functions-get-imenu ()
+  "Return Imenu, process buffer if not done already."
+  (phps-mode-functions-process-current-buffer)
+  phps-mode-functions-imenu)
+
+(defun phps-mode-functions-get-moved-imenu (old-index start diff)
+  "Move imenu-index OLD-INDEX beginning from START with DIFF."
+  (let ((new-index '()))
+
+    (when old-index
+      (if (and (listp old-index)
+               (listp (car old-index)))
+          (dolist (item old-index)
+            (let ((sub-item (phps-mode-functions-get-moved-imenu item start 
diff)))
+              (push (car sub-item) new-index)))
+        (let ((item old-index))
+          (let ((item-label (car item)))
+            (if (listp (cdr item))
+                (let ((sub-item (phps-mode-functions-get-moved-imenu (cdr 
item) start diff)))
+                  (push `(,item-label . ,sub-item) new-index))
+              (let ((item-start (cdr item)))
+                (when (>= item-start start)
+                  (setq item-start (+ item-start diff)))
+                (push `(,item-label . ,item-start) new-index)))))))
+
+    (nreverse new-index)))
+
+(defun phps-mode-functions--get-lines-in-buffer (beg end)
+  "Return the number of lines in buffer between BEG and END."
+  (phps-mode-functions--get-lines-in-string (buffer-substring-no-properties 
beg end)))
+
+(defun phps-mode-functions--get-lines-in-string (string)
+  "Return the number of lines in STRING."
+  (let ((lines-in-string 0)
+        (start 0))
+    (while (string-match "[\n\C-m]" string start)
+      (setq start (match-end 0))
+      (setq lines-in-string (1+ lines-in-string)))
+    lines-in-string))
+
+(defun phps-mode-functions--get-inline-html-indentation (inline-html indent 
tag-level curly-bracket-level square-bracket-level round-bracket-level)
+  "Generate a list of indentation for each line in INLINE-HTML, working 
incrementally on INDENT, TAG-LEVEL, CURLY-BRACKET-LEVEL, SQUARE-BRACKET-LEVEL 
and ROUND-BRACKET-LEVEL."
+  (phps-mode-debug-message
+   (message "Calculating HTML indent for: '%s'" inline-html))
+
+  ;; Add trailing newline if missing
+  (unless (string-match "\n$" inline-html)
+    (setq inline-html (concat inline-html "\n")))
+
+  (let ((start 0)
+        (indent-start indent)
+        (indent-end indent)
+        (line-indents nil)
+        (first-object-on-line t)
+        (first-object-is-nesting-decrease nil))
+    (while (string-match 
"\\([\n\C-m]\\)\\|\\(<[a-zA-Z]+\\)\\|\\(</[a-zA-Z]+\\)\\|\\(/>\\)\\|\\(\\[\\)\\|\\()\\)\\|\\((\\)"
 inline-html start)
+      (let* ((end (match-end 0))
+             (string (substring inline-html (match-beginning 0) end)))
+
+        (cond
+
+         ((string= string "\n")
+
+          (let ((temp-indent indent))
+            (when first-object-is-nesting-decrease
+              (phps-mode-debug-message
+               (message "Decreasing indent with one since first object was a 
nesting decrease"))
+              (setq temp-indent (1- indent))
+              (when (< temp-indent 0)
+                (setq temp-indent 0)))
+            (push temp-indent line-indents))
+
+          (setq indent-end (+ tag-level curly-bracket-level 
square-bracket-level round-bracket-level))
+          (phps-mode-debug-message "Encountered a new-line")
+          (if (> indent-end indent-start)
+              (progn
+                (phps-mode-debug-message
+                 (message "Increasing indent since %s is above %s" indent-end 
indent-start))
+                (setq indent (1+ indent)))
+            (when (< indent-end indent-start)
+              (phps-mode-debug-message
+               (message "Decreasing indent since %s is below %s" indent-end 
indent-start))
+              (setq indent (1- indent))
+              (when (< indent 0)
+                (setq indent 0))))
+
+          (setq indent-start indent-end)
+          (setq first-object-on-line t)
+          (setq first-object-is-nesting-decrease nil))
+
+         ((string= string "(")
+          (setq round-bracket-level (1+ round-bracket-level)))
+         ((string= string ")")
+          (setq round-bracket-level (1- round-bracket-level)))
+
+         ((string= string "[")
+          (setq square-bracket-level (1+ square-bracket-level)))
+         ((string= string "]")
+          (setq square-bracket-level (1- square-bracket-level)))
+
+         ((string= string "{")
+          (setq curly-bracket-level (1+ curly-bracket-level)))
+         ((string= string "}")
+          (setq curly-bracket-level (1- curly-bracket-level)))
+
+         ((string-match "<[a-zA-Z]+" string)
+          (setq tag-level (1+ tag-level)))
+
+         ((string-match "\\(</[a-zA-Z]+\\)\\|\\(/>\\)" string)
+          (setq tag-level (1- tag-level)))
+
+         )
+
+        (when first-object-on-line
+          (unless (string= string "\n")
+            (setq first-object-on-line nil)
+            (setq indent-end (+ tag-level curly-bracket-level 
square-bracket-level round-bracket-level))
+            (when (< indent-end indent-start)
+              (phps-mode-debug-message "First object was nesting decrease")
+              (setq first-object-is-nesting-decrease t))))
+
+        (setq start end)))
+    (list (nreverse line-indents) indent tag-level curly-bracket-level 
square-bracket-level round-bracket-level)))
+
+(defun phps-mode-functions--process-tokens-in-string (tokens string)
+  "Generate indexes for imenu and indentation for TOKENS and STRING one pass.  
Complexity: O(n)."
+  (if tokens
+      (progn
+        (phps-mode-debug-message (message "\nCalculation indentation and imenu 
for all lines in buffer:\n\n%s" string))
+        (let ((in-heredoc nil)
+              (in-heredoc-started-this-line nil)
+              (in-heredoc-ended-this-line nil)
+              (in-inline-control-structure nil)
+              (inline-html-indent 0)
+              (inline-html-indent-start 0)
+              (inline-html-tag-level 0)
+              (inline-html-curly-bracket-level 0)
+              (inline-html-square-bracket-level 0)
+              (inline-html-round-bracket-level 0)
+              (inline-html-is-whitespace nil)
+              (first-token-is-inline-html nil)
+              (after-special-control-structure nil)
+              (after-special-control-structure-token nil)
+              (after-extra-special-control-structure nil)
+              (after-extra-special-control-structure-first-on-line nil)
+              (switch-curly-stack nil)
+              (switch-alternative-stack nil)
+              (switch-case-alternative-stack nil)
+              (curly-bracket-level 0)
+              (round-bracket-level 0)
+              (square-bracket-level 0)
+              (alternative-control-structure-level 0)
+              (in-concatenation nil)
+              (in-concatenation-round-bracket-level nil)
+              (in-concatenation-square-bracket-level nil)
+              (in-concatenation-level 0)
+              (column-level 0)
+              (column-level-start 0)
+              (tuning-level 0)
+              (nesting-start 0)
+              (nesting-end 0)
+              (last-line-number 0)
+              (first-token-on-line t)
+              (line-indents (make-hash-table :test 'equal))
+              (first-token-is-nesting-decrease nil)
+              (token-number 1)
+              (allow-custom-column-increment nil)
+              (allow-custom-column-decrement nil)
+              (in-assignment nil)
+              (in-assignment-round-bracket-level nil)
+              (in-assignment-square-bracket-level nil)
+              (in-assignment-level 0)
+              (in-object-operator nil)
+              (in-object-operator-round-bracket-level nil)
+              (in-object-operator-square-bracket-level nil)
+              (after-object-operator nil)
+              (in-object-operator-level 0)
+              (in-class-declaration nil)
+              (in-class-declaration-level 0)
+              (in-return nil)
+              (in-return-curly-bracket-level nil)
+              (in-return-level 0)
+              (previous-token nil)
+              (token nil)
+              (token-start nil)
+              (token-end nil)
+              (token-start-line-number 0)
+              (token-end-line-number 0)
+              (tokens (nreverse (copy-sequence tokens)))
+              (nesting-stack nil)
+              (nesting-key nil)
+              (class-declaration-started-this-line nil)
+              (special-control-structure-started-this-line nil)
+              (temp-pre-indent nil)
+              (temp-post-indent nil)
+              (imenu-index '())
+              (imenu-namespace-index '())
+              (imenu-namespace-definition nil)
+              (imenu-class-index '())
+              (imenu-class-definition nil)
+              (imenu-in-namespace-declaration nil)
+              (imenu-in-namespace-name nil)
+              (imenu-in-namespace-with-brackets nil)
+              (imenu-open-namespace-level nil)
+              (imenu-in-class-declaration nil)
+              (imenu-open-class-level nil)
+              (imenu-in-class-name nil)
+              (imenu-in-function-declaration nil)
+              (imenu-in-function-name nil)
+              (imenu-in-function-index nil)
+              (imenu-nesting-level 0)
+              (incremental-line-number 1))
+
+          (push `(END_PARSE ,(length string) . ,(length string)) tokens)
+
+          ;; Iterate through all buffer tokens from beginning to end
+          (dolist (item (nreverse tokens))
+            ;; (message "Items: %s %s" item phps-mode-lexer-tokens)
+            (let ((next-token (car item))
+                  (next-token-start (car (cdr item)))
+                  (next-token-end (cdr (cdr item)))
+                  (next-token-start-line-number nil)
+                  (next-token-end-line-number nil))
+
+              (when (and token
+                         (< token-end next-token-start))
+                ;; NOTE We use a incremental-line-number calculation because 
`line-at-pos' takes a lot of time
+                (setq incremental-line-number (+ incremental-line-number 
(phps-mode-functions--get-lines-in-string (substring string (1- token-end) (1- 
next-token-start))))))
+
+              ;; Handle the pseudo-token for last-line
+              (if (equal next-token 'END_PARSE)
+                  (progn
+                    (setq next-token-start-line-number (1+ 
token-start-line-number))
+                    (setq next-token-end-line-number (1+ 
token-end-line-number)))
+                (setq next-token-start-line-number incremental-line-number)
+
+                ;; NOTE We use a incremental-line-number calculation because 
`line-at-pos' takes a lot of time
+                ;; (message "Lines for %s '%s'" next-token (substring string 
(1- next-token-start) (1- next-token-end)))
+                (setq incremental-line-number (+ incremental-line-number 
(phps-mode-functions--get-lines-in-string (substring string (1- 
next-token-start) (1- next-token-end)))))
+                (setq next-token-end-line-number incremental-line-number)
+                (phps-mode-debug-message
+                 (message "Token '%s' pos: %s-%s lines: %s-%s" next-token 
next-token-start next-token-end next-token-start-line-number 
next-token-end-line-number)))
+
+              ;; Token logic - we have one-two token look-ahead at this point
+              ;; `token' is previous token
+              ;; `next-token' is current token
+              ;; `previous-token' is maybe two tokens back
+              (when token
+
+
+                ;; IMENU LOGIC
+
+                (cond
+
+                 ((or (string= token "{")
+                      (equal token 'T_CURLY_OPEN)
+                      (equal token 'T_DOLLAR_OPEN_CURLY_BRACES))
+                  (setq imenu-nesting-level (1+ imenu-nesting-level)))
+
+                 ((string= token "}")
+
+                  (when (and imenu-open-namespace-level
+                             (= imenu-open-namespace-level imenu-nesting-level)
+                             imenu-in-namespace-name)
+                    (let ((imenu-add-list (nreverse imenu-namespace-index)))
+                      (push `(,imenu-in-namespace-name . ,imenu-add-list) 
imenu-index))
+                    (setq imenu-in-namespace-name nil))
+
+                  (when (and imenu-open-class-level
+                             (= imenu-open-class-level imenu-nesting-level)
+                             imenu-in-class-name)
+                    (let ((imenu-add-list (nreverse imenu-class-index)))
+                      (if imenu-in-namespace-name
+                          (push `(,imenu-in-class-name . ,imenu-add-list) 
imenu-namespace-index)
+                        (push `(,imenu-in-class-name . ,imenu-add-list) 
imenu-index)))
+                    (setq imenu-in-class-name nil))
+
+                  (setq imenu-nesting-level (1- imenu-nesting-level))))
+
+                (cond
+
+                 (imenu-in-namespace-declaration
+                  (cond
+
+                   ((or (string= token "{")
+                        (string= token ";"))
+                    (setq imenu-in-namespace-with-brackets (string= token "{"))
+                    (setq imenu-open-namespace-level imenu-nesting-level)
+                    (setq imenu-namespace-index '())
+                    (push `("*definition*" . ,imenu-namespace-definition) 
imenu-namespace-index)
+                    (setq imenu-in-namespace-declaration nil))
+
+                   ((and (or (equal token 'T_STRING)
+                             (equal token 'T_NS_SEPARATOR))
+                         (setq imenu-namespace-definition token-start)
+                         (setq imenu-in-namespace-name (concat 
imenu-in-namespace-name (substring string (1- token-start) (1- token-end))))))))
+
+                 (imenu-in-class-declaration
+                  (cond
+
+                   ((string= token "{")
+                    (setq imenu-open-class-level imenu-nesting-level)
+                    (setq imenu-in-class-declaration nil)
+                    (setq imenu-class-index '())
+                    (push `("*definition*" . ,imenu-class-definition) 
imenu-class-index))
+
+                   ((and (equal token 'T_STRING)
+                         (not imenu-in-class-name))
+                    (setq imenu-class-definition token-start)
+                    (setq imenu-in-class-name (substring string (1- 
token-start) (1- token-end))))))
+
+                 (imenu-in-function-declaration
+                  (cond
+
+                   ((or (string= token "{")
+                        (string= token ";"))
+                    (when imenu-in-function-name
+                      (if imenu-in-class-name
+                          (push `(,imenu-in-function-name . 
,imenu-in-function-index) imenu-class-index)
+                        (if imenu-in-namespace-name
+                            (push `(,imenu-in-function-name . 
,imenu-in-function-index) imenu-namespace-index)
+                          (push `(,imenu-in-function-name . 
,imenu-in-function-index) imenu-index))))
+                    (setq imenu-in-function-name nil)
+                    (setq imenu-in-function-declaration nil))
+
+                   ((and (equal token 'T_STRING)
+                         (not imenu-in-function-name))
+                    (setq imenu-in-function-name (substring string (1- 
token-start) (1- token-end)))
+                    (setq imenu-in-function-index token-start))))
+
+                 (t (cond
+
+                     ((and (not imenu-in-namespace-name)
+                           (equal token 'T_NAMESPACE))
+                      (setq imenu-in-namespace-name nil)
+                      (setq imenu-in-namespace-declaration t))
+
+                     ((and (not imenu-in-class-name)
+                           (or (equal token 'T_CLASS)
+                               (equal token 'T_INTERFACE)))
+                      (setq imenu-in-class-name nil)
+                      (setq imenu-in-class-declaration t))
+
+                     ((and (not imenu-in-function-name)
+                           (equal token 'T_FUNCTION))
+                      (setq imenu-in-function-name nil)
+                      (setq imenu-in-function-declaration t)))))
+
+                (when (and (equal next-token 'END_PARSE)
+                           imenu-in-namespace-name
+                           (not imenu-in-namespace-with-brackets))
+                  (let ((imenu-add-list (nreverse imenu-namespace-index)))
+                    (push `(,imenu-in-namespace-name . ,imenu-add-list) 
imenu-index))
+                  (setq imenu-in-namespace-name nil))
+
+
+                ;; INDENTATION LOGIC
+
+                ;; Keep track of round bracket level
+                (when (string= token "(")
+                  (setq round-bracket-level (1+ round-bracket-level)))
+                (when (string= token ")")
+                  (setq round-bracket-level (1- round-bracket-level))
+                  (when first-token-on-line
+                    (setq first-token-is-nesting-decrease t)))
+
+                ;; Keep track of square bracket level
+                (when (string= token "[")
+                  (setq square-bracket-level (1+ square-bracket-level)))
+                (when (string= token "]")
+                  (setq square-bracket-level (1- square-bracket-level))
+                  (when first-token-on-line
+                    (setq first-token-is-nesting-decrease t)))
+
+                ;; Handle INLINE_HTML blocks
+                (when (equal token 'T_INLINE_HTML)
+
+                  ;; Flag whether inline-html is whitespace or not
+                  (setq inline-html-is-whitespace (string= (string-trim 
(substring string (1- token-start) (1- token-end))) ""))
+
+                  (when first-token-on-line
+                    (setq first-token-is-inline-html t))
+
+                  (let ((inline-html-indents 
(phps-mode-functions--get-inline-html-indentation (substring string (1- 
token-start) (1- token-end)) inline-html-indent inline-html-tag-level 
inline-html-curly-bracket-level inline-html-square-bracket-level 
inline-html-round-bracket-level)))
+
+                    (phps-mode-debug-message
+                     (message "Received inline html indent: %s from inline 
HTML: '%s'" inline-html-indents (substring string (1- token-start) (1- 
token-end))))
+
+                    ;; Update indexes
+                    (setq inline-html-indent (nth 1 inline-html-indents))
+                    (setq inline-html-tag-level (nth 2 inline-html-indents))
+                    (setq inline-html-curly-bracket-level (nth 3 
inline-html-indents))
+                    (setq inline-html-square-bracket-level (nth 4 
inline-html-indents))
+                    (setq inline-html-round-bracket-level (nth 5 
inline-html-indents))
+
+                    (phps-mode-debug-message
+                     (message "First token is inline html: %s" 
first-token-is-inline-html))
+
+                    ;; Does inline html span several lines or starts a new 
line?
+                    (when (or (> token-end-line-number token-start-line-number)
+                              first-token-is-inline-html)
+
+                      ;; Token does not only contain white-space?
+                      (unless inline-html-is-whitespace
+                        (let ((token-line-number-diff token-start-line-number))
+                          ;; Iterate lines here and add indents
+                          (dolist (item (nth 0 inline-html-indents))
+                            ;; Skip first line unless first token on line was 
inline-html
+                            (when (or (not (= token-line-number-diff 
token-start-line-number))
+                                      first-token-is-inline-html)
+                              (unless (gethash token-line-number-diff 
line-indents)
+                                (puthash token-line-number-diff (list item 0) 
line-indents)
+                                (phps-mode-debug-message
+                                 (message "Putting indent at line %s to %s 
from inline HTML" token-line-number-diff item))))
+                            (setq token-line-number-diff (1+ 
token-line-number-diff))))))))
+
+                ;; Keep track of when we are inside a class definition
+                (if in-class-declaration
+                    (if (string= token "{")
+                        (progn
+                          (setq in-class-declaration nil)
+                          (setq in-class-declaration-level 0)
+
+                          (unless class-declaration-started-this-line
+                            (setq column-level (1- column-level))
+                            (pop nesting-stack))
+
+                          (when first-token-on-line
+                            (setq first-token-is-nesting-decrease t))
+
+                          )
+                      (when first-token-on-line
+                        (setq in-class-declaration-level 1)))
+
+                  ;; If ::class is used as a magical class constant it should 
not be considered start of a class declaration
+                  (when (and (equal token 'T_CLASS)
+                             (or (not previous-token)
+                                 (not (equal previous-token 
'T_PAAMAYIM_NEKUDOTAYIM))))
+                    (setq in-class-declaration t)
+                    (setq in-class-declaration-level 1)
+                    (setq class-declaration-started-this-line t)))
+
+                ;; Keep track of curly bracket level
+                (when (or (equal token 'T_CURLY_OPEN)
+                          (equal token 'T_DOLLAR_OPEN_CURLY_BRACES)
+                          (string= token "{"))
+                  (setq curly-bracket-level (1+ curly-bracket-level)))
+                (when (string= token "}")
+                  (setq curly-bracket-level (1- curly-bracket-level))
+
+                  (when (and switch-curly-stack
+                             (= (1+ curly-bracket-level) (car 
switch-curly-stack)))
+
+                    (phps-mode-debug-message
+                     (message "Ended switch curly stack at %s" 
curly-bracket-level))
+
+                    (setq allow-custom-column-decrement t)
+                    (pop nesting-stack)
+                    (setq alternative-control-structure-level (1- 
alternative-control-structure-level))
+                    (pop switch-curly-stack))
+                  
+                  (when first-token-on-line
+                    (setq first-token-is-nesting-decrease t)))
+
+                ;; Keep track of ending alternative control structure level
+                (when (or (equal token 'T_ENDIF)
+                          (equal token 'T_ENDWHILE)
+                          (equal token 'T_ENDFOR)
+                          (equal token 'T_ENDFOREACH)
+                          (equal token 'T_ENDSWITCH))
+                  (setq alternative-control-structure-level (1- 
alternative-control-structure-level))
+                  ;; (message "Found ending alternative token %s %s" token 
alternative-control-structure-level)
+
+                  (when (and (equal token 'T_ENDSWITCH)
+                             switch-case-alternative-stack)
+
+                    (phps-mode-debug-message
+                     (message "Ended alternative switch stack at %s" 
alternative-control-structure-level))
+                    
+                    (pop switch-alternative-stack)
+                    (pop switch-case-alternative-stack)
+                    (setq allow-custom-column-decrement t)
+                    (pop nesting-stack)
+                    (setq alternative-control-structure-level (1- 
alternative-control-structure-level)))
+
+                  (when first-token-on-line
+                    (setq first-token-is-nesting-decrease t)))
+
+                ;; When we encounter a token except () after a 
control-structure
+                (when (and after-special-control-structure
+                           (= after-special-control-structure 
round-bracket-level)
+                           (not (string= token ")"))
+                           (not (string= token "(")))
+
+                  ;; Handle the else if case
+                  (if (equal 'T_IF token)
+                      (setq after-special-control-structure-token token)
+
+                    ;; Is token not a curly bracket - because that is a 
ordinary control structure syntax
+                    (if (string= token "{")
+
+                        ;; Save curly bracket level when switch starts
+                        (when (equal after-special-control-structure-token 
'T_SWITCH)
+
+                          (phps-mode-debug-message
+                           (message "Started switch curly stack at %s" 
curly-bracket-level))
+
+                          (push curly-bracket-level switch-curly-stack))
+
+                      ;; Is it the start of an alternative control structure?
+                      (if (string= token ":")
+
+                          (progn
+
+                            ;; Save alternative nesting level for switch
+                            (when (equal after-special-control-structure-token 
'T_SWITCH)
+
+                              (phps-mode-debug-message
+                               (message "Started switch alternative stack at 
%s" alternative-control-structure-level))
+
+                              (push alternative-control-structure-level 
switch-alternative-stack))
+
+                            (setq alternative-control-structure-level (1+ 
alternative-control-structure-level))
+
+                            (phps-mode-debug-message
+                             (message "\nIncreasing 
alternative-control-structure after %s %s to %s\n" 
after-special-control-structure-token token 
alternative-control-structure-level))
+                            )
+
+                        ;; Don't start inline control structures after a while 
($condition); expression
+                        (unless (string= token ";")
+                          (phps-mode-debug-message
+                           (message "\nStarted inline control-structure after 
%s at %s\n" after-special-control-structure-token token))
+
+                          (setq in-inline-control-structure t)
+                          (setq temp-pre-indent (1+ column-level)))))
+
+                    (setq after-special-control-structure nil)
+                    (setq after-special-control-structure-token nil)))
+
+                ;; Support extra special control structures (CASE)
+                (when (and after-extra-special-control-structure
+                           (string= token ":"))
+                  (setq alternative-control-structure-level (1+ 
alternative-control-structure-level))
+                  (when after-extra-special-control-structure-first-on-line
+                    (setq first-token-is-nesting-decrease t))
+                  (setq after-extra-special-control-structure nil))
+
+                ;; Keep track of concatenation
+                (if in-concatenation
+                    (when (or (string= token ";")
+                              (and (string= token ")")
+                                   (< round-bracket-level (car 
in-concatenation-round-bracket-level)))
+                              (and (string= token ",")
+                                   (= round-bracket-level (car 
in-concatenation-round-bracket-level))
+                                   (= square-bracket-level (car 
in-concatenation-square-bracket-level)))
+                              (and (string= token"]")
+                                   (< square-bracket-level (car 
in-concatenation-square-bracket-level))))
+                      (phps-mode-debug-message "Ended concatenation")
+                      (pop in-concatenation-round-bracket-level)
+                      (pop in-concatenation-square-bracket-level)
+                      (unless in-concatenation-round-bracket-level
+                        (setq in-concatenation nil))
+                      (setq in-concatenation-level (1- 
in-concatenation-level)))
+                  (when (and (> next-token-start-line-number 
token-end-line-number)
+                             (or (string= token ".")
+                                 (string= next-token ".")))
+                    (phps-mode-debug-message "Started concatenation")
+                    (setq in-concatenation t)
+                    (push round-bracket-level 
in-concatenation-round-bracket-level)
+                    (push square-bracket-level 
in-concatenation-square-bracket-level)
+                    (setq in-concatenation-level (1+ in-concatenation-level))))
+
+                ;; Did we reach a semicolon inside a inline block? Close the 
inline block
+                (when (and in-inline-control-structure
+                           (string= token ";")
+                           (not special-control-structure-started-this-line))
+                  (setq in-inline-control-structure nil))
+
+                ;; Did we encounter a token that supports alternative and 
inline control structures?
+                (when (or (equal token 'T_IF)
+                          (equal token 'T_WHILE)
+                          (equal token 'T_FOR)
+                          (equal token 'T_FOREACH)
+                          (equal token 'T_SWITCH)
+                          (equal token 'T_ELSE)
+                          (equal token 'T_ELSEIF)
+                          (equal token 'T_DEFAULT))
+                  (setq after-special-control-structure round-bracket-level)
+                  (setq after-special-control-structure-token token)
+                  (setq nesting-key token)
+                  (setq special-control-structure-started-this-line t)
+
+                  ;; ELSE and ELSEIF after a IF, ELSE, ELESIF
+                  ;; and DEFAULT after a CASE
+                  ;; should decrease alternative control structure level
+                  (when (and nesting-stack
+                             (string= (car (cdr (cdr (cdr (car 
nesting-stack))))) ":")
+                             (or
+                              (and (or (equal token 'T_ELSE)
+                                       (equal token 'T_ELSEIF))
+                                   (or (equal (car (cdr (cdr (car 
nesting-stack)))) 'T_IF)
+                                       (equal (car (cdr (cdr (car 
nesting-stack)))) 'T_ELSEIF)
+                                       (equal (car (cdr (cdr (car 
nesting-stack)))) 'T_ELSE)))
+                              (and (equal token 'T_DEFAULT)
+                                   (equal (car (cdr (cdr (car 
nesting-stack)))) 'T_CASE))))
+                    (setq alternative-control-structure-level (1- 
alternative-control-structure-level))
+
+                    (when first-token-on-line
+                      (setq first-token-is-nesting-decrease t))
+
+                    (phps-mode-debug-message
+                     (message "\nDecreasing alternative control structure 
nesting at %s to %s\n" token alternative-control-structure-level)))
+
+                  )
+
+                ;; Keep track of assignments
+                (when in-assignment
+                  (when (or (string= token ";")
+                            (and (string= token ")")
+                                 (or (< round-bracket-level (car 
in-assignment-round-bracket-level))
+                                     (and
+                                      (= round-bracket-level (car 
in-assignment-round-bracket-level))
+                                      (= square-bracket-level (car 
in-assignment-square-bracket-level))
+                                      (or (string= next-token ")")
+                                          (string= next-token "]")))))
+                            (and (string= token ",")
+                                 (= round-bracket-level (car 
in-assignment-round-bracket-level))
+                                 (= square-bracket-level (car 
in-assignment-square-bracket-level)))
+                            (and (string= token "]")
+                                 (or (< square-bracket-level (car 
in-assignment-square-bracket-level))
+                                     (and
+                                      (= square-bracket-level (car 
in-assignment-square-bracket-level))
+                                      (= round-bracket-level (car 
in-assignment-round-bracket-level))
+                                      (or (string= next-token "]")
+                                          (string= next-token ")")))))
+                            (and (equal token 'T_FUNCTION)
+                                 (= round-bracket-level (car 
in-assignment-round-bracket-level))))
+
+                    ;; NOTE Ending an assignment because of a T_FUNCTION token 
is to support PSR-2 Closures
+                    
+                    (phps-mode-debug-message
+                     (message "Ended assignment %s at %s %s" 
in-assignment-level token next-token))
+                    (pop in-assignment-square-bracket-level)
+                    (pop in-assignment-round-bracket-level)
+                    (unless in-assignment-round-bracket-level
+                      (setq in-assignment nil))
+                    (setq in-assignment-level (1- in-assignment-level))
+
+                    ;; Did we end two assignment at once?
+                    (when (and
+                           in-assignment-round-bracket-level
+                           in-assignment-square-bracket-level
+                           (= round-bracket-level (car 
in-assignment-round-bracket-level))
+                           (= square-bracket-level (car 
in-assignment-square-bracket-level))
+                           (or (string= next-token ")")
+                               (string= next-token "]")))
+                      (phps-mode-debug-message
+                       (message "Ended another assignment %s at %s %s" 
in-assignment-level token next-token))
+                      (pop in-assignment-square-bracket-level)
+                      (pop in-assignment-round-bracket-level)
+                      (unless in-assignment-round-bracket-level
+                        (setq in-assignment nil))
+                      (setq in-assignment-level (1- in-assignment-level)))
+
+                    ))
+
+                (when (and (not after-special-control-structure)
+                           (or (string= token "=")
+                               (equal token 'T_DOUBLE_ARROW)
+                               (equal token 'T_CONCAT_EQUAL)
+                               (equal token 'T_POW_EQUAL)
+                               (equal token 'T_DIV_EQUAL)
+                               (equal token 'T_PLUS_EQUAL)
+                               (equal token 'T_MINUS_EQUAL)
+                               (equal token 'T_MUL_EQUAL)
+                               (equal token 'T_MOD_EQUAL)
+                               (equal token 'T_SL_EQUAL)
+                               (equal token 'T_SR_EQUAL)
+                               (equal token 'T_AND_EQUAL)
+                               (equal token 'T_OR_EQUAL)
+                               (equal token 'T_XOR_EQUAL)
+                               (equal token 'T_COALESCE_EQUAL)))
+                  (phps-mode-debug-message "Started assignment")
+                  (setq in-assignment t)
+                  (push round-bracket-level in-assignment-round-bracket-level)
+                  (push square-bracket-level 
in-assignment-square-bracket-level)
+                  (setq in-assignment-level (1+ in-assignment-level)))
+
+                ;; Second token after a object-operator
+                (when (and
+                       in-object-operator
+                       in-object-operator-round-bracket-level
+                       in-object-operator-square-bracket-level
+                       (<= round-bracket-level (car 
in-object-operator-round-bracket-level))
+                       (<= square-bracket-level (car 
in-object-operator-square-bracket-level))
+                       (not (or
+                             (equal next-token 'T_OBJECT_OPERATOR)
+                             (equal next-token 'T_PAAMAYIM_NEKUDOTAYIM))))
+                  (phps-mode-debug-message
+                   (message "Ended object-operator at %s %s at level %s" token 
next-token in-object-operator-level))
+                  (pop in-object-operator-round-bracket-level)
+                  (pop in-object-operator-square-bracket-level)
+                  (setq in-object-operator-level (1- in-object-operator-level))
+                  (when (= in-object-operator-level 0)
+                    (setq in-object-operator nil)))
+
+                ;; First token after a object-operator
+                (when after-object-operator
+                  (when (or (equal next-token 'T_STRING)
+                            (string= next-token "("))
+                    (progn
+                      (phps-mode-debug-message
+                       (message "Started object-operator at %s %s on level %s" 
 token next-token in-object-operator-level))
+                      (push round-bracket-level 
in-object-operator-round-bracket-level)
+                      (push square-bracket-level 
in-object-operator-square-bracket-level)
+                      (setq in-object-operator t)
+                      (setq in-object-operator-level (1+ 
in-object-operator-level))))
+                  (setq after-object-operator nil))
+
+                ;; Starting object-operator?
+                (when (and (or (equal token 'T_OBJECT_OPERATOR)
+                               (equal token 'T_PAAMAYIM_NEKUDOTAYIM))
+                           (equal next-token 'T_STRING))
+                  (phps-mode-debug-message
+                   (message "After object-operator at %s level %s"  token 
in-object-operator-level))
+                  (setq after-object-operator t))
+
+                ;; Keep track of return expressions
+                (when in-return
+                  (when (and (string= token ";")
+                             (= curly-bracket-level (car 
in-return-curly-bracket-level)))
+
+                    (phps-mode-debug-message (message "Ended return at %s" 
token))
+                    (pop in-return-curly-bracket-level)
+                    (unless in-return-curly-bracket-level
+                      (setq in-return nil))
+                    (setq in-return-level (1- in-return-level))))
+                (when (equal token 'T_RETURN)
+                  (phps-mode-debug-message "Started return")
+                  (setq in-return t)
+                  (push curly-bracket-level in-return-curly-bracket-level)
+                  (setq in-return-level (1+ in-return-level)))
+
+                ;; Did we encounter a token that supports extra special 
alternative control structures?
+                (when (equal token 'T_CASE)
+                  (setq after-extra-special-control-structure t)
+                  (setq nesting-key token)
+                  (setq after-extra-special-control-structure-first-on-line 
first-token-on-line)
+
+                  (when (and switch-case-alternative-stack
+                             (= (1- alternative-control-structure-level) (car 
switch-case-alternative-stack)))
+
+                    (phps-mode-debug-message
+                     (message "Found CASE %s vs %s" (1- 
alternative-control-structure-level) (car switch-case-alternative-stack)))
+
+                    (setq alternative-control-structure-level (1- 
alternative-control-structure-level))
+                    (when first-token-on-line
+                      (setq first-token-is-nesting-decrease t))
+                    (pop switch-case-alternative-stack))
+
+                  (push alternative-control-structure-level 
switch-case-alternative-stack)))
+
+              ;; Do we have one token look-ahead?
+              (when token
+
+                (phps-mode-debug-message (message "Processing token: %s" 
token))
+                
+                ;; Calculate nesting
+                (setq nesting-end (+ round-bracket-level square-bracket-level 
curly-bracket-level alternative-control-structure-level in-assignment-level 
in-class-declaration-level in-concatenation-level in-return-level 
in-object-operator-level))
+
+                ;; Keep track of whether we are inside a HEREDOC or NOWDOC
+                (when (equal token 'T_START_HEREDOC)
+                  (setq in-heredoc t)
+                  (setq in-heredoc-started-this-line t))
+                (when (equal token 'T_END_HEREDOC)
+                  (setq in-heredoc nil)
+                  (setq in-heredoc-ended-this-line t))
+
+                ;; Has nesting increased?
+                (when (and nesting-stack
+                           (<= nesting-end (car (car nesting-stack))))
+                  (let ((nesting-decrement 0))
+
+                    ;; Handle case were nesting has decreased less than next 
as well
+                    (while (and nesting-stack
+                                (<= nesting-end (car (car nesting-stack))))
+                      (phps-mode-debug-message
+                       (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)
+                      (setq nesting-decrement (1+ nesting-decrement)))
+
+                    (if first-token-is-nesting-decrease
+
+                        (progn
+                          ;; Decrement column
+                          (if allow-custom-column-decrement
+                              (progn
+                                (phps-mode-debug-message
+                                 (message "Doing custom decrement 1 from %s to 
%s" column-level (- column-level (- nesting-start nesting-end))))
+                                (setq column-level (- column-level (- 
nesting-start nesting-end)))
+                                (setq allow-custom-column-decrement nil))
+                            (phps-mode-debug-message
+                             (message "Doing regular decrement 1 from %s to 
%s" column-level (1- column-level)))
+                            (setq column-level (- column-level 
nesting-decrement)))
+
+                          ;; Prevent negative column-values
+                          (when (< column-level 0)
+                            (setq column-level 0)))
+
+                      (unless temp-post-indent
+                        (phps-mode-debug-message
+                         (message "Temporary setting post indent %s" 
column-level))
+                        (setq temp-post-indent column-level))
+
+                      ;; Decrement column
+                      (if allow-custom-column-decrement
+                          (progn
+                            (phps-mode-debug-message
+                             (message "Doing custom decrement 2 from %s to %s" 
column-level (- column-level (- nesting-start nesting-end))))
+                            (setq temp-post-indent (- temp-post-indent (- 
nesting-start nesting-end)))
+                            (setq allow-custom-column-decrement nil))
+                        (setq temp-post-indent (- temp-post-indent 
nesting-decrement)))
+
+                      ;; Prevent negative column-values
+                      (when (< temp-post-indent 0)
+                        (setq temp-post-indent 0))
+
+                      )))
+
+                ;; Are we on a new line or is it the last token of the buffer?
+                (if (> next-token-start-line-number token-start-line-number)
+                    (progn
+
+
+                      ;; ;; Start indentation might differ from ending 
indentation in cases like } else {
+                      (setq column-level-start column-level)
+
+                      ;; Support temporarily pre-indent
+                      (when temp-pre-indent
+                        (setq column-level-start temp-pre-indent)
+                        (setq temp-pre-indent nil))
+
+                      ;; HEREDOC lines should have zero indent
+                      (when (or (and in-heredoc
+                                     (not in-heredoc-started-this-line))
+                                in-heredoc-ended-this-line)
+                        (setq column-level-start 0))
+
+                      ;; Inline HTML should have zero indent
+                      (when (and first-token-is-inline-html
+                                 (not inline-html-is-whitespace))
+                        (phps-mode-debug-message
+                         (message "Setting column-level to inline HTML indent: 
%s" inline-html-indent-start))
+                        (setq column-level-start inline-html-indent-start))
+
+                      ;; Save line indent
+                      (phps-mode-debug-message
+                       (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))
+
+                      (when (and (> token-start-line-number 0)
+                                 (or
+                                  (not first-token-is-inline-html)
+                                  inline-html-is-whitespace))
+                        (phps-mode-debug-message
+                         (message "Putting indent on line %s to %s at #C" 
token-start-line-number column-level-start))
+                        (puthash token-start-line-number `(,column-level-start 
,tuning-level) line-indents))
+
+                      ;; Support trailing indent decrements
+                      (when temp-post-indent
+                        (setq column-level temp-post-indent)
+                        (setq temp-post-indent nil))
+
+                      ;; Increase indentation
+                      (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)))))
+
+                          (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)))
+
+                          (phps-mode-debug-message
+                           (message "\nPushing (%s %s %s %s) to nesting-stack 
since %s is greater than %s or stack is empty\n" nesting-start nesting-end 
nesting-key token nesting-end (car (cdr (car nesting-stack))))
+                           )
+                          (push `(,nesting-stack-end ,nesting-end ,nesting-key 
,token) nesting-stack)))
+
+
+                      ;; Does token span over several lines and is it not a 
INLINE_HTML token?
+                      (when (and (> token-end-line-number 
token-start-line-number)
+                                 (not (equal token 'T_INLINE_HTML)))
+                        (let ((column-level-end column-level))
+
+                          ;; HEREDOC lines should have zero indent
+                          (when (or (and in-heredoc
+                                         (not in-heredoc-started-this-line))
+                                    in-heredoc-ended-this-line)
+                            (setq column-level-end 0))
+
+                          ;; (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-end tuning-level)
+
+                          ;; Indent doc-comment lines with 1 tuning
+                          (when (equal token 'T_DOC_COMMENT)
+                            (setq tuning-level 1))
+
+                          (let ((token-line-number-diff (1- (- 
token-end-line-number token-start-line-number))))
+                            (while (>= token-line-number-diff 0)
+                              (phps-mode-debug-message
+                               (message "Putting indent on line %s to %s at 
#A" (- token-end-line-number token-line-number-diff) column-level-end))
+                              (puthash (- token-end-line-number 
token-line-number-diff) `(,column-level-end ,tuning-level) line-indents)
+                              ;; (message "Saved line %s indent %s %s" (- 
token-end-line-number token-line-number-diff) column-level tuning-level)
+                              (setq token-line-number-diff (1- 
token-line-number-diff))))
+
+                          ;; Rest tuning-level used for comments
+                          (setq tuning-level 0)))
+
+                      ;; Indent token-less lines here in between last tokens 
if distance is more than 1 line
+                      (when (and (> next-token-start-line-number (1+ 
token-end-line-number))
+                                 (not (equal token 'T_CLOSE_TAG)))
+
+                        (phps-mode-debug-message
+                         (message "\nDetected token-less lines between %s and 
%s, should have indent: %s\n" token-end-line-number 
next-token-start-line-number column-level))
+
+                        (let ((token-line-number-diff (1- (- 
next-token-start-line-number token-end-line-number))))
+                          (while (> token-line-number-diff 0)
+                            (phps-mode-debug-message
+                             (message "Putting indent at line %s indent %s at 
#B" (- next-token-start-line-number token-line-number-diff) column-level))
+                            (puthash (- next-token-start-line-number 
token-line-number-diff) `(,column-level ,tuning-level) line-indents)
+                            (setq token-line-number-diff (1- 
token-line-number-diff)))))
+
+
+                      ;; Calculate indentation level at start of line
+                      (setq nesting-start (+ round-bracket-level 
square-bracket-level curly-bracket-level alternative-control-structure-level 
in-assignment-level in-class-declaration-level in-concatenation-level 
in-return-level in-object-operator-level))
+
+                      ;; Set initial values for tracking first token
+                      (when (> token-start-line-number last-line-number)
+                        (setq inline-html-indent-start inline-html-indent)
+                        (setq first-token-on-line t)
+                        (setq first-token-is-nesting-decrease nil)
+                        (setq first-token-is-inline-html nil)
+                        (setq in-class-declaration-level 0)
+                        (setq class-declaration-started-this-line nil)
+                        (setq in-heredoc-started-this-line nil)
+                        (setq special-control-structure-started-this-line nil)
+
+                        ;; When line ends with multi-line inline-html flag 
first token as inline-html
+                        (when (and
+                               (equal token 'T_INLINE_HTML)
+                               (not inline-html-is-whitespace)
+                               (> token-end-line-number 
token-start-line-number))
+
+                          (setq inline-html-is-whitespace
+                                (not (null
+                                      (string-match "[\n\C-m][ \t]+$" 
(substring string (1- token-start) (1- token-end))))))
+                          (phps-mode-debug-message
+                           (message "Trailing inline html line is whitespace: 
%s" inline-html-is-whitespace))
+                          (phps-mode-debug-message
+                           (message "Setting first-token-is-inline-html to 
true since last token on line is inline-html and spans several lines"))
+                          (setq first-token-is-inline-html t))))
+
+                  ;; Current token is not first if it's not <?php or <?=
+                  (unless (or (equal token 'T_OPEN_TAG)
+                              (equal token 'T_OPEN_TAG_WITH_ECHO))
+                    (setq first-token-on-line nil))
+
+                  (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)
+                      (setq tuning-level 1))
+
+                    (let ((token-line-number-diff (1- (- token-end-line-number 
token-start-line-number))))
+                      (while (>= token-line-number-diff 0)
+                        (phps-mode-debug-message
+                         (message "Putting indent on line %s to %s at #E" (- 
token-end-line-number token-line-number-diff) column-level))
+                        (puthash (- token-end-line-number 
token-line-number-diff) `(,column-level ,tuning-level) line-indents)
+                        (setq token-line-number-diff (1- 
token-line-number-diff))))
+                    (setq tuning-level 0))))
+
+              ;; Update current token
+              (setq previous-token token)
+              (setq token next-token)
+              (setq token-start next-token-start)
+              (setq token-end next-token-end)
+              (setq token-start-line-number next-token-start-line-number)
+              (setq token-end-line-number next-token-end-line-number)
+              (setq token-number (1+ token-number))))
+          (list (nreverse imenu-index) line-indents)))
+    (list nil nil)))
+
+(defun phps-mode-functions-indent-line ()
+  "Indent line."
+  (phps-mode-debug-message (message "Indent line"))
+  (phps-mode-functions-process-current-buffer)
+  (if phps-mode-functions-lines-indent
+      (let ((line-number (line-number-at-pos (point))))
+        (phps-mode-debug-message (message "Found lines indent index, 
indenting.."))
+        (let ((indent (gethash line-number phps-mode-functions-lines-indent)))
+          (if indent
+              (progn
+                (let ((indent-sum (+ (* (car indent) tab-width) (car (cdr 
indent))))
+                      (old-indentation (current-indentation))
+                      (line-start (line-beginning-position)))
+
+                  (unless old-indentation
+                    (setq old-indentation 0))
+
+                  ;; Only continue if current indentation is wrong
+                  (if (not (equal indent-sum old-indentation))
+                      (progn
+
+                        (setq-local phps-mode-functions-allow-after-change nil)
+                        (indent-line-to indent-sum)
+                        (setq-local phps-mode-functions-allow-after-change t)
+
+                        (let ((indent-diff (- (current-indentation) 
old-indentation)))
+
+
+                          ;; When indent is changed the trailing tokens and 
states just need to adjust their positions, this will improve speed of 
indent-region a lot
+                          (phps-mode-lexer-move-tokens line-start indent-diff)
+                          (phps-mode-lexer-move-states line-start indent-diff)
+                          (phps-mode-functions-move-imenu-index line-start 
indent-diff)
+
+                          (phps-mode-debug-message
+                           (message "Lexer tokens after move: %s" 
phps-mode-lexer-tokens)
+                           (message "Lexer states after move: %s" 
phps-mode-lexer-states))
+
+                          ;; Reset change flag
+                          (phps-mode-functions--reset-changes)
+                          (phps-mode-functions--cancel-idle-timer)
+
+                          ;; Update last buffer states
+                          (setq-local phps-mode-lexer-buffer-length (1- 
(point-max)))
+                          (setq-local phps-mode-lexer-buffer-contents 
(buffer-substring-no-properties (point-min) (point-max)))
+
+                          ))))))))
+    (phps-mode-debug-message "Did not find lines indent index, skipping 
indenting..")
+    (message "Did not find lines indent index, skipping indenting..")))
+
+(defun phps-mode-functions--reset-changes ()
+  "Reset change stack."
+  (setq-local phps-mode-functions-buffer-changes nil))
+
+(defun phps-mode-functions--get-changes ()
+  "Get change stack."
+  phps-mode-functions-buffer-changes)
+
+(defun phps-mode-functions--cancel-idle-timer ()
+  "Cancel idle timer."
+  (phps-mode-debug-message (message "Cancelled idle timer"))
+  (when phps-mode-functions-idle-timer
+    (cancel-timer phps-mode-functions-idle-timer)
+    (setq-local phps-mode-functions-idle-timer nil)))
+
+(defun phps-mode-functions--start-idle-timer ()
+  "Start idle timer."
+  (phps-mode-debug-message (message "Enqueued idle timer"))
+  (when (boundp 'phps-mode-idle-interval)
+    (setq-local phps-mode-functions-idle-timer (run-with-idle-timer 
phps-mode-idle-interval nil #'phps-mode-lexer-run-incremental 
(current-buffer)))))
+
+(defun phps-mode-functions-after-change (start stop length)
+  "Track buffer change from START to STOP with LENGTH."
+  (phps-mode-debug-message
+   (message "After change %s - %s, length: %s" start stop length))
+
+  (if phps-mode-functions-allow-after-change
+      (progn
+        (phps-mode-debug-message (message "After change registration is 
enabled"))
+        
+        ;; If we haven't scheduled incremental lexer before - do it
+        (when (and (boundp 'phps-mode-idle-interval)
+                   phps-mode-idle-interval
+                   (not phps-mode-functions-idle-timer))
+
+          ;; Reset imenu
+          (when (and (boundp 'imenu--index-alist)
+                     imenu--index-alist)
+            (setq-local imenu--index-alist nil)
+            (phps-mode-debug-message (message "Cleared Imenu index")))
+
+          (phps-mode-functions--start-idle-timer))
+
+        ;; Save change in changes stack
+        (push `(,start ,stop ,length ,(point-max) 
,(buffer-substring-no-properties (point-min) (point-max))) 
phps-mode-functions-buffer-changes))
+    (phps-mode-debug-message (message "After change registration is 
disabled"))))
+
+(defun phps-mode-functions-imenu-create-index ()
+  "Get Imenu for current buffer."
+  (phps-mode-functions-process-current-buffer)
+  phps-mode-functions-imenu)
+
+(defun phps-mode-functions-comment-region (beg end &optional _arg)
+  "Comment region from BEG to END with optional ARG."
+  ;; Iterate tokens from beginning to end and comment out all PHP code
+  (when-let ((tokens phps-mode-lexer-tokens))
+    (let ((token-comment-start nil)
+          (token-comment-end nil)
+          (in-token-comment nil)
+          (offset 0))
+      (dolist (token tokens)
+        (let ((token-label (car token))
+              (token-start (car (cdr token)))
+              (token-end (cdr (cdr token))))
+          (when (and (>= token-start beg)
+                     (<= token-end end))
+
+            (if in-token-comment
+                (cond
+                 ((or
+                   (equal token-label 'T_COMMENT)
+                   (equal token-label 'T_DOC_COMMENT)
+                   (equal token-label 'T_CLOSE_TAG))
+                  (setq in-token-comment nil))
+                 (t (setq token-comment-end token-end)))
+
+              ;; When we have a start and end of comment, comment it out
+              (when (and
+                     token-comment-start
+                     token-comment-end)
+                (let ((offset-comment-start (+ token-comment-start offset))
+                      (offset-comment-end))
+                  (save-excursion
+                    (goto-char offset-comment-start)
+                    (insert "/* "))
+                  (setq offset (+ offset 3))
+                  (setq offset-comment-end (+ token-comment-end offset))
+                  (save-excursion
+                    (goto-char offset-comment-end)
+                    (insert " */"))
+                  (setq offset (+ offset 3))
+                  (phps-mode-debug-message
+                   (message "Commented out %s-%s" offset-comment-start 
offset-comment-end)))
+                (setq token-comment-start nil)
+                (setq token-comment-end nil))
+
+              (cond
+               ((or
+                 (equal token-label 'T_INLINE_HTML)
+                 (equal token-label 'T_OPEN_TAG)
+                 (equal token-label 'T_OPEN_TAG_WITH_ECHO)))
+               (t
+                (phps-mode-debug-message
+                 (message "Comment should start at %s %s" token-label 
token-start))
+                (setq token-comment-start token-start)
+                (setq in-token-comment t)))))))
+
+      ;; When we have a start and end of comment, comment it out
+      (when (and
+             in-token-comment
+             token-comment-start
+             token-comment-end)
+        (let ((offset-comment-start (+ token-comment-start offset))
+              (offset-comment-end))
+          (save-excursion
+            (goto-char offset-comment-start)
+            (insert "/* "))
+          (setq offset (+ offset 3))
+          (setq offset-comment-end (+ token-comment-end offset))
+          (save-excursion
+            (goto-char offset-comment-end)
+            (insert " */"))
+          (setq offset (+ offset 3))
+          (phps-mode-debug-message
+           (message "Commented out trailing %s-%s" offset-comment-start 
offset-comment-end)))
+        (setq token-comment-start nil)
+        (setq token-comment-end nil)))))
+
+(defun phps-mode-functions-uncomment-region (beg end &optional _arg)
+  "Un-comment region from BEG to END with optional ARG."
+  ;; Iterate tokens from beginning to end and uncomment out all commented PHP 
code
+  (when-let ((tokens phps-mode-lexer-tokens))
+    (let ((offset 0))
+      (dolist (token tokens)
+        (let ((token-label (car token))
+              (token-start (car (cdr token)))
+              (token-end (cdr (cdr token))))
+          (when (and (>= token-start beg)
+                     (<= token-end end))
+            (when (or
+                   (equal token-label 'T_COMMENT)
+                   (equal token-label 'T_DOC_COMMENT))
+
+              (phps-mode-debug-message
+               (message "Un-comment comment at %s %s" token-label token-start 
token-end))
+
+              (let ((offset-comment-start (+ token-start offset))
+                    (offset-comment-end))
+
+                (if (equal token-label 'T_DOC_COMMENT)
+                    (progn
+                      (phps-mode-debug-message
+                       (message "Un-comment doc comment at %s-%s" token-start 
token-end))
+                      (save-excursion
+                        (goto-char offset-comment-start)
+                        (delete-char 4))
+                      (setq offset (- offset 4))
+                      (setq offset-comment-end (+ token-end offset))
+                      (save-excursion
+                        (goto-char offset-comment-end)
+                        (delete-char -4))
+                      (setq offset (- offset 4)))
+
+                  (phps-mode-debug-message
+                   (message "Un-comment comment starting at %s" token-start))
+
+                  (cond
+
+                   ((string=
+                     (buffer-substring-no-properties offset-comment-start (+ 
offset-comment-start 1))
+                     "#")
+                    (save-excursion
+                      (goto-char offset-comment-start)
+                      (delete-char 1))
+                    (setq offset (- offset 1)))
+                   ((string=
+                     (buffer-substring-no-properties offset-comment-start (+ 
offset-comment-start 2))
+                     "//")
+                    (save-excursion
+                      (goto-char offset-comment-start)
+                      (delete-char 2))
+                    (setq offset (- offset 2)))
+                   (t
+                    (save-excursion
+                      (goto-char offset-comment-start)
+                      (delete-char 3))
+                    (setq offset (- offset 3))))
+
+                  
+                  (setq offset-comment-end (+ token-end offset))
+                  (if (string=
+                       (buffer-substring-no-properties (- offset-comment-end 
3) offset-comment-end)
+                       " */")
+                      (progn
+                        (phps-mode-debug-message
+                         (message "Un-comment comment ending at %s" token-end))
+                        (save-excursion
+                          (goto-char offset-comment-end)
+                          (delete-char -3))
+                        (setq offset (- offset 3)))
+                    (phps-mode-debug-message
+                     (message "Do not un-comment comment ending at %s" 
token-end))))))))))))
+
+(provide 'phps-mode-analyzer)
 
-;;; phps-mode-lexer.el ends here
+;;; phps-mode-analyzer.el ends here
diff --git a/phps-mode-flymake.el b/phps-mode-flymake.el
index ead108d..b1d1078 100644
--- a/phps-mode-flymake.el
+++ b/phps-mode-flymake.el
@@ -27,8 +27,6 @@
 
 (require 'flymake)
 
-;; TODO Implement this
-
 (defun phps-mode-flymake-init ()
   "PHP specific init-cleanup routines.
 
diff --git a/phps-mode-functions.el b/phps-mode-functions.el
deleted file mode 100644
index 9466f17..0000000
--- a/phps-mode-functions.el
+++ /dev/null
@@ -1,1379 +0,0 @@
-;;; phps-mode-functions.el --- Mode functions for PHPs -*- lexical-binding: t 
-*-
-
-;; Copyright (C) 2018-2019  Free Software Foundation, Inc.
-
-;; This file is not part of GNU Emacs.
-
-;; This program is free software; you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation; either version 2, or (at
-;; your option) any later version.
-
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;; General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
-
-
-;;; Commentary:
-
-
-;;; Code:
-
-(require 'subr-x)
-(require 'phps-mode-lexer)
-
-(autoload 'phps-mode-runtime-debug-message "phps-mode")
-
-(require 'phps-mode-macros)
-
-(defvar phps-mode-functions-allow-after-change t
-  "Flag to tell us whether after change detection is enabled or not.")
-
-(defvar phps-mode-functions-buffer-changes nil
-  "A stack of buffer changes.")
-
-(defvar phps-mode-functions-idle-timer nil
-  "Timer object of idle timer.")
-
-(defvar phps-mode-functions-imenu nil
-  "The Imenu alist for current buffer, nil if none.")
-
-(defvar phps-mode-functions-lines-indent nil
-  "The indentation of each line in buffer, nil if none.")
-
-(defvar phps-mode-functions-processed-buffer nil
-  "Flag whether current buffer is processed or not.")
-
-(defun phps-mode-functions-get-processed-buffer ()
-  "Get flag for whether buffer is processed or not."
-  phps-mode-functions-processed-buffer)
-
-(defun phps-mode-functions-reset-processed-buffer ()
-  "Reset flag for whether buffer is processed or not."
-  (setq-local phps-mode-functions-processed-buffer nil))
-
-(defun phps-mode-functions-process-current-buffer ()
-  "Process current buffer, generate indentations and Imenu, trigger 
incremental lexer if we have change."
-  (interactive)
-  (phps-mode-debug-message (message "Process current buffer"))
-  (when phps-mode-functions-idle-timer
-    (phps-mode-debug-message (message "Trigger incremental lexer"))
-    (phps-mode-lexer-run-incremental (current-buffer))
-    (setq-local phps-mode-functions-processed-buffer nil))
-  (if (not phps-mode-functions-processed-buffer)
-      (progn
-        (phps-mode-debug-message (message "Buffer is not processed"))
-        (let ((processed (phps-mode-functions--process-tokens-in-string 
phps-mode-lexer-tokens (buffer-substring-no-properties (point-min) 
(point-max)))))
-          (phps-mode-debug-message (message "Processed result: %s" processed))
-          (setq-local phps-mode-functions-imenu (nth 0 processed))
-          (setq-local phps-mode-functions-lines-indent (nth 1 processed)))
-        (setq-local phps-mode-functions-processed-buffer t))
-    (phps-mode-debug-message (message "Buffer is already processed"))))
-
-(defun phps-mode-functions-get-moved-lines-indent (old-lines-indents 
start-line-number diff)
-  "Move OLD-LINES-INDENTS from START-LINE-NUMBER with DIFF points."
-  (let ((lines-indents (make-hash-table :test 'equal))
-        (line-number 1))
-    (when old-lines-indents
-      (let ((line-indent (gethash line-number old-lines-indents))
-            (new-line-number))
-        (while line-indent
-
-          (when (< line-number start-line-number)
-            ;; (message "Added new indent 3 %s from %s to %s" line-indent 
line-number line-number)
-            (puthash line-number line-indent lines-indents))
-
-          (when (and (> diff 0)
-                     (>= line-number start-line-number)
-                     (< line-number (+ start-line-number diff)))
-            ;; (message "Added new indent 2 %s from %s to %s" line-indent 
line-number line-number)
-            (puthash line-number (gethash start-line-number old-lines-indents) 
lines-indents))
-
-          (when (>= line-number start-line-number)
-            (setq new-line-number (+ line-number diff))
-            ;; (message "Added new indent %s from %s to %s" line-indent 
line-number new-line-number)
-            (puthash new-line-number line-indent lines-indents))
-
-          (setq line-number (1+ line-number))
-          (setq line-indent (gethash line-number old-lines-indents))))
-      lines-indents)))
-
-(defun phps-mode-functions-move-imenu-index (start diff)
-  "Moved imenu from START by DIFF points."
-  (when phps-mode-functions-imenu
-    (setq-local phps-mode-functions-imenu (phps-mode-functions-get-moved-imenu 
phps-mode-functions-imenu start diff))))
-
-(defun phps-mode-functions-move-lines-indent (start-line-number diff)
-  "Move lines indent from START-LINE-NUMBER with DIFF points."
-  (when phps-mode-functions-lines-indent
-    ;; (message "Moving line-indent index from %s with %s" start-line-number 
diff)
-    (setq-local phps-mode-functions-lines-indent 
(phps-mode-functions-get-moved-lines-indent phps-mode-functions-lines-indent 
start-line-number diff))))
-  
-(defun phps-mode-functions-get-lines-indent ()
-  "Return lines indent, process buffer if not done already."
-  (phps-mode-functions-process-current-buffer)
-  phps-mode-functions-lines-indent)
-
-(defun phps-mode-functions-get-imenu ()
-  "Return Imenu, process buffer if not done already."
-  (phps-mode-functions-process-current-buffer)
-  phps-mode-functions-imenu)
-
-(defun phps-mode-functions-get-moved-imenu (old-index start diff)
-  "Move imenu-index OLD-INDEX beginning from START with DIFF."
-  (let ((new-index '()))
-
-    (when old-index
-      (if (and (listp old-index)
-               (listp (car old-index)))
-          (dolist (item old-index)
-            (let ((sub-item (phps-mode-functions-get-moved-imenu item start 
diff)))
-              (push (car sub-item) new-index)))
-        (let ((item old-index))
-          (let ((item-label (car item)))
-            (if (listp (cdr item))
-                (let ((sub-item (phps-mode-functions-get-moved-imenu (cdr 
item) start diff)))
-                  (push `(,item-label . ,sub-item) new-index))
-              (let ((item-start (cdr item)))
-                (when (>= item-start start)
-                  (setq item-start (+ item-start diff)))
-                (push `(,item-label . ,item-start) new-index)))))))
-
-    (nreverse new-index)))
-
-(defun phps-mode-functions--get-lines-in-buffer (beg end)
-  "Return the number of lines in buffer between BEG and END."
-  (phps-mode-functions--get-lines-in-string (buffer-substring-no-properties 
beg end)))
-
-(defun phps-mode-functions--get-lines-in-string (string)
-  "Return the number of lines in STRING."
-  (let ((lines-in-string 0)
-        (start 0))
-    (while (string-match "[\n\C-m]" string start)
-      (setq start (match-end 0))
-      (setq lines-in-string (1+ lines-in-string)))
-    lines-in-string))
-
-(defun phps-mode-functions--get-inline-html-indentation (inline-html indent 
tag-level curly-bracket-level square-bracket-level round-bracket-level)
-  "Generate a list of indentation for each line in INLINE-HTML, working 
incrementally on INDENT, TAG-LEVEL, CURLY-BRACKET-LEVEL, SQUARE-BRACKET-LEVEL 
and ROUND-BRACKET-LEVEL."
-  (phps-mode-debug-message
-   (message "Calculating HTML indent for: '%s'" inline-html))
-
-  ;; Add trailing newline if missing
-  (unless (string-match "\n$" inline-html)
-    (setq inline-html (concat inline-html "\n")))
-
-  (let ((start 0)
-        (indent-start indent)
-        (indent-end indent)
-        (line-indents nil)
-        (first-object-on-line t)
-        (first-object-is-nesting-decrease nil))
-    (while (string-match 
"\\([\n\C-m]\\)\\|\\(<[a-zA-Z]+\\)\\|\\(</[a-zA-Z]+\\)\\|\\(/>\\)\\|\\(\\[\\)\\|\\()\\)\\|\\((\\)"
 inline-html start)
-      (let* ((end (match-end 0))
-             (string (substring inline-html (match-beginning 0) end)))
-
-        (cond
-
-         ((string= string "\n")
-
-          (let ((temp-indent indent))
-            (when first-object-is-nesting-decrease
-              (phps-mode-debug-message
-               (message "Decreasing indent with one since first object was a 
nesting decrease"))
-              (setq temp-indent (1- indent))
-              (when (< temp-indent 0)
-                (setq temp-indent 0)))
-            (push temp-indent line-indents))
-
-          (setq indent-end (+ tag-level curly-bracket-level 
square-bracket-level round-bracket-level))
-          (phps-mode-debug-message "Encountered a new-line")
-          (if (> indent-end indent-start)
-              (progn
-                (phps-mode-debug-message
-                  (message "Increasing indent since %s is above %s" indent-end 
indent-start))
-                (setq indent (1+ indent)))
-            (when (< indent-end indent-start)
-              (phps-mode-debug-message
-                (message "Decreasing indent since %s is below %s" indent-end 
indent-start))
-              (setq indent (1- indent))
-              (when (< indent 0)
-                (setq indent 0))))
-
-          (setq indent-start indent-end)
-          (setq first-object-on-line t)
-          (setq first-object-is-nesting-decrease nil))
-
-         ((string= string "(")
-          (setq round-bracket-level (1+ round-bracket-level)))
-         ((string= string ")")
-          (setq round-bracket-level (1- round-bracket-level)))
-
-         ((string= string "[")
-          (setq square-bracket-level (1+ square-bracket-level)))
-         ((string= string "]")
-          (setq square-bracket-level (1- square-bracket-level)))
-
-         ((string= string "{")
-          (setq curly-bracket-level (1+ curly-bracket-level)))
-         ((string= string "}")
-          (setq curly-bracket-level (1- curly-bracket-level)))
-
-         ((string-match "<[a-zA-Z]+" string)
-          (setq tag-level (1+ tag-level)))
-
-         ((string-match "\\(</[a-zA-Z]+\\)\\|\\(/>\\)" string)
-          (setq tag-level (1- tag-level)))
-
-         )
-
-        (when first-object-on-line
-          (unless (string= string "\n")
-            (setq first-object-on-line nil)
-            (setq indent-end (+ tag-level curly-bracket-level 
square-bracket-level round-bracket-level))
-            (when (< indent-end indent-start)
-              (phps-mode-debug-message "First object was nesting decrease")
-              (setq first-object-is-nesting-decrease t))))
-
-        (setq start end)))
-    (list (nreverse line-indents) indent tag-level curly-bracket-level 
square-bracket-level round-bracket-level)))
-
-(defun phps-mode-functions--process-tokens-in-string (tokens string)
-  "Generate indexes for imenu and indentation for TOKENS and STRING one pass.  
Complexity: O(n)."
-  (if tokens
-      (progn
-        (phps-mode-debug-message (message "\nCalculation indentation and imenu 
for all lines in buffer:\n\n%s" string))
-        (let ((in-heredoc nil)
-              (in-heredoc-started-this-line nil)
-              (in-heredoc-ended-this-line nil)
-              (in-inline-control-structure nil)
-              (inline-html-indent 0)
-              (inline-html-indent-start 0)
-              (inline-html-tag-level 0)
-              (inline-html-curly-bracket-level 0)
-              (inline-html-square-bracket-level 0)
-              (inline-html-round-bracket-level 0)
-              (inline-html-is-whitespace nil)
-              (first-token-is-inline-html nil)
-              (after-special-control-structure nil)
-              (after-special-control-structure-token nil)
-              (after-extra-special-control-structure nil)
-              (after-extra-special-control-structure-first-on-line nil)
-              (switch-curly-stack nil)
-              (switch-alternative-stack nil)
-              (switch-case-alternative-stack nil)
-              (curly-bracket-level 0)
-              (round-bracket-level 0)
-              (square-bracket-level 0)
-              (alternative-control-structure-level 0)
-              (in-concatenation nil)
-              (in-concatenation-round-bracket-level nil)
-              (in-concatenation-square-bracket-level nil)
-              (in-concatenation-level 0)
-              (column-level 0)
-              (column-level-start 0)
-              (tuning-level 0)
-              (nesting-start 0)
-              (nesting-end 0)
-              (last-line-number 0)
-              (first-token-on-line t)
-              (line-indents (make-hash-table :test 'equal))
-              (first-token-is-nesting-decrease nil)
-              (token-number 1)
-              (allow-custom-column-increment nil)
-              (allow-custom-column-decrement nil)
-              (in-assignment nil)
-              (in-assignment-round-bracket-level nil)
-              (in-assignment-square-bracket-level nil)
-              (in-assignment-level 0)
-              (in-object-operator nil)
-              (in-object-operator-round-bracket-level nil)
-              (in-object-operator-square-bracket-level nil)
-              (after-object-operator nil)
-              (in-object-operator-level 0)
-              (in-class-declaration nil)
-              (in-class-declaration-level 0)
-              (in-return nil)
-              (in-return-curly-bracket-level nil)
-              (in-return-level 0)
-              (previous-token nil)
-              (token nil)
-              (token-start nil)
-              (token-end nil)
-              (token-start-line-number 0)
-              (token-end-line-number 0)
-              (tokens (nreverse (copy-sequence tokens)))
-              (nesting-stack nil)
-              (nesting-key nil)
-              (class-declaration-started-this-line nil)
-              (special-control-structure-started-this-line nil)
-              (temp-pre-indent nil)
-              (temp-post-indent nil)
-              (imenu-index '())
-              (imenu-namespace-index '())
-              (imenu-class-index '())
-              (imenu-in-namespace-declaration nil)
-              (imenu-in-namespace-name nil)
-              (imenu-in-namespace-with-brackets nil)
-              (imenu-open-namespace-level nil)
-              (imenu-in-class-declaration nil)
-              (imenu-open-class-level nil)
-              (imenu-in-class-name nil)
-              (imenu-in-function-declaration nil)
-              (imenu-in-function-name nil)
-              (imenu-in-function-index nil)
-              (imenu-nesting-level 0)
-              (incremental-line-number 1))
-
-          (push `(END_PARSE ,(length string) . ,(length string)) tokens)
-
-          ;; Iterate through all buffer tokens from beginning to end
-          (dolist (item (nreverse tokens))
-            ;; (message "Items: %s %s" item phps-mode-lexer-tokens)
-            (let ((next-token (car item))
-                  (next-token-start (car (cdr item)))
-                  (next-token-end (cdr (cdr item)))
-                  (next-token-start-line-number nil)
-                  (next-token-end-line-number nil))
-
-              (when (and token
-                         (< token-end next-token-start))
-                ;; NOTE We use a incremental-line-number calculation because 
`line-at-pos' takes a lot of time
-                (setq incremental-line-number (+ incremental-line-number 
(phps-mode-functions--get-lines-in-string (substring string (1- token-end) (1- 
next-token-start))))))
-
-              ;; Handle the pseudo-token for last-line
-              (if (equal next-token 'END_PARSE)
-                  (progn
-                    (setq next-token-start-line-number (1+ 
token-start-line-number))
-                    (setq next-token-end-line-number (1+ 
token-end-line-number)))
-                (setq next-token-start-line-number incremental-line-number)
-
-                ;; NOTE We use a incremental-line-number calculation because 
`line-at-pos' takes a lot of time
-                ;; (message "Lines for %s '%s'" next-token (substring string 
(1- next-token-start) (1- next-token-end)))
-                (setq incremental-line-number (+ incremental-line-number 
(phps-mode-functions--get-lines-in-string (substring string (1- 
next-token-start) (1- next-token-end)))))
-                (setq next-token-end-line-number incremental-line-number)
-                (phps-mode-debug-message
-                  (message "Token '%s' pos: %s-%s lines: %s-%s" next-token 
next-token-start next-token-end next-token-start-line-number 
next-token-end-line-number)))
-
-              ;; Token logic - we have one-two token look-ahead at this point
-              ;; `token' is previous token
-              ;; `next-token' is current token
-              ;; `previous-token' is maybe two tokens back
-              (when token
-
-
-                ;; IMENU LOGIC
-
-                (cond
-
-                 ((or (string= token "{")
-                      (equal token 'T_CURLY_OPEN)
-                      (equal token 'T_DOLLAR_OPEN_CURLY_BRACES))
-                  (setq imenu-nesting-level (1+ imenu-nesting-level)))
-
-                 ((string= token "}")
-
-                  (when (and imenu-open-namespace-level
-                             (= imenu-open-namespace-level imenu-nesting-level)
-                             imenu-in-namespace-name)
-                    (let ((imenu-add-list (nreverse imenu-namespace-index)))
-                      (push `(,imenu-in-namespace-name . ,imenu-add-list) 
imenu-index))
-                    (setq imenu-in-namespace-name nil))
-
-                  (when (and imenu-open-class-level
-                             (= imenu-open-class-level imenu-nesting-level)
-                             imenu-in-class-name)
-                    (let ((imenu-add-list (nreverse imenu-class-index)))
-                      (if imenu-in-namespace-name
-                          (push `(,imenu-in-class-name . ,imenu-add-list) 
imenu-namespace-index)
-                        (push `(,imenu-in-class-name . ,imenu-add-list) 
imenu-index)))
-                    (setq imenu-in-class-name nil))
-
-                  (setq imenu-nesting-level (1- imenu-nesting-level))))
-
-                (when (and (equal next-token 'END_PARSE)
-                           imenu-in-namespace-name
-                           (not imenu-in-namespace-with-brackets))
-                  (let ((imenu-add-list (nreverse imenu-namespace-index)))
-                    (push `(,imenu-in-namespace-name . ,imenu-add-list) 
imenu-index))
-                  (setq imenu-in-namespace-name nil))
-                
-                (cond
-
-                 (imenu-in-namespace-declaration
-                  (cond
-
-                   ((or (string= token "{")
-                        (string= token ";"))
-                    (setq imenu-in-namespace-with-brackets (string= token "{"))
-                    (setq imenu-open-namespace-level imenu-nesting-level)
-                    (setq imenu-namespace-index '())
-                    (setq imenu-in-namespace-declaration nil))
-
-                    ((and (or (equal token 'T_STRING)
-                              (equal token 'T_NS_SEPARATOR))
-                          (setq imenu-in-namespace-name (concat 
imenu-in-namespace-name (substring string (1- token-start) (1- token-end))))))))
-
-                 (imenu-in-class-declaration
-                  (cond
-
-                   ((string= token "{")
-                    (setq imenu-open-class-level imenu-nesting-level)
-                    (setq imenu-in-class-declaration nil)
-                    (setq imenu-class-index '()))
-
-                   ((and (equal token 'T_STRING)
-                         (not imenu-in-class-name))
-                    (setq imenu-in-class-name (substring string (1- 
token-start) (1- token-end))))))
-
-                 (imenu-in-function-declaration
-                  (cond
-
-                   ((or (string= token "{")
-                        (string= token ";"))
-                    (when imenu-in-function-name
-                      (if imenu-in-class-name
-                          (push `(,imenu-in-function-name . 
,imenu-in-function-index) imenu-class-index)
-                        (if imenu-in-namespace-name
-                            (push `(,imenu-in-function-name . 
,imenu-in-function-index) imenu-namespace-index)
-                          (push `(,imenu-in-function-name . 
,imenu-in-function-index) imenu-index))))
-                    (setq imenu-in-function-name nil)
-                    (setq imenu-in-function-declaration nil))
-
-                   ((and (equal token 'T_STRING)
-                         (not imenu-in-function-name))
-                    (setq imenu-in-function-name (substring string (1- 
token-start) (1- token-end)))
-                    (setq imenu-in-function-index token-start))))
-
-                 (t (cond
-
-                     ((and (not imenu-in-namespace-name)
-                           (equal token 'T_NAMESPACE))
-                      (setq imenu-in-namespace-name nil)
-                      (setq imenu-in-namespace-declaration t))
-
-                     ((and (not imenu-in-class-name)
-                           (or (equal token 'T_CLASS)
-                               (equal token 'T_INTERFACE)))
-                      (setq imenu-in-class-name nil)
-                      (setq imenu-in-class-declaration t))
-
-                     ((and (not imenu-in-function-name)
-                           (equal token 'T_FUNCTION))
-                      (setq imenu-in-function-name nil)
-                      (setq imenu-in-function-declaration t)))))
-
-
-                ;; INDENTATION LOGIC
-
-                ;; Keep track of round bracket level
-                (when (string= token "(")
-                  (setq round-bracket-level (1+ round-bracket-level)))
-                (when (string= token ")")
-                  (setq round-bracket-level (1- round-bracket-level))
-                  (when first-token-on-line
-                    (setq first-token-is-nesting-decrease t)))
-
-                ;; Keep track of square bracket level
-                (when (string= token "[")
-                  (setq square-bracket-level (1+ square-bracket-level)))
-                (when (string= token "]")
-                  (setq square-bracket-level (1- square-bracket-level))
-                  (when first-token-on-line
-                    (setq first-token-is-nesting-decrease t)))
-
-                ;; Handle INLINE_HTML blocks
-                (when (equal token 'T_INLINE_HTML)
-
-                  ;; Flag whether inline-html is whitespace or not
-                  (setq inline-html-is-whitespace (string= (string-trim 
(substring string (1- token-start) (1- token-end))) ""))
-
-                  (when first-token-on-line
-                    (setq first-token-is-inline-html t))
-
-                  (let ((inline-html-indents 
(phps-mode-functions--get-inline-html-indentation (substring string (1- 
token-start) (1- token-end)) inline-html-indent inline-html-tag-level 
inline-html-curly-bracket-level inline-html-square-bracket-level 
inline-html-round-bracket-level)))
-
-                    (phps-mode-debug-message
-                      (message "Received inline html indent: %s from inline 
HTML: '%s'" inline-html-indents (substring string (1- token-start) (1- 
token-end))))
-
-                    ;; Update indexes
-                    (setq inline-html-indent (nth 1 inline-html-indents))
-                    (setq inline-html-tag-level (nth 2 inline-html-indents))
-                    (setq inline-html-curly-bracket-level (nth 3 
inline-html-indents))
-                    (setq inline-html-square-bracket-level (nth 4 
inline-html-indents))
-                    (setq inline-html-round-bracket-level (nth 5 
inline-html-indents))
-
-                    (phps-mode-debug-message
-                     (message "First token is inline html: %s" 
first-token-is-inline-html))
-
-                    ;; Does inline html span several lines or starts a new 
line?
-                    (when (or (> token-end-line-number token-start-line-number)
-                              first-token-is-inline-html)
-
-                      ;; Token does not only contain white-space?
-                      (unless inline-html-is-whitespace
-                        (let ((token-line-number-diff token-start-line-number))
-                          ;; Iterate lines here and add indents
-                          (dolist (item (nth 0 inline-html-indents))
-                            ;; Skip first line unless first token on line was 
inline-html
-                            (when (or (not (= token-line-number-diff 
token-start-line-number))
-                                      first-token-is-inline-html)
-                              (puthash token-line-number-diff (list item 0) 
line-indents)
-                              (phps-mode-debug-message
-                               (message "Putting indent at line %s to %s from 
inline HTML" token-line-number-diff item)))
-                            (setq token-line-number-diff (1+ 
token-line-number-diff))))))))
-
-                ;; Keep track of when we are inside a class definition
-                (if in-class-declaration
-                    (if (string= token "{")
-                        (progn
-                          (setq in-class-declaration nil)
-                          (setq in-class-declaration-level 0)
-
-                          (unless class-declaration-started-this-line
-                            (setq column-level (1- column-level))
-                            (pop nesting-stack))
-
-                          (when first-token-on-line
-                            (setq first-token-is-nesting-decrease t))
-
-                          )
-                      (when first-token-on-line
-                        (setq in-class-declaration-level 1)))
-
-                  ;; If ::class is used as a magical class constant it should 
not be considered start of a class declaration
-                  (when (and (equal token 'T_CLASS)
-                             (or (not previous-token)
-                                 (not (equal previous-token 
'T_PAAMAYIM_NEKUDOTAYIM))))
-                    (setq in-class-declaration t)
-                    (setq in-class-declaration-level 1)
-                    (setq class-declaration-started-this-line t)))
-
-                ;; Keep track of curly bracket level
-                (when (or (equal token 'T_CURLY_OPEN)
-                          (equal token 'T_DOLLAR_OPEN_CURLY_BRACES)
-                          (string= token "{"))
-                  (setq curly-bracket-level (1+ curly-bracket-level)))
-                (when (string= token "}")
-                  (setq curly-bracket-level (1- curly-bracket-level))
-
-                  (when (and switch-curly-stack
-                             (= (1+ curly-bracket-level) (car 
switch-curly-stack)))
-
-                    (phps-mode-debug-message
-                      (message "Ended switch curly stack at %s" 
curly-bracket-level))
-
-                    (setq allow-custom-column-decrement t)
-                    (pop nesting-stack)
-                    (setq alternative-control-structure-level (1- 
alternative-control-structure-level))
-                    (pop switch-curly-stack))
-                  
-                  (when first-token-on-line
-                    (setq first-token-is-nesting-decrease t)))
-
-                ;; Keep track of ending alternative control structure level
-                (when (or (equal token 'T_ENDIF)
-                          (equal token 'T_ENDWHILE)
-                          (equal token 'T_ENDFOR)
-                          (equal token 'T_ENDFOREACH)
-                          (equal token 'T_ENDSWITCH))
-                  (setq alternative-control-structure-level (1- 
alternative-control-structure-level))
-                  ;; (message "Found ending alternative token %s %s" token 
alternative-control-structure-level)
-
-                  (when (and (equal token 'T_ENDSWITCH)
-                             switch-case-alternative-stack)
-
-                    (phps-mode-debug-message
-                      (message "Ended alternative switch stack at %s" 
alternative-control-structure-level))
-                    
-                    (pop switch-alternative-stack)
-                    (pop switch-case-alternative-stack)
-                    (setq allow-custom-column-decrement t)
-                    (pop nesting-stack)
-                    (setq alternative-control-structure-level (1- 
alternative-control-structure-level)))
-
-                  (when first-token-on-line
-                    (setq first-token-is-nesting-decrease t)))
-
-                ;; When we encounter a token except () after a 
control-structure
-                (when (and after-special-control-structure
-                           (= after-special-control-structure 
round-bracket-level)
-                           (not (string= token ")"))
-                           (not (string= token "(")))
-
-                  ;; Handle the else if case
-                  (if (equal 'T_IF token)
-                      (setq after-special-control-structure-token token)
-
-                    ;; Is token not a curly bracket - because that is a 
ordinary control structure syntax
-                    (if (string= token "{")
-
-                        ;; Save curly bracket level when switch starts
-                        (when (equal after-special-control-structure-token 
'T_SWITCH)
-
-                          (phps-mode-debug-message
-                            (message "Started switch curly stack at %s" 
curly-bracket-level))
-
-                          (push curly-bracket-level switch-curly-stack))
-
-                      ;; Is it the start of an alternative control structure?
-                      (if (string= token ":")
-
-                          (progn
-
-                            ;; Save alternative nesting level for switch
-                            (when (equal after-special-control-structure-token 
'T_SWITCH)
-
-                              (phps-mode-debug-message
-                                (message "Started switch alternative stack at 
%s" alternative-control-structure-level))
-
-                              (push alternative-control-structure-level 
switch-alternative-stack))
-
-                            (setq alternative-control-structure-level (1+ 
alternative-control-structure-level))
-
-                            (phps-mode-debug-message
-                              (message "\nIncreasing 
alternative-control-structure after %s %s to %s\n" 
after-special-control-structure-token token 
alternative-control-structure-level))
-                            )
-
-                        ;; Don't start inline control structures after a while 
($condition); expression
-                        (unless (string= token ";")
-                          (phps-mode-debug-message
-                            (message "\nStarted inline control-structure after 
%s at %s\n" after-special-control-structure-token token))
-
-                          (setq in-inline-control-structure t)
-                          (setq temp-pre-indent (1+ column-level)))))
-
-                    (setq after-special-control-structure nil)
-                    (setq after-special-control-structure-token nil)))
-
-                ;; Support extra special control structures (CASE)
-                (when (and after-extra-special-control-structure
-                           (string= token ":"))
-                  (setq alternative-control-structure-level (1+ 
alternative-control-structure-level))
-                  (when after-extra-special-control-structure-first-on-line
-                    (setq first-token-is-nesting-decrease t))
-                  (setq after-extra-special-control-structure nil))
-
-                ;; Keep track of concatenation
-                (if in-concatenation
-                    (when (or (string= token ";")
-                              (and (string= token ")")
-                                   (< round-bracket-level (car 
in-concatenation-round-bracket-level)))
-                              (and (string= token ",")
-                                   (= round-bracket-level (car 
in-concatenation-round-bracket-level))
-                                   (= square-bracket-level (car 
in-concatenation-square-bracket-level)))
-                              (and (string= token"]")
-                                   (< square-bracket-level (car 
in-concatenation-square-bracket-level))))
-                      (phps-mode-debug-message "Ended concatenation")
-                      (pop in-concatenation-round-bracket-level)
-                      (pop in-concatenation-square-bracket-level)
-                      (unless in-concatenation-round-bracket-level
-                        (setq in-concatenation nil))
-                      (setq in-concatenation-level (1- 
in-concatenation-level)))
-                  (when (and (> next-token-start-line-number 
token-end-line-number)
-                             (or (string= token ".")
-                                 (string= next-token ".")))
-                    (phps-mode-debug-message "Started concatenation")
-                    (setq in-concatenation t)
-                    (push round-bracket-level 
in-concatenation-round-bracket-level)
-                    (push square-bracket-level 
in-concatenation-square-bracket-level)
-                    (setq in-concatenation-level (1+ in-concatenation-level))))
-
-                ;; Did we reach a semicolon inside a inline block? Close the 
inline block
-                (when (and in-inline-control-structure
-                           (string= token ";")
-                           (not special-control-structure-started-this-line))
-                  (setq in-inline-control-structure nil))
-
-                ;; Did we encounter a token that supports alternative and 
inline control structures?
-                (when (or (equal token 'T_IF)
-                          (equal token 'T_WHILE)
-                          (equal token 'T_FOR)
-                          (equal token 'T_FOREACH)
-                          (equal token 'T_SWITCH)
-                          (equal token 'T_ELSE)
-                          (equal token 'T_ELSEIF)
-                          (equal token 'T_DEFAULT))
-                  (setq after-special-control-structure round-bracket-level)
-                  (setq after-special-control-structure-token token)
-                  (setq nesting-key token)
-                  (setq special-control-structure-started-this-line t)
-
-                  ;; ELSE and ELSEIF after a IF, ELSE, ELESIF
-                  ;; and DEFAULT after a CASE
-                  ;; should decrease alternative control structure level
-                  (when (and nesting-stack
-                             (string= (car (cdr (cdr (cdr (car 
nesting-stack))))) ":")
-                             (or
-                              (and (or (equal token 'T_ELSE)
-                                       (equal token 'T_ELSEIF))
-                                   (or (equal (car (cdr (cdr (car 
nesting-stack)))) 'T_IF)
-                                       (equal (car (cdr (cdr (car 
nesting-stack)))) 'T_ELSEIF)
-                                       (equal (car (cdr (cdr (car 
nesting-stack)))) 'T_ELSE)))
-                              (and (equal token 'T_DEFAULT)
-                                   (equal (car (cdr (cdr (car 
nesting-stack)))) 'T_CASE))))
-                    (setq alternative-control-structure-level (1- 
alternative-control-structure-level))
-
-                    (when first-token-on-line
-                      (setq first-token-is-nesting-decrease t))
-
-                    (phps-mode-debug-message
-                      (message "\nDecreasing alternative control structure 
nesting at %s to %s\n" token alternative-control-structure-level)))
-
-                  )
-
-                ;; Keep track of assignments
-                (when in-assignment
-                  (when (or (string= token ";")
-                            (and (string= token ")")
-                                 (or (< round-bracket-level (car 
in-assignment-round-bracket-level))
-                                     (and
-                                      (= round-bracket-level (car 
in-assignment-round-bracket-level))
-                                      (= square-bracket-level (car 
in-assignment-square-bracket-level))
-                                      (or (string= next-token ")")
-                                          (string= next-token "]")))))
-                            (and (string= token ",")
-                                 (= round-bracket-level (car 
in-assignment-round-bracket-level))
-                                 (= square-bracket-level (car 
in-assignment-square-bracket-level)))
-                            (and (string= token "]")
-                                 (or (< square-bracket-level (car 
in-assignment-square-bracket-level))
-                                     (and
-                                      (= square-bracket-level (car 
in-assignment-square-bracket-level))
-                                      (= round-bracket-level (car 
in-assignment-round-bracket-level))
-                                      (or (string= next-token "]")
-                                          (string= next-token ")")))))
-                            (and (equal token 'T_FUNCTION)
-                                 (= round-bracket-level (car 
in-assignment-round-bracket-level))))
-
-                    ;; NOTE Ending an assignment because of a T_FUNCTION token 
is to support PSR-2 Closures
-                    
-                    (phps-mode-debug-message
-                      (message "Ended assignment %s at %s %s" 
in-assignment-level token next-token))
-                    (pop in-assignment-square-bracket-level)
-                    (pop in-assignment-round-bracket-level)
-                    (unless in-assignment-round-bracket-level
-                      (setq in-assignment nil))
-                    (setq in-assignment-level (1- in-assignment-level))
-
-                    ;; Did we end two assignment at once?
-                    (when (and
-                           in-assignment-round-bracket-level
-                           in-assignment-square-bracket-level
-                           (= round-bracket-level (car 
in-assignment-round-bracket-level))
-                           (= square-bracket-level (car 
in-assignment-square-bracket-level))
-                           (or (string= next-token ")")
-                               (string= next-token "]")))
-                      (phps-mode-debug-message
-                        (message "Ended another assignment %s at %s %s" 
in-assignment-level token next-token))
-                      (pop in-assignment-square-bracket-level)
-                      (pop in-assignment-round-bracket-level)
-                      (unless in-assignment-round-bracket-level
-                        (setq in-assignment nil))
-                      (setq in-assignment-level (1- in-assignment-level)))
-
-                    ))
-
-                (when (and (not after-special-control-structure)
-                           (or (string= token "=")
-                               (equal token 'T_DOUBLE_ARROW)
-                               (equal token 'T_CONCAT_EQUAL)
-                               (equal token 'T_POW_EQUAL)
-                               (equal token 'T_DIV_EQUAL)
-                               (equal token 'T_PLUS_EQUAL)
-                               (equal token 'T_MINUS_EQUAL)
-                               (equal token 'T_MUL_EQUAL)
-                               (equal token 'T_MOD_EQUAL)
-                               (equal token 'T_SL_EQUAL)
-                               (equal token 'T_SR_EQUAL)
-                               (equal token 'T_AND_EQUAL)
-                               (equal token 'T_OR_EQUAL)
-                               (equal token 'T_XOR_EQUAL)
-                               (equal token 'T_COALESCE_EQUAL)))
-                  (phps-mode-debug-message "Started assignment")
-                  (setq in-assignment t)
-                  (push round-bracket-level in-assignment-round-bracket-level)
-                  (push square-bracket-level 
in-assignment-square-bracket-level)
-                  (setq in-assignment-level (1+ in-assignment-level)))
-
-                ;; Second token after a object-operator
-                (when (and
-                       in-object-operator
-                       in-object-operator-round-bracket-level
-                       in-object-operator-square-bracket-level
-                       (<= round-bracket-level (car 
in-object-operator-round-bracket-level))
-                       (<= square-bracket-level (car 
in-object-operator-square-bracket-level))
-                       (not (or
-                             (equal next-token 'T_OBJECT_OPERATOR)
-                             (equal next-token 'T_PAAMAYIM_NEKUDOTAYIM))))
-                  (phps-mode-debug-message
-                    (message "Ended object-operator at %s %s at level %s" 
token next-token in-object-operator-level))
-                  (pop in-object-operator-round-bracket-level)
-                  (pop in-object-operator-square-bracket-level)
-                  (setq in-object-operator-level (1- in-object-operator-level))
-                  (when (= in-object-operator-level 0)
-                    (setq in-object-operator nil)))
-
-                ;; First token after a object-operator
-                (when after-object-operator
-                  (when (or (equal next-token 'T_STRING)
-                            (string= next-token "("))
-                    (progn
-                      (phps-mode-debug-message
-                        (message "Started object-operator at %s %s on level 
%s"  token next-token in-object-operator-level))
-                      (push round-bracket-level 
in-object-operator-round-bracket-level)
-                      (push square-bracket-level 
in-object-operator-square-bracket-level)
-                      (setq in-object-operator t)
-                      (setq in-object-operator-level (1+ 
in-object-operator-level))))
-                  (setq after-object-operator nil))
-
-                ;; Starting object-operator?
-                (when (and (or (equal token 'T_OBJECT_OPERATOR)
-                               (equal token 'T_PAAMAYIM_NEKUDOTAYIM))
-                           (equal next-token 'T_STRING))
-                  (phps-mode-debug-message
-                    (message "After object-operator at %s level %s"  token 
in-object-operator-level))
-                  (setq after-object-operator t))
-
-                ;; Keep track of return expressions
-                (when in-return
-                  (when (and (string= token ";")
-                             (= curly-bracket-level (car 
in-return-curly-bracket-level)))
-
-                    (phps-mode-debug-message (message "Ended return at %s" 
token))
-                    (pop in-return-curly-bracket-level)
-                    (unless in-return-curly-bracket-level
-                      (setq in-return nil))
-                    (setq in-return-level (1- in-return-level))))
-                (when (equal token 'T_RETURN)
-                  (phps-mode-debug-message "Started return")
-                  (setq in-return t)
-                  (push curly-bracket-level in-return-curly-bracket-level)
-                  (setq in-return-level (1+ in-return-level)))
-
-                ;; Did we encounter a token that supports extra special 
alternative control structures?
-                (when (equal token 'T_CASE)
-                  (setq after-extra-special-control-structure t)
-                  (setq nesting-key token)
-                  (setq after-extra-special-control-structure-first-on-line 
first-token-on-line)
-
-                  (when (and switch-case-alternative-stack
-                             (= (1- alternative-control-structure-level) (car 
switch-case-alternative-stack)))
-
-                    (phps-mode-debug-message
-                      (message "Found CASE %s vs %s" (1- 
alternative-control-structure-level) (car switch-case-alternative-stack)))
-
-                    (setq alternative-control-structure-level (1- 
alternative-control-structure-level))
-                    (when first-token-on-line
-                      (setq first-token-is-nesting-decrease t))
-                    (pop switch-case-alternative-stack))
-
-                  (push alternative-control-structure-level 
switch-case-alternative-stack)))
-
-              ;; Do we have one token look-ahead?
-              (when token
-
-                (phps-mode-debug-message (message "Processing token: %s" 
token))
-                
-                ;; Calculate nesting
-                (setq nesting-end (+ round-bracket-level square-bracket-level 
curly-bracket-level alternative-control-structure-level in-assignment-level 
in-class-declaration-level in-concatenation-level in-return-level 
in-object-operator-level))
-
-                ;; Keep track of whether we are inside a HEREDOC or NOWDOC
-                (when (equal token 'T_START_HEREDOC)
-                  (setq in-heredoc t)
-                  (setq in-heredoc-started-this-line t))
-                (when (equal token 'T_END_HEREDOC)
-                  (setq in-heredoc nil)
-                  (setq in-heredoc-ended-this-line t))
-
-                ;; Has nesting increased?
-                (when (and nesting-stack
-                           (<= nesting-end (car (car nesting-stack))))
-                  (let ((nesting-decrement 0))
-
-                    ;; Handle case were nesting has decreased less than next 
as well
-                    (while (and nesting-stack
-                                (<= nesting-end (car (car nesting-stack))))
-                      (phps-mode-debug-message
-                        (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)
-                      (setq nesting-decrement (1+ nesting-decrement)))
-
-                    (if first-token-is-nesting-decrease
-
-                        (progn
-                          ;; Decrement column
-                          (if allow-custom-column-decrement
-                              (progn
-                                (phps-mode-debug-message
-                                  (message "Doing custom decrement 1 from %s 
to %s" column-level (- column-level (- nesting-start nesting-end))))
-                                (setq column-level (- column-level (- 
nesting-start nesting-end)))
-                                (setq allow-custom-column-decrement nil))
-                            (phps-mode-debug-message
-                              (message "Doing regular decrement 1 from %s to 
%s" column-level (1- column-level)))
-                            (setq column-level (- column-level 
nesting-decrement)))
-
-                          ;; Prevent negative column-values
-                          (when (< column-level 0)
-                            (setq column-level 0)))
-
-                      (unless temp-post-indent
-                        (phps-mode-debug-message
-                          (message "Temporary setting post indent %s" 
column-level))
-                        (setq temp-post-indent column-level))
-
-                      ;; Decrement column
-                      (if allow-custom-column-decrement
-                          (progn
-                            (phps-mode-debug-message
-                              (message "Doing custom decrement 2 from %s to 
%s" column-level (- column-level (- nesting-start nesting-end))))
-                            (setq temp-post-indent (- temp-post-indent (- 
nesting-start nesting-end)))
-                            (setq allow-custom-column-decrement nil))
-                        (setq temp-post-indent (- temp-post-indent 
nesting-decrement)))
-
-                      ;; Prevent negative column-values
-                      (when (< temp-post-indent 0)
-                        (setq temp-post-indent 0))
-
-                      )))
-
-                ;; Are we on a new line or is it the last token of the buffer?
-                (if (> next-token-start-line-number token-start-line-number)
-                    (progn
-
-
-                      ;; ;; Start indentation might differ from ending 
indentation in cases like } else {
-                      (setq column-level-start column-level)
-
-                      ;; Support temporarily pre-indent
-                      (when temp-pre-indent
-                        (setq column-level-start temp-pre-indent)
-                        (setq temp-pre-indent nil))
-
-                      ;; HEREDOC lines should have zero indent
-                      (when (or (and in-heredoc
-                                     (not in-heredoc-started-this-line))
-                                in-heredoc-ended-this-line)
-                        (setq column-level-start 0))
-
-                      ;; Inline HTML should have zero indent
-                      (when (and first-token-is-inline-html
-                                 (not inline-html-is-whitespace))
-                        (phps-mode-debug-message
-                         (message "Setting column-level to inline HTML indent: 
%s" inline-html-indent-start))
-                        (setq column-level-start inline-html-indent-start))
-
-                      ;; Save line indent
-                      (phps-mode-debug-message
-                        (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))
-
-                      (when (and (> token-start-line-number 0)
-                                 (or
-                                  (not first-token-is-inline-html)
-                                  inline-html-is-whitespace))
-                        (phps-mode-debug-message
-                         (message "Putting indent on line %s to %s at #C" 
token-start-line-number column-level-start))
-                        (puthash token-start-line-number `(,column-level-start 
,tuning-level) line-indents))
-
-                      ;; Support trailing indent decrements
-                      (when temp-post-indent
-                        (setq column-level temp-post-indent)
-                        (setq temp-post-indent nil))
-
-                      ;; Increase indentation
-                      (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)))))
-
-                          (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)))
-
-                          (phps-mode-debug-message
-                            (message "\nPushing (%s %s %s %s) to nesting-stack 
since %s is greater than %s or stack is empty\n" nesting-start nesting-end 
nesting-key token nesting-end (car (cdr (car nesting-stack))))
-                            )
-                          (push `(,nesting-stack-end ,nesting-end ,nesting-key 
,token) nesting-stack)))
-
-
-                      ;; Does token span over several lines and is it not a 
INLINE_HTML token?
-                      (when (and (> token-end-line-number 
token-start-line-number)
-                                 (not (equal token 'T_INLINE_HTML)))
-                        (let ((column-level-end column-level))
-
-                          ;; HEREDOC lines should have zero indent
-                          (when (or (and in-heredoc
-                                         (not in-heredoc-started-this-line))
-                                    in-heredoc-ended-this-line)
-                            (setq column-level-end 0))
-
-                          ;; (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-end tuning-level)
-
-                          ;; Indent doc-comment lines with 1 tuning
-                          (when (equal token 'T_DOC_COMMENT)
-                            (setq tuning-level 1))
-
-                          (let ((token-line-number-diff (1- (- 
token-end-line-number token-start-line-number))))
-                            (while (>= token-line-number-diff 0)
-                              (phps-mode-debug-message
-                               (message "Putting indent on line %s to %s at 
#A" (- token-end-line-number token-line-number-diff) column-level-end))
-                              (puthash (- token-end-line-number 
token-line-number-diff) `(,column-level-end ,tuning-level) line-indents)
-                              ;; (message "Saved line %s indent %s %s" (- 
token-end-line-number token-line-number-diff) column-level tuning-level)
-                              (setq token-line-number-diff (1- 
token-line-number-diff))))
-
-                          ;; Rest tuning-level used for comments
-                          (setq tuning-level 0)))
-
-                      ;; Indent token-less lines here in between last tokens 
if distance is more than 1 line
-                      (when (and (> next-token-start-line-number (1+ 
token-end-line-number))
-                                 (not (equal token 'T_CLOSE_TAG)))
-
-                        (phps-mode-debug-message
-                          (message "\nDetected token-less lines between %s and 
%s, should have indent: %s\n" token-end-line-number 
next-token-start-line-number column-level))
-
-                        (let ((token-line-number-diff (1- (- 
next-token-start-line-number token-end-line-number))))
-                          (while (> token-line-number-diff 0)
-                            (phps-mode-debug-message
-                             (message "Putting indent at line %s indent %s at 
#B" (- next-token-start-line-number token-line-number-diff) column-level))
-                            (puthash (- next-token-start-line-number 
token-line-number-diff) `(,column-level ,tuning-level) line-indents)
-                            (setq token-line-number-diff (1- 
token-line-number-diff)))))
-
-
-                      ;; Calculate indentation level at start of line
-                      (setq nesting-start (+ round-bracket-level 
square-bracket-level curly-bracket-level alternative-control-structure-level 
in-assignment-level in-class-declaration-level in-concatenation-level 
in-return-level in-object-operator-level))
-
-                      ;; Set initial values for tracking first token
-                      (when (> token-start-line-number last-line-number)
-                        (setq inline-html-indent-start inline-html-indent)
-                        (setq first-token-on-line t)
-                        (setq first-token-is-nesting-decrease nil)
-                        (setq first-token-is-inline-html nil)
-                        (setq in-class-declaration-level 0)
-                        (setq class-declaration-started-this-line nil)
-                        (setq in-heredoc-started-this-line nil)
-                        (setq special-control-structure-started-this-line nil)
-
-                        ;; When line ends with multi-line inline-html flag 
first token as inline-html
-                        (when (and
-                               (equal token 'T_INLINE_HTML)
-                               (not inline-html-is-whitespace)
-                               (> token-end-line-number 
token-start-line-number))
-
-                          (setq inline-html-is-whitespace
-                                (not (null
-                                      (string-match "[\n\C-m][ \t]+$" 
(substring string (1- token-start) (1- token-end))))))
-                          (phps-mode-debug-message
-                           (message "Trailing inline html line is whitespace: 
%s" inline-html-is-whitespace))
-                          (phps-mode-debug-message
-                           (message "Setting first-token-is-inline-html to 
true since last token on line is inline-html and spans several lines"))
-                          (setq first-token-is-inline-html t))))
-
-                  ;; Current token is not first if it's not <?php or <?=
-                  (unless (or (equal token 'T_OPEN_TAG)
-                              (equal token 'T_OPEN_TAG_WITH_ECHO))
-                    (setq first-token-on-line nil))
-
-                  (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)
-                      (setq tuning-level 1))
-
-                    (let ((token-line-number-diff (1- (- token-end-line-number 
token-start-line-number))))
-                      (while (>= token-line-number-diff 0)
-                        (phps-mode-debug-message
-                         (message "Putting indent on line %s to %s at #E" (- 
token-end-line-number token-line-number-diff) column-level))
-                        (puthash (- token-end-line-number 
token-line-number-diff) `(,column-level ,tuning-level) line-indents)
-                        (setq token-line-number-diff (1- 
token-line-number-diff))))
-                    (setq tuning-level 0))))
-
-              ;; Update current token
-              (setq previous-token token)
-              (setq token next-token)
-              (setq token-start next-token-start)
-              (setq token-end next-token-end)
-              (setq token-start-line-number next-token-start-line-number)
-              (setq token-end-line-number next-token-end-line-number)
-              (setq token-number (1+ token-number))))
-          (list (nreverse imenu-index) line-indents)))
-    (list nil nil)))
-
-;; TODO newline with electric mode not working
-(defun phps-mode-functions-indent-line ()
-  "Indent line."
-  (phps-mode-runtime-debug-message "Indent line")
-  (phps-mode-debug-message (message "Indent line"))
-  (phps-mode-functions-process-current-buffer)
-  (if phps-mode-functions-lines-indent
-      (let ((line-number (line-number-at-pos (point))))
-        (phps-mode-runtime-debug-message "Found lines indent index, 
indenting..")
-        (phps-mode-debug-message (message "Found lines indent index, 
indenting.."))
-        (let ((indent (gethash line-number phps-mode-functions-lines-indent)))
-          (if indent
-              (progn
-                (phps-mode-runtime-debug-message (format "Found indent for 
line number %s = %s" line-number indent))
-                (let ((indent-sum (+ (* (car indent) tab-width) (car (cdr 
indent))))
-                      (old-indentation (current-indentation))
-                      (line-start (line-beginning-position)))
-
-                  (unless old-indentation
-                    (setq old-indentation 0))
-
-                  ;; Only continue if current indentation is wrong
-                  (if (not (equal indent-sum old-indentation))
-                      (progn
-                        (phps-mode-runtime-debug-message (format "Indenting 
line since it's not already indented correctly %s vs %s" old-indentation 
indent-sum))
-
-                        (setq-local phps-mode-functions-allow-after-change nil)
-                        (indent-line-to indent-sum)
-                        (setq-local phps-mode-functions-allow-after-change t)
-
-                        (let ((indent-diff (- (current-indentation) 
old-indentation)))
-
-                          (phps-mode-runtime-debug-message (format "Moving 
indexes by %s points from %s" indent-diff line-start))
-                          (phps-mode-runtime-debug-message (format "Lexer 
tokens before move: %s" phps-mode-lexer-tokens))
-
-                          ;; When indent is changed the trailing tokens and 
states just need to adjust their positions, this will improve speed of 
indent-region a lot
-                          (phps-mode-lexer-move-tokens line-start indent-diff)
-                          (phps-mode-lexer-move-states line-start indent-diff)
-                          (phps-mode-functions-move-imenu-index line-start 
indent-diff)
-
-                          (phps-mode-runtime-debug-message (format "Lexer 
tokens after move: %s" phps-mode-lexer-tokens))
-                          (phps-mode-debug-message
-                           (message "Lexer tokens after move: %s" 
phps-mode-lexer-tokens)
-                           (message "Lexer states after move: %s" 
phps-mode-lexer-states))
-
-                          ;; Reset change flag
-                          (phps-mode-functions--reset-changes)
-                          (phps-mode-functions--cancel-idle-timer)
-
-                          ;; Update last buffer states
-                          (setq-local phps-mode-lexer-buffer-length (1- 
(point-max)))
-                          (setq-local phps-mode-lexer-buffer-contents 
(buffer-substring-no-properties (point-min) (point-max)))
-
-                          (phps-mode-runtime-debug-message (format "buffer 
contents:\n%s" (buffer-substring-no-properties (point-min) (point-max))))
-                          ))
-                    (phps-mode-runtime-debug-message "Skipping indentation of 
line since it's already indented correctly"))))
-            (phps-mode-runtime-debug-message (format "Found no indent for line 
number %s" line-number)))))
-    (phps-mode-runtime-debug-message "Did not find lines indent index, 
skipping indenting..")
-    (phps-mode-debug-message "Did not find lines indent index, skipping 
indenting..")
-    (message "Did not find lines indent index, skipping indenting..")))
-
-(defun phps-mode-functions--reset-changes ()
-  "Reset change stack."
-  (setq-local phps-mode-functions-buffer-changes nil))
-
-(defun phps-mode-functions--get-changes ()
-  "Get change stack."
-  phps-mode-functions-buffer-changes)
-
-(defun phps-mode-functions--cancel-idle-timer ()
-  "Cancel idle timer."
-  (phps-mode-runtime-debug-message "Cancelled idle timer")
-  (phps-mode-debug-message (message "Cancelled idle timer"))
-  (when phps-mode-functions-idle-timer
-    (cancel-timer phps-mode-functions-idle-timer)
-    (setq-local phps-mode-functions-idle-timer nil)))
-
-(defun phps-mode-functions--start-idle-timer ()
-  "Start idle timer."
-  (phps-mode-runtime-debug-message "Enqueued idle timer")
-  (phps-mode-debug-message (message "Enqueued idle timer"))
-  (when (boundp 'phps-mode-idle-interval)
-    (setq-local phps-mode-functions-idle-timer (run-with-idle-timer 
phps-mode-idle-interval nil #'phps-mode-lexer-run-incremental 
(current-buffer)))))
-
-(defun phps-mode-functions-after-change (start stop length)
-  "Track buffer change from START to STOP with LENGTH."
-  (phps-mode-runtime-debug-message
-   (format "After change %s - %s, length: %s" start stop length))
-  (phps-mode-debug-message
-   (message "After change %s - %s, length: %s" start stop length))
-
-  (if phps-mode-functions-allow-after-change
-      (progn
-        (phps-mode-debug-message (message "After change registration is 
enabled"))
-        (phps-mode-runtime-debug-message "After change registration is 
enabled")
-        
-        ;; If we haven't scheduled incremental lexer before - do it
-        (when (and (boundp 'phps-mode-idle-interval)
-                   phps-mode-idle-interval
-                   (not phps-mode-functions-idle-timer))
-
-          ;; Reset imenu
-          (when (and (boundp 'imenu--index-alist)
-                     imenu--index-alist)
-            (setq-local imenu--index-alist nil)
-            (phps-mode-debug-message (message "Cleared Imenu index")))
-
-          (phps-mode-functions--start-idle-timer))
-
-        ;; Save change in changes stack
-        (push `(,start ,stop ,length ,(point-max) 
,(buffer-substring-no-properties (point-min) (point-max))) 
phps-mode-functions-buffer-changes))
-    (phps-mode-debug-message (message "After change registration is disabled"))
-    (phps-mode-runtime-debug-message "After change registration is disabled")))
-
-(defun phps-mode-functions-imenu-create-index ()
-  "Get Imenu for current buffer."
-  (phps-mode-functions-process-current-buffer)
-  phps-mode-functions-imenu)
-
-(defun phps-mode-functions-comment-region (beg end &optional _arg)
-  "Comment region from BEG to END with optional ARG."
-  ;; Iterate tokens from beginning to end and comment out all PHP code
-  (when-let ((tokens phps-mode-lexer-tokens))
-    (let ((token-comment-start nil)
-          (token-comment-end nil)
-          (in-token-comment nil)
-          (offset 0))
-      (dolist (token tokens)
-        (let ((token-label (car token))
-              (token-start (car (cdr token)))
-              (token-end (cdr (cdr token))))
-          (when (and (>= token-start beg)
-                     (<= token-end end))
-
-            (if in-token-comment
-                (cond
-                 ((or
-                   (equal token-label 'T_COMMENT)
-                   (equal token-label 'T_DOC_COMMENT)
-                   (equal token-label 'T_CLOSE_TAG))
-                  (setq in-token-comment nil))
-                 (t (setq token-comment-end token-end)))
-
-              ;; When we have a start and end of comment, comment it out
-              (when (and
-                     token-comment-start
-                     token-comment-end)
-                (let ((offset-comment-start (+ token-comment-start offset))
-                      (offset-comment-end))
-                  (save-excursion
-                    (goto-char offset-comment-start)
-                    (insert "/* "))
-                  (setq offset (+ offset 3))
-                  (setq offset-comment-end (+ token-comment-end offset))
-                  (save-excursion
-                    (goto-char offset-comment-end)
-                    (insert " */"))
-                  (setq offset (+ offset 3))
-                  (phps-mode-debug-message
-                   (message "Commented out %s-%s" offset-comment-start 
offset-comment-end)))
-                (setq token-comment-start nil)
-                (setq token-comment-end nil))
-
-              (cond
-               ((or
-                 (equal token-label 'T_INLINE_HTML)
-                 (equal token-label 'T_OPEN_TAG)
-                 (equal token-label 'T_OPEN_TAG_WITH_ECHO)))
-               (t
-                (phps-mode-debug-message
-                 (message "Comment should start at %s %s" token-label 
token-start))
-                (setq token-comment-start token-start)
-                (setq in-token-comment t)))))))
-
-      ;; When we have a start and end of comment, comment it out
-      (when (and
-             in-token-comment
-             token-comment-start
-             token-comment-end)
-        (let ((offset-comment-start (+ token-comment-start offset))
-              (offset-comment-end))
-          (save-excursion
-            (goto-char offset-comment-start)
-            (insert "/* "))
-          (setq offset (+ offset 3))
-          (setq offset-comment-end (+ token-comment-end offset))
-          (save-excursion
-            (goto-char offset-comment-end)
-            (insert " */"))
-          (setq offset (+ offset 3))
-          (phps-mode-debug-message
-           (message "Commented out trailing %s-%s" offset-comment-start 
offset-comment-end)))
-        (setq token-comment-start nil)
-        (setq token-comment-end nil)))))
-
-(defun phps-mode-functions-uncomment-region (beg end &optional _arg)
-  "Un-comment region from BEG to END with optional ARG."
-  ;; Iterate tokens from beginning to end and uncomment out all commented PHP 
code
-  (when-let ((tokens phps-mode-lexer-tokens))
-    (let ((offset 0))
-      (dolist (token tokens)
-        (let ((token-label (car token))
-              (token-start (car (cdr token)))
-              (token-end (cdr (cdr token))))
-          (when (and (>= token-start beg)
-                     (<= token-end end))
-            (when (or
-                   (equal token-label 'T_COMMENT)
-                   (equal token-label 'T_DOC_COMMENT))
-
-              (phps-mode-debug-message
-               (message "Un-comment comment at %s %s" token-label token-start 
token-end))
-
-              (let ((offset-comment-start (+ token-start offset))
-                    (offset-comment-end))
-
-                (if (equal token-label 'T_DOC_COMMENT)
-                    (progn
-                      (phps-mode-debug-message
-                       (message "Un-comment doc comment at %s-%s" token-start 
token-end))
-                      (save-excursion
-                        (goto-char offset-comment-start)
-                        (delete-char 4))
-                      (setq offset (- offset 4))
-                      (setq offset-comment-end (+ token-end offset))
-                      (save-excursion
-                        (goto-char offset-comment-end)
-                        (delete-char -4))
-                      (setq offset (- offset 4)))
-
-                  (phps-mode-debug-message
-                   (message "Un-comment comment starting at %s" token-start))
-
-                  (cond
-
-                   ((string=
-                     (buffer-substring-no-properties offset-comment-start (+ 
offset-comment-start 1))
-                     "#")
-                    (save-excursion
-                      (goto-char offset-comment-start)
-                      (delete-char 1))
-                    (setq offset (- offset 1)))
-                   ((string=
-                     (buffer-substring-no-properties offset-comment-start (+ 
offset-comment-start 2))
-                     "//")
-                    (save-excursion
-                      (goto-char offset-comment-start)
-                      (delete-char 2))
-                    (setq offset (- offset 2)))
-                   (t
-                    (save-excursion
-                      (goto-char offset-comment-start)
-                      (delete-char 3))
-                    (setq offset (- offset 3))))
-
-                  
-                  (setq offset-comment-end (+ token-end offset))
-                  (if (string=
-                       (buffer-substring-no-properties (- offset-comment-end 
3) offset-comment-end)
-                       " */")
-                      (progn
-                        (phps-mode-debug-message
-                         (message "Un-comment comment ending at %s" token-end))
-                        (save-excursion
-                          (goto-char offset-comment-end)
-                          (delete-char -3))
-                        (setq offset (- offset 3)))
-                    (phps-mode-debug-message
-                     (message "Do not un-comment comment ending at %s" 
token-end))))))))))))
-
-(provide 'phps-mode-functions)
-
-;;; phps-mode-functions.el ends here
diff --git a/phps-mode.el b/phps-mode.el
index 943ad11..9ce64e8 100644
--- a/phps-mode.el
+++ b/phps-mode.el
@@ -5,8 +5,8 @@
 ;; Author: Christian Johansson <address@hidden>
 ;; Maintainer: Christian Johansson <address@hidden>
 ;; Created: 3 Mar 2018
-;; Modified: 26 Sep 2019
-;; Version: 0.3.2
+;; Modified: 30 Sep 2019
+;; Version: 0.3.4
 ;; Keywords: tools, convenience
 ;; URL: https://github.com/cjohansson/emacs-phps-mode
 
@@ -30,7 +30,13 @@
 
 ;;; Commentary:
 
-;; A major-mode that uses original PHP lexer tokens for syntax coloring and 
indentation making it easier to spot errors in syntax.  Also includes full 
support for PSR-1 and PSR-2 indentation, imenu.  Improved syntax table in 
comparison with old PHP major-mode.
+;; A major-mode that uses original PHP lexer tokens for syntax coloring and 
indentation
+;; making it easier to spot errors in syntax.
+;;
+;; Also includes full support for PSR-1 and PSR-2 indentation and imenu.
+;; Improved syntax table in comparison with old PHP major-mode.
+;;
+;; For flycheck support run `(phps-mode-flycheck-setup)'.
 
 ;; Please see README.md from the same repository for extended documentation.
 
@@ -40,29 +46,19 @@
 
 ;; NOTE use wisent-parse-toggle-verbose-flag and (semantic-debug) to debug 
parsing
 
+(require 'phps-mode-analyzer)
 (require 'phps-mode-flymake)
-(require 'phps-mode-functions)
-(require 'phps-mode-lexer)
 (require 'phps-mode-semantic)
 (require 'phps-mode-syntax-table)
 (require 'phps-mode-tags)
 (require 'semantic)
 
-(defvar phps-mode-use-electric-pair-mode t
-  "Whether or not we want to use electric pair mode.")
-
-(defvar phps-mode-use-transient-mark-mode t
-  "Whether or not we want to use transient mark mode.")
-
 (defvar phps-mode-use-psr-2 t
   "Whether to use PSR-2 guidelines for white-space or not.")
 
 (defvar phps-mode-idle-interval 1
   "Idle seconds before running the incremental lexer.")
 
-(defvar phps-mode-flycheck-applied nil
-  "Boolean flag whether flycheck configuration has been applied or not.")
-
 (defvar phps-mode-inline-mmm-submode nil
   "Symbol declaring what mmm-mode to use as submode in inline areas.")
 
@@ -79,38 +75,48 @@
           (insert message)
           (insert "\n"))))))
 
-(defun phps-mode-get-syntax-table ()
-  "Get syntax table."
-  phps-mode-syntax-table)
-
 (defvar phps-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map (kbd "C-c /") #'comment-region)
-    (define-key map (kbd "C-c DEL") #'uncomment-region)
     (define-key map (kbd "C-c C-r") #'phps-mode-lexer-run)
     (define-key map (kbd "C-c C-f") #'phps-mode-format-buffer)
-    (define-key map (kbd "C-c C-p") 
#'phps-mode-functions-process-current-buffer)
     map)
   "Keymap for `phps-mode'.")
 
 ;;;###autoload
+(defun phps-mode-flycheck-setup ()
+  "Setup `flycheck' for `phps-mode'."
+  ;; Add support for flycheck PHP checkers: PHP, PHPMD and PHPCS here
+  ;; Do it only if flycheck is available
+  (when (fboundp 'flycheck-add-mode)
+    (flycheck-add-mode 'php 'phps-mode)
+    (flycheck-add-mode 'php-phpmd 'phps-mode)
+    (flycheck-add-mode 'php-phpcs 'phps-mode)))
+
+;;;###autoload
 (defun phps-mode-format-buffer ()
   "Format current buffer according to PHPs mode."
   (interactive)
-  (let ((old-buffer-contents (buffer-substring-no-properties (point-min) 
(point-max)))
-        (old-buffer (current-buffer))
-        (temp-buffer (generate-new-buffer "*PHPs Formatting*"))
-        (new-buffer-contents ""))
-    (save-excursion
-      (switch-to-buffer temp-buffer)
-      (insert old-buffer-contents)
-      (phps-mode)
-      (indent-region (point-min) (point-max))
-      (setq new-buffer-contents (buffer-substring-no-properties (point-min) 
(point-max)))
-      (kill-buffer)
-      (switch-to-buffer old-buffer)
-      (delete-region (point-min) (point-max))
-      (insert new-buffer-contents))))
+  (if (derived-mode-p 'phps-mode)
+      (progn
+        (when phps-mode-use-psr-2
+          (untabify (point-min) (point-max)))
+        (indent-region (point-min) (point-max)))
+    (let ((old-buffer-contents (buffer-substring-no-properties (point-min) 
(point-max)))
+          (old-buffer (current-buffer))
+          (temp-buffer (generate-new-buffer "*PHPs Formatting*"))
+          (new-buffer-contents ""))
+      (save-excursion
+        (switch-to-buffer temp-buffer)
+        (insert old-buffer-contents)
+        (phps-mode)
+        (when phps-mode-use-psr-2
+          (untabify (point-min) (point-max)))
+        (indent-region (point-min) (point-max))
+        (setq new-buffer-contents (buffer-substring-no-properties (point-min) 
(point-max)))
+        (kill-buffer)
+        (switch-to-buffer old-buffer)
+        (delete-region (point-min) (point-max))
+        (insert new-buffer-contents)))))
 
 (define-derived-mode phps-mode prog-mode "PHPs"
   "Major mode for PHP with Semantic integration."
@@ -118,20 +124,6 @@
   ;; Skip comments when navigating via syntax-table
   (setq-local parse-sexp-ignore-comments t)
 
-  ;; Key-map
-  (use-local-map phps-mode-map)
-
-  ;; Syntax table
-  (set-syntax-table phps-mode-syntax-table)
-
-  (when phps-mode-use-transient-mark-mode
-    ;; NOTE: These are required for wrapping region functionality
-    (transient-mark-mode))
-
-  ;; TODO Add this as a menu setting similar to php-mode?
-  (when phps-mode-use-electric-pair-mode
-    (electric-pair-local-mode))
-
   ;; Font lock
   ;; This makes it possible to have full control over syntax coloring from the 
lexer
   (setq-local font-lock-keywords-only nil)
@@ -140,16 +132,6 @@
   ;; Flymake TODO
   ;; (phps-mode-flymake-init)
 
-  ;; Flycheck
-  ;; Add support for flycheck PHP checkers: PHP, PHPMD and PHPCS here
-  ;; Do it once but only if flycheck is available
-  (when (and (fboundp 'flycheck-add-mode)
-             (not phps-mode-flycheck-applied))
-    (flycheck-add-mode 'php 'phps-mode)
-    (flycheck-add-mode 'php-phpmd 'phps-mode)
-    (flycheck-add-mode 'php-phpcs 'phps-mode)
-    (setq phps-mode-flycheck-applied t))
-
   ;; Custom indentation
   ;; Indent-region will call this on each line of selected region
   (setq-local indent-line-function #'phps-mode-functions-indent-line)
diff --git a/phps-mode-test-functions.el b/test/phps-mode-test-functions.el
similarity index 96%
rename from phps-mode-test-functions.el
rename to test/phps-mode-test-functions.el
index b30eb8d..53d2c83 100644
--- a/phps-mode-test-functions.el
+++ b/test/phps-mode-test-functions.el
@@ -27,8 +27,6 @@
 
 (require 'ert)
 (require 'phps-mode)
-(require 'phps-mode-functions)
-(require 'phps-mode-lexer)
 (require 'phps-mode-test)
 
 (defun phps-mode-test-functions-move-lines-indent ()
@@ -851,6 +849,13 @@
    (let ((buffer-contents (buffer-substring-no-properties (point-min) 
(point-max))))
      (should (equal buffer-contents "<html>\n    <head>\n        <title><?php 
echo $title; ?></title>\n    </head>\n    <body>\n        <div 
class=\"contents\"><?php echo $body; ?></div>\n    </body>\n</html>"))))
 
+  (phps-mode-test-with-buffer
+   "<html>\n<head>\n<title><?php echo $title; ?></title>\n</head>\n<body 
class=\"<?php echo $class; ?>\">\n<div class=\"contents\"><?php echo $body; 
?></div>\n</body>\n</html>"
+   "A mixed HTML and PHP file, each PHP command is inside HTML markup, one PHP 
inside markup tag"
+   (indent-region (point-min) (point-max))
+   (let ((buffer-contents (buffer-substring-no-properties (point-min) 
(point-max))))
+     (should (equal buffer-contents "<html>\n    <head>\n        <title><?php 
echo $title; ?></title>\n    </head>\n    <body class=\"<?php echo $class; 
?>\">\n        <div class=\"contents\"><?php echo $body; ?></div>\n    
</body>\n</html>"))))
+
   )
 
 (defun phps-mode-test-functions-imenu ()
@@ -869,52 +874,67 @@
   (phps-mode-test-with-buffer
    "<?php\nclass myClass {\n    public function myFunctionA() {}\n    
protected function myFunctionB() {}\n}\n"
    "Imenu object-oriented file"
-   (should (equal (phps-mode-functions-get-imenu) '(("myClass" . 
(("myFunctionA" . 43) ("myFunctionB" . 83)))))))
+   (should (equal (phps-mode-functions-get-imenu) '(("myClass" . 
(("*definition*" . 13) ("myFunctionA" . 43) ("myFunctionB" . 83)))))))
 
   (phps-mode-test-with-buffer
    "<?php\ninterface myInterface {\n    public function myFunctionA() {}\n    
protected function myFunctionB() {}\n}\n"
    "Imenu object-oriented file with interface"
-   (should (equal (phps-mode-functions-get-imenu) '(("myInterface" . 
(("myFunctionA" . 51) ("myFunctionB" . 91)))))))
+   (should (equal (phps-mode-functions-get-imenu) '(("myInterface" . 
(("*definition*" . 17) ("myFunctionA" . 51) ("myFunctionB" . 91)))))))
 
   (phps-mode-test-with-buffer
    "<?php\nnamespace myNamespace {\n    class myClass {\n        public 
function myFunctionA() {}\n        protected function myFunctionB() {}\n    
}\n}\n"
    "Imenu object-oriented file with namespace, class and function"
-   (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" ("myClass" 
("myFunctionA" . 75) ("myFunctionB" . 119)))))))
+   (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" 
("*definition*" . 17) ("myClass" ("*definition*" . 41) ("myFunctionA" . 75) 
("myFunctionB" . 119)))))))
 
   (phps-mode-test-with-buffer
    "<?php\nnamespace myNamespace;\nclass myClass {\n    public function 
myFunctionA() {}\n    protected function myFunctionB() {}\n}\n"
    "Imenu object-oriented file with bracket-less namespace, class and function"
-   (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" ("myClass" 
("myFunctionA" . 66) ("myFunctionB" . 106)))))))
+   (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" 
("*definition*" . 17) ("myClass" ("*definition*" . 36) ("myFunctionA" . 66) 
("myFunctionB" . 106)))))))
 
   (phps-mode-test-with-buffer
    "<?php\nnamespace myNamespace {\n    class myClass extends myAbstract {\n   
     public function myFunctionA() {}\n        protected function myFunctionB() 
{}\n    }\n}\n"
    "Imenu object-oriented file with namespace, class that extends and 
functions"
-   (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" ("myClass" 
("myFunctionA" . 94) ("myFunctionB" . 138)))))))
+   (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" 
("*definition*" . 17) ("myClass" ("*definition*" . 41) ("myFunctionA" . 94) 
("myFunctionB" . 138)))))))
 
   (phps-mode-test-with-buffer
    "<?php\nnamespace myNamespace;\nclass myClass extends myAbstract implements 
myInterface {\n    public function myFunctionA() {}\n    protected function 
myFunctionB() {}\n}\n"
    "Imenu object-oriented file with bracket-less namespace, class that extends 
and implements and functions"
-   (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" ("myClass" 
("myFunctionA" . 108) ("myFunctionB" . 148)))))))
+   (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" 
("*definition*" . 17) ("myClass" ("*definition*" . 36) ("myFunctionA" . 108) 
("myFunctionB" . 148)))))))
 
   (phps-mode-test-with-buffer
    "<?php\nnamespace myNamespace;\nclass myClass extends myAbstract implements 
myInterface {\n    public function myFunctionA($myArg = null) {}\n    protected 
function myFunctionB($myArg = 'abc') {}\n}\n"
    "Imenu object-oriented file with bracket-less namespace, class that extends 
and implements and functions with optional arguments"
-   (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" ("myClass" 
("myFunctionA" . 108) ("myFunctionB" . 161)))))))
+   (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" 
("*definition*" . 17) ("myClass" ("*definition*" . 36) ("myFunctionA" . 108) 
("myFunctionB" . 161)))))))
 
   (phps-mode-test-with-buffer
    "<?php\nnamespace myNamespace\\myNamespace2;\nclass myClass extends 
myAbstract implements myInterface {\n    public function myFunctionA($myArg = 
null) {}\n    protected function myFunctionB($myArg = 'abc') {}\n}\n"
    "Imenu object-oriented file with bracket-less namespace with multiple 
levels, class that extends and implements and functions with optional arguments"
-   (should (equal (phps-mode-functions-get-imenu) 
'(("myNamespace\\myNamespace2" ("myClass" ("myFunctionA" . 121) ("myFunctionB" 
. 174)))))))
+   (should (equal (phps-mode-functions-get-imenu) 
'(("myNamespace\\myNamespace2" ("*definition*" . 29) ("myClass" ("*definition*" 
. 49) ("myFunctionA" . 121) ("myFunctionB" . 174)))))))
 
   (phps-mode-test-with-buffer
    "<?php\nclass myClass\n{\n\n    public function myFunction1()\n    {\n      
  echo \"my string with variable {$variable} inside it\";\n    }\n\n    public 
function myFunction2()\n    {\n    }\n\n}"
    "Imenu with double quoted string with variable inside it"
-   (should (equal (phps-mode-functions-get-imenu) '(("myClass" ("myFunction1" 
. 44) ("myFunction2" . 153))))))
+   (should (equal (phps-mode-functions-get-imenu) '(("myClass" ("*definition*" 
. 13) ("myFunction1" . 44) ("myFunction2" . 153))))))
 
   (phps-mode-test-with-buffer
    "<?php\n\nnamespace MyNamespace;\n\nclass MyClass\n{\n\n    /**\n     *\n   
  */\n    public function __construct()\n    {\n        if ($test) {\n        
}\n    }\n\n    /**\n     *\n     */\n    public function myFunction1()\n    
{\n        $this->addMessage(\"My random {$message} here\" . ($random > 1 ? 
\"A\" : \"\") . \" was here.\");\n    }\n    \n    /**\n     *\n     */\n    
public function myFunction2()\n    {\n    }\n\n    /**\n     * It's good\n     
*/\n    public function my [...]
    "Imenu with double quoted string with variable inside it and concatenated 
string"
-   (should (equal (phps-mode-functions-get-imenu) '(("MyNamespace" ("MyClass" 
("__construct" . 92) ("myFunction1" . 193) ("myFunction2" . 365) ("myFunction3" 
. 445) ("myFunction4" . 515)))))))
+   (should (equal (phps-mode-functions-get-imenu) '(("MyNamespace" 
("*definition*" . 18) ("MyClass" ("*definition*" . 38) ("__construct" . 92) 
("myFunction1" . 193) ("myFunction2" . 365) ("myFunction3" . 445) 
("myFunction4" . 515)))))))
+
+  (phps-mode-test-with-buffer
+   "<?php\nclass myClass {}"
+   "Imenu empty class"
+   (should (equal (phps-mode-functions-get-imenu) '(("myClass" ("*definition*" 
. 13))))))
+
+  (phps-mode-test-with-buffer
+   "<?php\nnamespace myNamespace {}"
+   "Imenu empty bracketed namespace"
+   (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" 
("*definition*" . 17))))))
+
+  (phps-mode-test-with-buffer
+   "<?php\nnamespace myNamespace;"
+   "Imenu empty namespace without brackets"
+   (should (equal (phps-mode-functions-get-imenu) '(("myNamespace" 
("*definition*" . 17))))))
 
   )
 
diff --git a/phps-mode-test-integration.el b/test/phps-mode-test-integration.el
similarity index 99%
rename from phps-mode-test-integration.el
rename to test/phps-mode-test-integration.el
index bc572e8..0f7e522 100644
--- a/phps-mode-test-integration.el
+++ b/test/phps-mode-test-integration.el
@@ -26,8 +26,7 @@
 ;;; Code:
 
 (require 'ert)
-(require 'phps-mode-functions)
-(require 'phps-mode-lexer)
+(require 'phps-mode)
 (require 'phps-mode-test)
 
 (eval-when-compile
diff --git a/phps-mode-test-lexer.el b/test/phps-mode-test-lexer.el
similarity index 99%
rename from phps-mode-test-lexer.el
rename to test/phps-mode-test-lexer.el
index 0b3b05b..1abf3ce 100644
--- a/phps-mode-test-lexer.el
+++ b/test/phps-mode-test-lexer.el
@@ -27,7 +27,6 @@
 
 (require 'ert)
 (require 'phps-mode)
-(require 'phps-mode-lexer)
 (require 'phps-mode-test)
 
 (defun phps-mode-test-lexer-script-boundaries ()
diff --git a/phps-mode-test-parser.el b/test/phps-mode-test-parser.el
similarity index 100%
rename from phps-mode-test-parser.el
rename to test/phps-mode-test-parser.el
diff --git a/phps-mode-test-syntax-table.el 
b/test/phps-mode-test-syntax-table.el
similarity index 99%
rename from phps-mode-test-syntax-table.el
rename to test/phps-mode-test-syntax-table.el
index 84305bd..d9c9eab 100644
--- a/phps-mode-test-syntax-table.el
+++ b/test/phps-mode-test-syntax-table.el
@@ -26,7 +26,7 @@
 ;;; Code:
 
 (require 'ert)
-(require 'phps-mode-functions)
+(require 'phps-mode)
 (require 'phps-mode-test)
 
 ;; TODO Should test `backward-sexp', `forward-sexp', `backward-word', 
`forward-word', `backward-list', `forward-list' as well
diff --git a/phps-mode-test.el b/test/phps-mode-test.el
similarity index 98%
rename from phps-mode-test.el
rename to test/phps-mode-test.el
index 8050594..54c9c80 100644
--- a/phps-mode-test.el
+++ b/test/phps-mode-test.el
@@ -25,8 +25,7 @@
 
 (require 'ert)
 (require 'phps-mode)
-(require 'phps-mode-functions)
-(require 'phps-mode-lexer)
+(require 'phps-mode-macros)
 
 (defmacro phps-mode-test-incremental-vs-intial-buffer (source &optional title 
&rest change)
   "Set up test buffer with SOURCE, TITLE, apply CHANGE and compare incremental 
values with initial values."
@@ -118,6 +117,9 @@
           (sort (nreverse result) (lambda (a b) (< (car a) (car b)))))
       nil)))
 
+(transient-mark-mode t)
+(electric-pair-mode t)
+
 (provide 'phps-mode-test)
 
 ;;; phps-mode-test.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]