From 247bff462d7596476b6ba84fc8ac25e034893958 Mon Sep 17 00:00:00 2001 From: cjbarre Date: Thu, 17 Dec 2020 17:38:06 -0800 Subject: [PATCH 1/5] Tests passing. --- src/debugger/util.ts | 14 ++++++++------ .../expanded-form-of-syntax-quoted-map.clj | 12 ++++++++++++ .../syntax-quoted-map-with-syntax-unquote.clj | 5 +++++ src/extension-test/unit/debugger/util-test.ts | 8 ++++++++ 4 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 src/extension-test/unit/debugger/test-files/expanded-form-of-syntax-quoted-map.clj create mode 100644 src/extension-test/unit/debugger/test-files/syntax-quoted-map-with-syntax-unquote.clj diff --git a/src/debugger/util.ts b/src/debugger/util.ts index 3a63915e3..17e5ec494 100644 --- a/src/debugger/util.ts +++ b/src/debugger/util.ts @@ -38,13 +38,14 @@ function moveTokenCursorToBreakpoint(tokenCursor: LispTokenCursor, debugResponse inSyntaxQuote = true; } + + // A syntax quote is ending - this happens if ~ or ~@ precedes a form + if (previousToken.raw.match(/~@?/)) { + inSyntaxQuote = false; + } + if (inSyntaxQuote) { i++; // Ignore this coor and move to the next - - // A syntax quote is ending - this happens if ~ or ~@ precedes a form - if (previousToken.raw.match(/~@?/)) { - inSyntaxQuote = false; - } } if (inSyntaxQuote) { @@ -54,7 +55,8 @@ function moveTokenCursorToBreakpoint(tokenCursor: LispTokenCursor, debugResponse i++; } // Now we're inside the `concat` form, but we need to ignore the actual `concat` symbol - coor[i]--; + i++; + //coor[i]--; } // #() expands to (fn* ([] ...)) and this is what coor is calculated with, so ignore this coor and move to the next diff --git a/src/extension-test/unit/debugger/test-files/expanded-form-of-syntax-quoted-map.clj b/src/extension-test/unit/debugger/test-files/expanded-form-of-syntax-quoted-map.clj new file mode 100644 index 000000000..8cb6e528e --- /dev/null +++ b/src/extension-test/unit/debugger/test-files/expanded-form-of-syntax-quoted-map.clj @@ -0,0 +1,12 @@ +;; 3, 2, 2, 1, 2, 1 +(defn foo [] + (let [a "foo" + b "bar"] + (clojure.core/apply + clojure.core/hash-map + (clojure.core/seq + (clojure.core/concat + (clojure.core/list :a) + (clojure.core/list #break a|) + (clojure.core/list :b) + (clojure.core/list b)))))) \ No newline at end of file diff --git a/src/extension-test/unit/debugger/test-files/syntax-quoted-map-with-syntax-unquote.clj b/src/extension-test/unit/debugger/test-files/syntax-quoted-map-with-syntax-unquote.clj new file mode 100644 index 000000000..f75f48352 --- /dev/null +++ b/src/extension-test/unit/debugger/test-files/syntax-quoted-map-with-syntax-unquote.clj @@ -0,0 +1,5 @@ +;; 3, 2, 2, 1, 2, 1 +(defn foo [] + (let [a "foo" + b "bar"] + `{:a #break ~a| :b ~b})) \ No newline at end of file diff --git a/src/extension-test/unit/debugger/util-test.ts b/src/extension-test/unit/debugger/util-test.ts index ec6354d97..0655a2c3c 100644 --- a/src/extension-test/unit/debugger/util-test.ts +++ b/src/extension-test/unit/debugger/util-test.ts @@ -66,5 +66,13 @@ describe('Debugger Util', async () => { it('syntax quote', () => { expectBreakpointToBeFound('syntax-quote.clj'); }); + + it('syntax quoted map with ~ values', () => { + expectBreakpointToBeFound('syntax-quoted-map-with-syntax-unquote.clj'); + }); + + it('expanded form of syntax quoted map', () => { + expectBreakpointToBeFound('expanded-form-of-syntax-quoted-map.clj'); + }); }); }); From 9370e5a3b30f020aea8d5f04d70605daf18cf54e Mon Sep 17 00:00:00 2001 From: cjbarre Date: Fri, 18 Dec 2020 14:08:47 -0800 Subject: [PATCH 2/5] Add / alter tests for this issue. --- .../expanded-form-of-syntax-quoted-map.clj | 12 ------------ .../test-files/syntax-quoted-list-1.clj | 13 +++++++++++++ .../test-files/syntax-quoted-map-1.clj | 19 +++++++++++++++++++ .../syntax-quoted-map-with-syntax-unquote.clj | 5 ----- .../test-files/syntax-quoted-vector-1.clj | 15 +++++++++++++++ src/extension-test/unit/debugger/util-test.ts | 12 ++++++++---- 6 files changed, 55 insertions(+), 21 deletions(-) delete mode 100644 src/extension-test/unit/debugger/test-files/expanded-form-of-syntax-quoted-map.clj create mode 100644 src/extension-test/unit/debugger/test-files/syntax-quoted-list-1.clj create mode 100644 src/extension-test/unit/debugger/test-files/syntax-quoted-map-1.clj delete mode 100644 src/extension-test/unit/debugger/test-files/syntax-quoted-map-with-syntax-unquote.clj create mode 100644 src/extension-test/unit/debugger/test-files/syntax-quoted-vector-1.clj diff --git a/src/extension-test/unit/debugger/test-files/expanded-form-of-syntax-quoted-map.clj b/src/extension-test/unit/debugger/test-files/expanded-form-of-syntax-quoted-map.clj deleted file mode 100644 index 8cb6e528e..000000000 --- a/src/extension-test/unit/debugger/test-files/expanded-form-of-syntax-quoted-map.clj +++ /dev/null @@ -1,12 +0,0 @@ -;; 3, 2, 2, 1, 2, 1 -(defn foo [] - (let [a "foo" - b "bar"] - (clojure.core/apply - clojure.core/hash-map - (clojure.core/seq - (clojure.core/concat - (clojure.core/list :a) - (clojure.core/list #break a|) - (clojure.core/list :b) - (clojure.core/list b)))))) \ No newline at end of file diff --git a/src/extension-test/unit/debugger/test-files/syntax-quoted-list-1.clj b/src/extension-test/unit/debugger/test-files/syntax-quoted-list-1.clj new file mode 100644 index 000000000..b4b07ae5d --- /dev/null +++ b/src/extension-test/unit/debugger/test-files/syntax-quoted-list-1.clj @@ -0,0 +1,13 @@ +;; 3, 1, 1 +(defn fooz [x y] + `(#break :x| ~x :y ~y)) + +(comment + "Expanded form" + (defn fooz [x y] + (clojure.core/seq + (clojure.core/concat + (clojure.core/list :x) + (clojure.core/list x) + (clojure.core/list :y) + (clojure.core/list y))))) \ No newline at end of file diff --git a/src/extension-test/unit/debugger/test-files/syntax-quoted-map-1.clj b/src/extension-test/unit/debugger/test-files/syntax-quoted-map-1.clj new file mode 100644 index 000000000..e30828ee9 --- /dev/null +++ b/src/extension-test/unit/debugger/test-files/syntax-quoted-map-1.clj @@ -0,0 +1,19 @@ +;; 3, 2, 2, 1, 2, 1 +(defn foo [] + (let [a "foo" + b "bar"] + `{:a #break ~a| :b ~b})) + +(comment + "Expanded Form" + (defn foo [] + (let [a "foo" + b "bar"] + (clojure.core/apply + clojure.core/hash-map + (clojure.core/seq + (clojure.core/concat + (clojure.core/list :a) + (clojure.core/list a) + (clojure.core/list :b) + (clojure.core/list b))))))) \ No newline at end of file diff --git a/src/extension-test/unit/debugger/test-files/syntax-quoted-map-with-syntax-unquote.clj b/src/extension-test/unit/debugger/test-files/syntax-quoted-map-with-syntax-unquote.clj deleted file mode 100644 index f75f48352..000000000 --- a/src/extension-test/unit/debugger/test-files/syntax-quoted-map-with-syntax-unquote.clj +++ /dev/null @@ -1,5 +0,0 @@ -;; 3, 2, 2, 1, 2, 1 -(defn foo [] - (let [a "foo" - b "bar"] - `{:a #break ~a| :b ~b})) \ No newline at end of file diff --git a/src/extension-test/unit/debugger/test-files/syntax-quoted-vector-1.clj b/src/extension-test/unit/debugger/test-files/syntax-quoted-vector-1.clj new file mode 100644 index 000000000..c2cd7079f --- /dev/null +++ b/src/extension-test/unit/debugger/test-files/syntax-quoted-vector-1.clj @@ -0,0 +1,15 @@ +;; 3, 1, 1 +(defn fooz [x y] + `[#break :x| ~x :y ~y]) + +(comment + "Expanded form" + (defn fooz [x y] + (clojure.core/apply + clojure.core/vector + (clojure.core/seq + (clojure.core/concat + (clojure.core/list :x) + (clojure.core/list x) + (clojure.core/list :y) + (clojure.core/list y)))))) \ No newline at end of file diff --git a/src/extension-test/unit/debugger/util-test.ts b/src/extension-test/unit/debugger/util-test.ts index 0655a2c3c..6edee8cc2 100644 --- a/src/extension-test/unit/debugger/util-test.ts +++ b/src/extension-test/unit/debugger/util-test.ts @@ -67,12 +67,16 @@ describe('Debugger Util', async () => { expectBreakpointToBeFound('syntax-quote.clj'); }); - it('syntax quoted map with ~ values', () => { - expectBreakpointToBeFound('syntax-quoted-map-with-syntax-unquote.clj'); + it('syntax quoted map 1', () => { + expectBreakpointToBeFound('syntax-quoted-map-1.clj'); }); - it('expanded form of syntax quoted map', () => { - expectBreakpointToBeFound('expanded-form-of-syntax-quoted-map.clj'); + it('syntax quoted list 1', () => { + expectBreakpointToBeFound('syntax-quoted-list-1.clj'); + }); + + it('syntax quoted vector 1', () => { + expectBreakpointToBeFound('syntax-quoted-vector-1.clj'); }); }); }); From 4cd9d41c472db7f77fca3d63c6dfe6ea270a0150 Mon Sep 17 00:00:00 2001 From: cjbarre Date: Mon, 21 Dec 2020 13:44:45 -0800 Subject: [PATCH 3/5] Light refactoring for readability. --- src/debugger/util.ts | 50 +++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/debugger/util.ts b/src/debugger/util.ts index 17e5ec494..b1363d5b0 100644 --- a/src/debugger/util.ts +++ b/src/debugger/util.ts @@ -1,3 +1,4 @@ +import { Token } from "../cursor-doc/clojure-lexer"; import { LispTokenCursor } from "../cursor-doc/token-cursor"; function moveCursorPastStringInList(tokenCursor: LispTokenCursor, s: string): void { @@ -18,6 +19,30 @@ function moveCursorPastStringInList(tokenCursor: LispTokenCursor, s: string): vo } } +function syntaxQuoteBegins(token: Token) { + // Check if we just entered a syntax quote, since we have to account for how syntax quoted forms are read + // `(. .) is read as (seq (concat (list .) (list .))). + if (/.*\`(\[|\{|\()$/.test(token.raw)) { + return true; + } + return false; +} + +function syntaxQuoteEnds(token: Token) { + // A syntax quote is ending - this happens if ~ or ~@ precedes a form + if (token.raw.match(/~@?/)) { + return true; + } + return false; +} + +function listBegins(token: Token) { + if(token.raw.endsWith('(')) { + return true; + } + return false; +} + function moveTokenCursorToBreakpoint(tokenCursor: LispTokenCursor, debugResponse: any): LispTokenCursor { const errorMessage = "Error finding position of breakpoint"; @@ -32,31 +57,22 @@ function moveTokenCursorToBreakpoint(tokenCursor: LispTokenCursor, debugResponse } const previousToken = tokenCursor.getPrevToken(); - // Check if we just entered a syntax quote, since we have to account for how syntax quoted forms are read - // `(. .) is read as (seq (concat (list .) (list .))). - if (/.*\`(\[|\{|\()$/.test(previousToken.raw)) { - inSyntaxQuote = true; - } + inSyntaxQuote = syntaxQuoteBegins(previousToken); - - // A syntax quote is ending - this happens if ~ or ~@ precedes a form - if (previousToken.raw.match(/~@?/)) { + if (syntaxQuoteEnds(previousToken)) { inSyntaxQuote = false; } if (inSyntaxQuote) { - i++; // Ignore this coor and move to the next - } - - if (inSyntaxQuote) { - if (!previousToken.raw.endsWith('(')) { - // Non-list seqs like `[] and `{} are read with an extra (apply vector ...) or (apply hash-map ...) + // Ignore this coor and move to the next + i++; + // Now we're inside the `concat` form, but we need to ignore the actual `concat` symbol + i++; + // Non-list seqs like `[] and `{} are read with an extra (apply vector ...) or (apply hash-map ...) + if (!listBegins(previousToken)) { // Ignore this coor too i++; } - // Now we're inside the `concat` form, but we need to ignore the actual `concat` symbol - i++; - //coor[i]--; } // #() expands to (fn* ([] ...)) and this is what coor is calculated with, so ignore this coor and move to the next From 4990885fffb6cd3fb83dc665684f5c26d9893710 Mon Sep 17 00:00:00 2001 From: Brandon Ringe Date: Tue, 22 Dec 2020 10:30:50 -0800 Subject: [PATCH 4/5] Update test names --- src/extension-test/unit/debugger/util-test.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/extension-test/unit/debugger/util-test.ts b/src/extension-test/unit/debugger/util-test.ts index 6edee8cc2..9e67ba2df 100644 --- a/src/extension-test/unit/debugger/util-test.ts +++ b/src/extension-test/unit/debugger/util-test.ts @@ -43,39 +43,39 @@ describe('Debugger Util', async () => { expect(tokenCursor.getPrevToken().raw.endsWith('|')).toBe(true); } - it('simple example', () => { + it('handles simple example', () => { expectBreakpointToBeFound('simple.clj'); }); - it('function shorthand', () => { + it('handles function shorthand', () => { expectBreakpointToBeFound('fn-shorthand.clj'); }); - it('map', () => { + it('handles map', () => { expectBreakpointToBeFound('map.clj'); }); - it('metadata symbol', () => { + it('handles metadata symbol', () => { expectBreakpointToBeFound('metadata-symbol.clj'); }); - it('ignored forms', () => { + it('handles ignored forms', () => { expectBreakpointToBeFound('ignored-forms.clj'); }); - it('syntax quote', () => { + it('handles syntax quote', () => { expectBreakpointToBeFound('syntax-quote.clj'); }); - it('syntax quoted map 1', () => { + it('handles syntax quoted map 1', () => { expectBreakpointToBeFound('syntax-quoted-map-1.clj'); }); - it('syntax quoted list 1', () => { + it('handles syntax quoted list 1', () => { expectBreakpointToBeFound('syntax-quoted-list-1.clj'); }); - it('syntax quoted vector 1', () => { + it('handles syntax quoted vector 1', () => { expectBreakpointToBeFound('syntax-quoted-vector-1.clj'); }); }); From 8a9a0aa7b9b5fe037a5f57665126b03622ad746a Mon Sep 17 00:00:00 2001 From: Brandon Ringe Date: Tue, 22 Dec 2020 11:09:45 -0800 Subject: [PATCH 5/5] Add draft of new test method for moving cursor using coordinates --- src/extension-test/unit/debugger/util-test.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/extension-test/unit/debugger/util-test.ts b/src/extension-test/unit/debugger/util-test.ts index 9e67ba2df..2140b57de 100644 --- a/src/extension-test/unit/debugger/util-test.ts +++ b/src/extension-test/unit/debugger/util-test.ts @@ -32,6 +32,7 @@ describe('Debugger Util', async () => { }; }); + // Cider's test cases: https://github.com/clojure-emacs/cider/blob/f1c2a797291fd3d2a44cb32372852950d5ecf8a2/test/cider-debug-tests.el#L82 describe('moveTokenCursorToBreakpoint', () => { function expectBreakpointToBeFound(fileName: string) { @@ -43,8 +44,16 @@ describe('Debugger Util', async () => { expect(tokenCursor.getPrevToken().raw.endsWith('|')).toBe(true); } - it('handles simple example', () => { + function expectBreakpointToBeFound2(code: string, coor: number[]) { + doc.insertString(code); + const tokenCursor = doc.getTokenCursor(0); + moveTokenCursorToBreakpoint(tokenCursor, { coor }); + expect(tokenCursor.getPrevToken().raw.endsWith('|')).toBe(true); + } + + it('navigates the clojure sexpresions guided by the given coordinates', () => { expectBreakpointToBeFound('simple.clj'); + expectBreakpointToBeFound2('(defn a [] (let [x 1] (inc x|)) {:a 1, :b 2})', [3, 2, 1]); }); it('handles function shorthand', () => {