branch: externals/sql-indent
commit 75a4e24426f15643716dbc140e6e1e6fb4630755
Author: Pierre Téchoueyres <[email protected]>
Commit: Alex Harsányi <[email protected]>

    Correct detection of labels in `for` or `while` loops. (#48)
    
    Correct detection of labels in `for` or `while` loops.
---
 sql-indent-test.el     |  3 +++
 sql-indent.el          | 24 +++++++++++++---------
 test-data/pr48-syn.eld | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++
 test-data/pr48.sql     | 25 ++++++++++++++++++++++
 4 files changed, 98 insertions(+), 10 deletions(-)

diff --git a/sql-indent-test.el b/sql-indent-test.el
index f3d2e51..69be7e2 100644
--- a/sql-indent-test.el
+++ b/sql-indent-test.el
@@ -342,4 +342,7 @@ information read from DATA-FILE (as generated by
 (ert-deftest sqlind-ert-pr46 ()
   (sqlind-ert-check-file-syntax "test-data/pr46.sql" "test-data/pr46-syn.eld"))
 
+(ert-deftest sqlind-ert-pr48 ()
+  (sqlind-ert-check-file-syntax "test-data/pr48.sql" "test-data/pr48-syn.eld"))
+
 ;;; sql-indent-test.el ends here
diff --git a/sql-indent.el b/sql-indent.el
index 34844ae..586166f 100644
--- a/sql-indent.el
+++ b/sql-indent.el
@@ -300,7 +300,7 @@ But don't go before LIMIT."
     (catch 'done
       (while (> (point) (or limit (point-min)))
         (when (re-search-backward
-               
";\\|:=\\|\\_<\\(declare\\|begin\\|cursor\\|for\\|loop\\|if\\|then\\|else\\|elsif\\)\\_>\\|)"
+               
";\\|:=\\|\\_<\\(declare\\|begin\\|cursor\\|for\\|while\\|loop\\|if\\|then\\|else\\|elsif\\)\\_>\\|)"
                limit 'noerror)
           (unless (sqlind-in-comment-or-string (point))
             (let ((candidate-pos (match-end 0)))
@@ -309,7 +309,7 @@ But don't go before LIMIT."
                      ;; of the keywords inside one of them and think this is a
                      ;; statement start.
                      (progn (forward-char 1) (forward-sexp -1)))
-                    ((looking-at "cursor\\|for")
+                    ((looking-at "cursor\\|for\\|while")
                      ;; statement begins at the start of the keyword
                      (throw 'done (point)))
                     ((looking-at "then\\|else")
@@ -530,19 +530,23 @@ See also `sqlind-beginning-of-block'"
       ;; note that we might have found a loop in an "end loop;" statement.
       (or (sqlind-maybe-end-statement)
           (progn
-            (let ((loop-label (if (looking-at "<<\\([a-z0-9_]+\\)>>")
-                                  (sqlind-match-string 1) "")))
-              ;; start of loop.  this always starts a block, we only check if
-              ;; the labels match
-              (if (null sqlind-end-stmt-stack)
-                  (throw 'finished (list 'in-block 'loop loop-label))
+            (let ((posn (point)))
+             (forward-word -1)
+             (sqlind-beginning-of-statement)
+             (let ((loop-label (if (looking-at "<<\\([a-z0-9_]+\\)>>")
+                                   (sqlind-match-string 1) "")))
+               (goto-char posn)
+               ;; start of loop.  this always starts a block, we only check if
+               ;; the labels match
+               (if (null sqlind-end-stmt-stack)
+                   (throw 'finished (list 'in-block 'loop loop-label))
                   (cl-destructuring-bind (pos kind label)
                       (pop sqlind-end-stmt-stack)
                     (unless (and (eq kind 'loop)
                                  (sqlind-labels-match label loop-label))
                       (throw 'finished
-                        (list 'syntax-error
-                              "bad closing for loop block" (point) 
pos)))))))))))
+                            (list 'syntax-error
+                                  "bad closing for loop block" (point) 
pos))))))))))))
 
 (defun sqlind-maybe-begin-statement ()
   "Return the syntax of a \"begin\" statement.
diff --git a/test-data/pr48-syn.eld b/test-data/pr48-syn.eld
new file mode 100644
index 0000000..8357c18
--- /dev/null
+++ b/test-data/pr48-syn.eld
@@ -0,0 +1,56 @@
+((((block-start begin)
+   . 1)
+  (toplevel . 1))
+ (((in-begin-block toplevel-block "")
+   . 1))
+ (((in-begin-block toplevel-block "")
+   . 1))
+ (((in-begin-block toplevel-block "")
+   . 1))
+ ((labeled-statement-start . 87)
+  (statement-continuation . 87))
+ (((in-block loop "my_loop")
+   . 101))
+ (((block-end loop "my_loop")
+   . 101)
+  ((in-block loop "my_loop")
+   . 101))
+ (((in-begin-block toplevel-block "")
+   . 1))
+ (((in-begin-block toplevel-block "")
+   . 1))
+ (((in-begin-block toplevel-block "")
+   . 1))
+ ((labeled-statement-start . 229)
+  (statement-continuation . 229))
+ (((in-block loop "my_second_loop")
+   . 250))
+ (((in-block loop "my_second_loop")
+   . 250))
+ (((block-end loop "my_second_loop")
+   . 250)
+  ((in-block loop "my_second_loop")
+   . 250))
+ (((in-begin-block toplevel-block "")
+   . 1))
+ (((block-end toplevel-block "")
+   . 1)
+  ((in-begin-block toplevel-block "")
+   . 1))
+ ((toplevel . 1))
+ ((toplevel . 1))
+ ((comment-start . 1)
+  (toplevel . 1))
+ ((comment-start . 1)
+  (toplevel . 1))
+ ((comment-start . 1)
+  (toplevel . 1))
+ ((comment-start . 1)
+  (toplevel . 1))
+ ((comment-start . 1)
+  (toplevel . 1))
+ ((comment-start . 1)
+  (toplevel . 1))
+ ((comment-start . 1)
+  (toplevel . 1))
+ ((toplevel . 1)))
diff --git a/test-data/pr48.sql b/test-data/pr48.sql
new file mode 100644
index 0000000..527ee54
--- /dev/null
+++ b/test-data/pr48.sql
@@ -0,0 +1,25 @@
+begin
+  goto my_loop;
+  dbms_output.put_line('If you read it, you''re in trouble');
+  <<my_loop>>
+  for ind in 1..5 loop
+    dbms_output.put_line('ind: ' || ind);
+  end loop my_loop;
+
+  dbms_output.put_line('end of my_loop');
+  <<my_second_loop>>
+  while true loop
+    dbms_output.put_line('in my_second_loop');
+    goto out_of_loop;
+  end loop my_second_loop;
+  dbms_output.put_line('end of my_second_loop');
+end;
+/
+
+-- Local Variables:
+-- indent-tabs-mode: nil
+-- mode: sql
+-- mode: sqlind-minor
+-- sql-product: oracle
+-- tab-width: 2
+-- End:

Reply via email to