diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e2401037..e4a2c2887 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,11 @@ Changes to Calva. ## [Unreleased] +- Maintenance: [Dumb down the token cursor some dealing with meta data and readers](https://github.com/BetterThanTomorrow/calva/pull/1585) ## [2.0.253] - 2022-03-09 - Fix: [Structural editing hangs in specific cases of unbalanced forms](https://github.com/BetterThanTomorrow/calva/pull/1585) -- Fix: [over snippet markdown and adds example](https://github.com/BetterThanTomorrow/calva/pull/1582) +- Fix: [Hover snippet markdown and adds example](https://github.com/BetterThanTomorrow/calva/pull/1582) - Maintenance: [Begin work on enabling strictNullChecks in the TypeScript config.](https://github.com/BetterThanTomorrow/calva/pull/1568) ## [2.0.252] - 2022-03-05 diff --git a/src/cursor-doc/paredit.ts b/src/cursor-doc/paredit.ts index ef6e97f14..fa01b38e3 100644 --- a/src/cursor-doc/paredit.ts +++ b/src/cursor-doc/paredit.ts @@ -325,17 +325,7 @@ export function rangeToForwardDownList( goPastWhitespace = false ): [number, number] { const cursor = doc.getTokenCursor(offset); - do { - cursor.forwardThroughAnyReader(); - cursor.forwardWhitespace(); - if ( - cursor.getToken().type === 'open' && - !cursor.tokenBeginsMetadata() - ) { - break; - } - } while (cursor.forwardSexp()); - if (cursor.downList(true)) { + if (cursor.downListSkippingMeta()) { if (goPastWhitespace) { cursor.forwardWhitespace(); } diff --git a/src/cursor-doc/token-cursor.ts b/src/cursor-doc/token-cursor.ts index 26e100f1b..d2f71df15 100644 --- a/src/cursor-doc/token-cursor.ts +++ b/src/cursor-doc/token-cursor.ts @@ -578,20 +578,15 @@ export class LispTokenCursor extends TokenCursor { } /** - * If possible, moves this cursor forwards past any whitespace, and then past the immediately following open-paren and returns true. + * If possible, moves this cursor forwards past any readers and whitespace, + * and then past the immediately following open-paren and returns true. * If the source does not match this, returns false and does not move the cursor. */ - downList(skipMetadata = false): boolean { + downList(): boolean { const cursor = this.clone(); cursor.forwardThroughAnyReader(); cursor.forwardWhitespace(); if (cursor.getToken().type === 'open') { - if (skipMetadata) { - while (cursor.tokenBeginsMetadata()) { - cursor.forwardSexp(); - cursor.forwardWhitespace(); - } - } cursor.next(); this.set(cursor); return true; @@ -599,6 +594,30 @@ export class LispTokenCursor extends TokenCursor { return false; } + /** + * If possible, moves this cursor forwards past any readers, whitespace, and metadata, + * and then past the immediately following open-paren and returns true. + * If the source does not match this, returns false and does not move the cursor. + */ + downListSkippingMeta(): boolean { + const cursor = this.clone(); + do { + cursor.forwardThroughAnyReader(); + cursor.forwardWhitespace(); + if ( + cursor.getToken().type === 'open' && + !cursor.tokenBeginsMetadata() + ) { + break; + } + } while (cursor.forwardSexp()); + if (cursor.downList()) { + this.set(cursor); + return true; + } + return false; + } + /** * If possible, moves this cursor forwards past any whitespace, and then past the immediately following close-paren and returns true. * If the source does not match this, returns false and does not move the cursor. diff --git a/src/debugger/util.ts b/src/debugger/util.ts index 7ad2cae13..df502cf83 100644 --- a/src/debugger/util.ts +++ b/src/debugger/util.ts @@ -31,7 +31,7 @@ function moveTokenCursorToBreakpoint( const coor = [...debugResponse.coor]; // Copy the array so we do not modify the one stored in state for (let i = 0; i < coor.length; i++) { - while (!tokenCursor.downList(true)) { + while (!tokenCursor.downListSkippingMeta()) { tokenCursor.next(); } const previousToken = tokenCursor.getPrevToken(); diff --git a/src/extension-test/unit/cursor-doc/token-cursor-test.ts b/src/extension-test/unit/cursor-doc/token-cursor-test.ts index bca67b417..2644b703f 100644 --- a/src/extension-test/unit/cursor-doc/token-cursor-test.ts +++ b/src/extension-test/unit/cursor-doc/token-cursor-test.ts @@ -273,18 +273,28 @@ describe('Token Cursor', () => { cursor.downList(); expect(cursor.offsetStart).toBe(b.selectionLeft); }); - it('Does not skip metadata by default', () => { + it('Does not skip metadata', () => { const a = docFromTextNotation('(a| ^{:x 1} (b 1))'); const b = docFromTextNotation('(a ^{|:x 1} (b 1))'); const cursor: LispTokenCursor = a.getTokenCursor(a.selectionLeft); cursor.downList(); expect(cursor.offsetStart).toBe(b.selectionLeft); }); - it('Skips metadata when skipMetadata is true', () => { - const a = docFromTextNotation('(a| ^{:x 1} (b 1))'); - const b = docFromTextNotation('(a ^{:x 1} (|b 1))'); + }); + + describe('downListSkippingMeta', () => { + it('Moves down, skipping metadata', () => { + const a = docFromTextNotation('(|a #b ^{:x 1} (c 1))'); + const b = docFromTextNotation('(a #b ^{:x 1} (|c 1))'); + const cursor: LispTokenCursor = a.getTokenCursor(a.selectionLeft); + cursor.downListSkippingMeta(); + expect(cursor.offsetStart).toBe(b.selectionLeft); + }); + it('Moves down when there is no metadata', () => { + const a = docFromTextNotation('(|a #b (c 1))'); + const b = docFromTextNotation('(a #b (|c 1))'); const cursor: LispTokenCursor = a.getTokenCursor(a.selectionLeft); - cursor.downList(true); + cursor.downListSkippingMeta(); expect(cursor.offsetStart).toBe(b.selectionLeft); }); }); diff --git a/src/extension-test/unit/debugger/test-files/metadata-map-last.clj b/src/extension-test/unit/debugger/test-files/metadata-map-last.clj new file mode 100644 index 000000000..cd3ca8169 --- /dev/null +++ b/src/extension-test/unit/debugger/test-files/metadata-map-last.clj @@ -0,0 +1,7 @@ +;; 3, 2, 2, 2 +#dbg + (defn test-metadata-symbol + [x] + (let [y x] + ^{:hello "world"} + (+ x ^{:inner "meta"} (+ 1 y|)))) \ No newline at end of file diff --git a/src/extension-test/unit/debugger/test-files/metadata-map.clj b/src/extension-test/unit/debugger/test-files/metadata-map.clj new file mode 100644 index 000000000..b8adc4d70 --- /dev/null +++ b/src/extension-test/unit/debugger/test-files/metadata-map.clj @@ -0,0 +1,6 @@ +;; 3, 2, 2, 2 +(defn test-metadata-symbol + [x] + (let [y x] + ^{:hello "world"} + (+ x ^{:inner "meta"} (+ 1 #break 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 789376943..8a6a21c79 100644 --- a/src/extension-test/unit/debugger/util-test.ts +++ b/src/extension-test/unit/debugger/util-test.ts @@ -60,6 +60,14 @@ describe('Debugger Util', () => { expectBreakpointToBeFound('metadata-symbol.clj'); }); + it('metadata map', () => { + expectBreakpointToBeFound('metadata-map.clj'); + }); + + it('metadata map last sexp', () => { + expectBreakpointToBeFound('metadata-map-last.clj'); + }); + it('ignored forms', () => { expectBreakpointToBeFound('ignored-forms.clj'); }); diff --git a/test-data/debugger_metadata.clj b/test-data/debugger_metadata.clj new file mode 100644 index 000000000..d1c4bad5c --- /dev/null +++ b/test-data/debugger_metadata.clj @@ -0,0 +1,18 @@ +(ns debugger-metadata) + +#dbg + (defn test-metadata-symbol + [x] + (let [y x] + ^{:hello "world"} + (+ x ^{:inner "meta"} (+ 1 y)))) + +(defn test-metadata-symbol2 + [x] + (let [y x] + ^{:hello "world"} + (+ x ^{:inner "meta"} (+ 1 #break y)))) + +(comment + (test-metadata-symbol 42) + (test-metadata-symbol2 42)) \ No newline at end of file