From 4d7ea86a8ee5bb56e9787cd36e9a838ae8191531 Mon Sep 17 00:00:00 2001 From: Pokey Rule Date: Mon, 6 Sep 2021 09:13:09 +0100 Subject: [PATCH 1/3] Add suffixedMatcher; use for keys --- src/languages/cpp.ts | 4 +-- src/languages/java.ts | 4 +-- src/languages/json.ts | 7 +++-- src/languages/python.ts | 9 +++--- src/languages/typescript.ts | 6 +++- .../recorded/languages/python/chuckKey.yml | 31 +++++++++++++++++++ .../recorded/languages/python/chuckKey2.yml | 31 +++++++++++++++++++ .../languages/typescript/chuckKey.yml | 29 +++++++++++++++++ .../languages/typescript/clearKey.yml | 29 +++++++++++++++++ src/util/nodeMatchers.ts | 19 +++++++++++- src/util/nodeSelectors.ts | 19 ++++++++++++ 11 files changed, 175 insertions(+), 13 deletions(-) create mode 100644 src/test/suite/fixtures/recorded/languages/python/chuckKey.yml create mode 100644 src/test/suite/fixtures/recorded/languages/python/chuckKey2.yml create mode 100644 src/test/suite/fixtures/recorded/languages/typescript/chuckKey.yml create mode 100644 src/test/suite/fixtures/recorded/languages/typescript/clearKey.yml diff --git a/src/languages/cpp.ts b/src/languages/cpp.ts index 8358f889f5..b4d8fb3949 100644 --- a/src/languages/cpp.ts +++ b/src/languages/cpp.ts @@ -1,7 +1,7 @@ import { createPatternMatchers, argumentMatcher, - valueMatcher, + prefixedMatcher, } from "../util/nodeMatchers"; import { NodeMatcherAlternative, ScopeType } from "../typings/Types"; @@ -95,7 +95,7 @@ const nodeMatchers: Partial> = { "function_definition[declarator][declarator]", // void funcName() {} "declaration.function_declarator![declarator]", // void funcName(); ], - value: valueMatcher( + value: prefixedMatcher( "*[declarator][value]", "*[value]", "assignment_expression[right]", diff --git a/src/languages/java.ts b/src/languages/java.ts index 965b487204..fb3921b013 100644 --- a/src/languages/java.ts +++ b/src/languages/java.ts @@ -1,7 +1,7 @@ import { createPatternMatchers, argumentMatcher, - valueMatcher, + prefixedMatcher, } from "../util/nodeMatchers"; import { NodeMatcherAlternative, ScopeType } from "../typings/Types"; @@ -62,7 +62,7 @@ const nodeMatchers: Partial> = { "method_declaration.identifier!", "constructor_declaration.identifier!", ], - value: valueMatcher("*[declarator][value]", "*[value]"), + value: prefixedMatcher("*[declarator][value]", "*[value]"), collectionItem: argumentMatcher("array_initializer"), argumentOrParameter: argumentMatcher("formal_parameters", "argument_list"), }; diff --git a/src/languages/json.ts b/src/languages/json.ts index d2b72a301a..ca902edaf0 100644 --- a/src/languages/json.ts +++ b/src/languages/json.ts @@ -1,7 +1,8 @@ import { createPatternMatchers, argumentMatcher, - valueMatcher, + prefixedMatcher, + suffixedMatcher, } from "../util/nodeMatchers"; import { ScopeType, NodeMatcherAlternative } from "../typings/Types"; @@ -10,8 +11,8 @@ const nodeMatchers: Partial> = { list: "array", string: "string", comment: "comment", - collectionKey: "pair[key]", - value: valueMatcher("*[value]"), + collectionKey: suffixedMatcher("pair[key]"), + value: prefixedMatcher("*[value]"), collectionItem: argumentMatcher("object", "array"), }; diff --git a/src/languages/python.ts b/src/languages/python.ts index 063bef283b..5f9595c773 100644 --- a/src/languages/python.ts +++ b/src/languages/python.ts @@ -2,7 +2,8 @@ import { SyntaxNode } from "web-tree-sitter"; import { createPatternMatchers, argumentMatcher, - valueMatcher, + prefixedMatcher, + suffixedMatcher, } from "../util/nodeMatchers"; import { NodeMatcherAlternative, ScopeType } from "../typings/Types"; @@ -46,7 +47,7 @@ const nodeMatchers: Partial> = { list: listTypes, statement: STATEMENT_TYPES, string: "string", - collectionKey: "pair[key]", + collectionKey: suffixedMatcher("pair[key]"), ifStatement: "if_statement", anonymousFunction: "lambda", functionCall: "call", @@ -55,7 +56,7 @@ const nodeMatchers: Partial> = { className: "class_definition[name]", namedFunction: "decorated_definition?.function_definition", functionName: "function_definition[name]", - type: valueMatcher("function_definition[return_type]", "*[type]"), + type: prefixedMatcher("function_definition[return_type]", "*[type]"), name: [ "assignment[left]", "typed_parameter.identifier!", @@ -63,7 +64,7 @@ const nodeMatchers: Partial> = { "*[name]", ], collectionItem: argumentMatcher(...dictionaryTypes, ...listTypes), - value: valueMatcher("assignment[right]", "~subscript[value]"), + value: prefixedMatcher("assignment[right]", "~subscript[value]"), argumentOrParameter: argumentMatcher("parameters", "argument_list"), }; diff --git a/src/languages/typescript.ts b/src/languages/typescript.ts index ac3ad463d0..fc83c7fe55 100644 --- a/src/languages/typescript.ts +++ b/src/languages/typescript.ts @@ -5,6 +5,7 @@ import { patternMatcher, createPatternMatchers, argumentMatcher, + suffixedMatcher, } from "../util/nodeMatchers"; import { NodeMatcherAlternative, @@ -86,7 +87,10 @@ const nodeMatchers: Partial> = { map: mapTypes, list: listTypes, string: ["string", "template_string"], - collectionKey: ["pair[key]", "jsx_attribute.property_identifier!"], + collectionKey: suffixedMatcher( + "pair[key]", + "jsx_attribute.property_identifier!" + ), collectionItem: argumentMatcher(...mapTypes, ...listTypes), value: valueMatcher(), ifStatement: "if_statement", diff --git a/src/test/suite/fixtures/recorded/languages/python/chuckKey.yml b/src/test/suite/fixtures/recorded/languages/python/chuckKey.yml new file mode 100644 index 0000000000..d97fa0cce1 --- /dev/null +++ b/src/test/suite/fixtures/recorded/languages/python/chuckKey.yml @@ -0,0 +1,31 @@ +spokenForm: chuck key +languageId: python +command: + actionName: remove + partialTargets: + - type: primitive + modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false} + extraArgs: [] +marks: {} +initialState: + documentContents: |- + { + "foo": "bar", + "baz": "bongo", + } + selections: + - anchor: {line: 1, character: 5} + active: {line: 1, character: 5} +finalState: + documentContents: |- + { + "bar", + "baz": "bongo", + } + selections: + - anchor: {line: 1, character: 4} + active: {line: 1, character: 4} + thatMark: + - anchor: {line: 1, character: 4} + active: {line: 1, character: 4} +fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, insideOutsideType: outside, modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false}}] diff --git a/src/test/suite/fixtures/recorded/languages/python/chuckKey2.yml b/src/test/suite/fixtures/recorded/languages/python/chuckKey2.yml new file mode 100644 index 0000000000..2ec06bafca --- /dev/null +++ b/src/test/suite/fixtures/recorded/languages/python/chuckKey2.yml @@ -0,0 +1,31 @@ +spokenForm: chuck key +languageId: python +command: + actionName: remove + partialTargets: + - type: primitive + modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false} + extraArgs: [] +marks: {} +initialState: + documentContents: |- + { + "foo": "bar", + "baz": "bongo", + } + selections: + - anchor: {line: 1, character: 12} + active: {line: 1, character: 12} +finalState: + documentContents: |- + { + "bar", + "baz": "bongo", + } + selections: + - anchor: {line: 1, character: 6} + active: {line: 1, character: 6} + thatMark: + - anchor: {line: 1, character: 4} + active: {line: 1, character: 4} +fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, insideOutsideType: outside, modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false}}] diff --git a/src/test/suite/fixtures/recorded/languages/typescript/chuckKey.yml b/src/test/suite/fixtures/recorded/languages/typescript/chuckKey.yml new file mode 100644 index 0000000000..6a74277f7d --- /dev/null +++ b/src/test/suite/fixtures/recorded/languages/typescript/chuckKey.yml @@ -0,0 +1,29 @@ +spokenForm: chuck key +languageId: typescript +command: + actionName: remove + partialTargets: + - type: primitive + modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false} + extraArgs: [] +marks: {} +initialState: + documentContents: |- + { + foo: "bar" + } + selections: + - anchor: {line: 1, character: 5} + active: {line: 1, character: 5} +finalState: + documentContents: |- + { + "bar" + } + selections: + - anchor: {line: 1, character: 4} + active: {line: 1, character: 4} + thatMark: + - anchor: {line: 1, character: 4} + active: {line: 1, character: 4} +fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, insideOutsideType: outside, modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false}}] diff --git a/src/test/suite/fixtures/recorded/languages/typescript/clearKey.yml b/src/test/suite/fixtures/recorded/languages/typescript/clearKey.yml new file mode 100644 index 0000000000..824f0456a0 --- /dev/null +++ b/src/test/suite/fixtures/recorded/languages/typescript/clearKey.yml @@ -0,0 +1,29 @@ +spokenForm: clear key +languageId: typescript +command: + actionName: clearAndSetSelection + partialTargets: + - type: primitive + modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false} + extraArgs: [] +marks: {} +initialState: + documentContents: |- + { + foo: "bar" + } + selections: + - anchor: {line: 1, character: 10} + active: {line: 1, character: 10} +finalState: + documentContents: |- + { + : "bar" + } + selections: + - anchor: {line: 1, character: 4} + active: {line: 1, character: 4} + thatMark: + - anchor: {line: 1, character: 4} + active: {line: 1, character: 4} +fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, insideOutsideType: inside, modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false}}] diff --git a/src/util/nodeMatchers.ts b/src/util/nodeMatchers.ts index ee3d4dd69d..e61a57a0bd 100644 --- a/src/util/nodeMatchers.ts +++ b/src/util/nodeMatchers.ts @@ -11,6 +11,7 @@ import { simpleSelectionExtractor, argumentSelectionExtractor, selectWithLeadingDelimiter, + selectWithTrailingDelimiter, } from "./nodeSelectors"; import { typedNodeFinder, @@ -72,10 +73,26 @@ export function argumentMatcher(...parentTypes: string[]): NodeMatcher { ); } -export function valueMatcher(...patterns: string[]): NodeMatcher { +/** + * Given `patterns`, creates a node matcher that will add leading delimiter to + * removal range. + * @param patterns Patterns for pattern finder + * @returns A node matcher + */ +export function prefixedMatcher(...patterns: string[]): NodeMatcher { return matcher(patternFinder(...patterns), selectWithLeadingDelimiter); } +/** + * Given `patterns`, creates a node matcher that will add trailing delimiter to + * removal range. + * @param patterns Patterns for pattern finder + * @returns A node matcher + */ +export function suffixedMatcher(...patterns: string[]): NodeMatcher { + return matcher(patternFinder(...patterns), selectWithTrailingDelimiter); +} + /** * Create a new matcher that will try the given matchers in sequence until one * returns non-null diff --git a/src/util/nodeSelectors.ts b/src/util/nodeSelectors.ts index 00c028b271..a00939f6e6 100644 --- a/src/util/nodeSelectors.ts +++ b/src/util/nodeSelectors.ts @@ -55,6 +55,25 @@ export function selectWithLeadingDelimiter( }; } +export function selectWithTrailingDelimiter( + editor: TextEditor, + node: SyntaxNode +): SelectionWithContext { + const trailingDelimiterToken = node.nextSibling; + + const trailingDelimiterRange = + trailingDelimiterToken != null + ? makeRange(node.endPosition, trailingDelimiterToken.endPosition) + : null; + + return { + ...simpleSelectionExtractor(editor, node), + context: { + trailingDelimiterRange, + }, + }; +} + function getNextNonDelimiterNode( startNode: SyntaxNode, isDelimiterNode: (node: SyntaxNode) => boolean From c25c457bf69607f1253903738cacd00e06987280 Mon Sep 17 00:00:00 2001 From: Pokey Rule Date: Mon, 6 Sep 2021 09:27:53 +0100 Subject: [PATCH 2/3] Fix whitespace --- .../fixtures/recorded/languages/python/chuckKey.yml | 2 +- .../fixtures/recorded/languages/python/chuckKey2.yml | 2 +- .../recorded/languages/python/chuckValue.yml | 2 +- .../recorded/languages/typescript/chuckKey.yml | 2 +- src/util/nodeSelectors.ts | 12 ++++++------ 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/suite/fixtures/recorded/languages/python/chuckKey.yml b/src/test/suite/fixtures/recorded/languages/python/chuckKey.yml index d97fa0cce1..308f9bfe12 100644 --- a/src/test/suite/fixtures/recorded/languages/python/chuckKey.yml +++ b/src/test/suite/fixtures/recorded/languages/python/chuckKey.yml @@ -19,7 +19,7 @@ initialState: finalState: documentContents: |- { - "bar", + "bar", "baz": "bongo", } selections: diff --git a/src/test/suite/fixtures/recorded/languages/python/chuckKey2.yml b/src/test/suite/fixtures/recorded/languages/python/chuckKey2.yml index 2ec06bafca..dfb1b7ed0e 100644 --- a/src/test/suite/fixtures/recorded/languages/python/chuckKey2.yml +++ b/src/test/suite/fixtures/recorded/languages/python/chuckKey2.yml @@ -19,7 +19,7 @@ initialState: finalState: documentContents: |- { - "bar", + "bar", "baz": "bongo", } selections: diff --git a/src/test/suite/fixtures/recorded/languages/python/chuckValue.yml b/src/test/suite/fixtures/recorded/languages/python/chuckValue.yml index 1eef01799f..333c44ae26 100644 --- a/src/test/suite/fixtures/recorded/languages/python/chuckValue.yml +++ b/src/test/suite/fixtures/recorded/languages/python/chuckValue.yml @@ -13,7 +13,7 @@ initialState: - anchor: {line: 0, character: 2} active: {line: 0, character: 2} finalState: - documentContents: "foo: str " + documentContents: "foo: str" selections: - anchor: {line: 0, character: 2} active: {line: 0, character: 2} diff --git a/src/test/suite/fixtures/recorded/languages/typescript/chuckKey.yml b/src/test/suite/fixtures/recorded/languages/typescript/chuckKey.yml index 6a74277f7d..337236886d 100644 --- a/src/test/suite/fixtures/recorded/languages/typescript/chuckKey.yml +++ b/src/test/suite/fixtures/recorded/languages/typescript/chuckKey.yml @@ -18,7 +18,7 @@ initialState: finalState: documentContents: |- { - "bar" + "bar" } selections: - anchor: {line: 1, character: 4} diff --git a/src/util/nodeSelectors.ts b/src/util/nodeSelectors.ts index a00939f6e6..e24262eba1 100644 --- a/src/util/nodeSelectors.ts +++ b/src/util/nodeSelectors.ts @@ -40,11 +40,11 @@ export function selectWithLeadingDelimiter( editor: TextEditor, node: SyntaxNode ): SelectionWithContext { - const leadingDelimiterToken = node.previousSibling; + const leadingNonDelimiterToken = node.previousSibling?.previousSibling; const leadingDelimiterRange = - leadingDelimiterToken != null - ? makeRange(leadingDelimiterToken.startPosition, node.startPosition) + leadingNonDelimiterToken != null + ? makeRange(leadingNonDelimiterToken.endPosition, node.startPosition) : null; return { @@ -59,11 +59,11 @@ export function selectWithTrailingDelimiter( editor: TextEditor, node: SyntaxNode ): SelectionWithContext { - const trailingDelimiterToken = node.nextSibling; + const trailingNonDelimiterToken = node.nextSibling?.nextSibling; const trailingDelimiterRange = - trailingDelimiterToken != null - ? makeRange(node.endPosition, trailingDelimiterToken.endPosition) + trailingNonDelimiterToken != null + ? makeRange(node.endPosition, trailingNonDelimiterToken.startPosition) : null; return { From 2526869c5279ca093d9edb0670f42e4ddb90d031 Mon Sep 17 00:00:00 2001 From: Pokey Rule Date: Mon, 6 Sep 2021 09:33:58 +0100 Subject: [PATCH 3/3] Fix tests --- .../suite/fixtures/recorded/languages/python/chuckKey2.yml | 4 ++-- .../suite/fixtures/recorded/languages/python/chuckValue.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/suite/fixtures/recorded/languages/python/chuckKey2.yml b/src/test/suite/fixtures/recorded/languages/python/chuckKey2.yml index dfb1b7ed0e..a79d64f4a7 100644 --- a/src/test/suite/fixtures/recorded/languages/python/chuckKey2.yml +++ b/src/test/suite/fixtures/recorded/languages/python/chuckKey2.yml @@ -23,8 +23,8 @@ finalState: "baz": "bongo", } selections: - - anchor: {line: 1, character: 6} - active: {line: 1, character: 6} + - anchor: {line: 1, character: 5} + active: {line: 1, character: 5} thatMark: - anchor: {line: 1, character: 4} active: {line: 1, character: 4} diff --git a/src/test/suite/fixtures/recorded/languages/python/chuckValue.yml b/src/test/suite/fixtures/recorded/languages/python/chuckValue.yml index 333c44ae26..7c637d1b57 100644 --- a/src/test/suite/fixtures/recorded/languages/python/chuckValue.yml +++ b/src/test/suite/fixtures/recorded/languages/python/chuckValue.yml @@ -18,6 +18,6 @@ finalState: - anchor: {line: 0, character: 2} active: {line: 0, character: 2} thatMark: - - anchor: {line: 0, character: 9} - active: {line: 0, character: 9} + - anchor: {line: 0, character: 8} + active: {line: 0, character: 8} fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, insideOutsideType: outside, modifier: {type: containingScope, scopeType: value, includeSiblings: false}}]