Support abstract methods (#1063)

* Support abstract methods

* Use trailing matcher

* Don't remove extra whitespace; always remove `;`

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

Co-authored-by: Pokey Rule <755842+pokey@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Andreas Arvidsson 2022-10-23 09:29:02 +02:00 committed by GitHub
parent 5589b5e39e
commit 0b651c786b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 175 additions and 25 deletions

View File

@ -17,12 +17,13 @@ import {
} from "../util/nodeMatchers";
import {
childRangeSelector,
xmlElementExtractor,
extendForwardPastOptional,
getNodeInternalRange,
getNodeRange,
pairSelectionExtractor,
selectWithLeadingDelimiter,
simpleSelectionExtractor,
xmlElementExtractor,
} from "../util/nodeSelectors";
// Generated by the following command:
@ -223,6 +224,8 @@ const nodeMatchers: Partial<
"function[name]",
// class method
"method_definition[name]",
// abstract class method
"abstract_method_signature[name]",
// class arrow method
"public_field_definition[name].arrow_function",
// const foo = function() { }
@ -234,30 +237,37 @@ const nodeMatchers: Partial<
// foo = () => { }
"assignment_expression[left].arrow_function",
],
namedFunction: [
// [export] function
"export_statement?.function_declaration",
// export default function
// NB: We require export statement because otherwise it is an anonymous
// function
"export_statement.function",
// export default arrow
"export_statement.arrow_function",
// class method
"method_definition",
// class arrow method
"public_field_definition.arrow_function",
// [export] const foo = function() { }
"export_statement?.lexical_declaration.variable_declarator.function",
// [export] const foo = () => { }
"export_statement?.lexical_declaration.variable_declarator.arrow_function",
// foo = function() { }
"assignment_expression.function",
// foo = () => { }
"assignment_expression.arrow_function",
// foo = function*() { }
"generator_function_declaration",
],
namedFunction: cascadingMatcher(
patternMatcher(
// [export] function
"export_statement?.function_declaration",
// export default function
// NB: We require export statement because otherwise it is an anonymous
// function
"export_statement.function",
// export default arrow
"export_statement.arrow_function",
// class method
"method_definition",
// class arrow method
"public_field_definition.arrow_function",
// [export] const foo = function() { }
"export_statement?.lexical_declaration.variable_declarator.function",
// [export] const foo = () => { }
"export_statement?.lexical_declaration.variable_declarator.arrow_function",
// foo = function() { }
"assignment_expression.function",
// foo = () => { }
"assignment_expression.arrow_function",
// foo = function*() { }
"generator_function_declaration"
),
// abstract class method
matcher(
patternFinder("abstract_method_signature"),
extendForwardPastOptional(";")
)
),
type: cascadingMatcher(
// Typed parameters, properties, and functions
typeMatcher(),

View File

@ -0,0 +1,29 @@
languageId: typescript
command:
spokenForm: clear funk
version: 3
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: namedFunction}
usePrePhraseSnapshot: true
action: {name: clearAndSetSelection}
initialState:
documentContents: |-
abstract class Foo {
protected abstract bar(): void;
}
selections:
- anchor: {line: 1, character: 26}
active: {line: 1, character: 26}
marks: {}
finalState:
documentContents: |-
abstract class Foo {
}
selections:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: containingScope, scopeType: {type: namedFunction}}]}]

View File

@ -0,0 +1,29 @@
languageId: typescript
command:
spokenForm: clear funk name
version: 3
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: functionName}
usePrePhraseSnapshot: true
action: {name: clearAndSetSelection}
initialState:
documentContents: |-
abstract class Foo {
protected abstract bar(): void;
}
selections:
- anchor: {line: 1, character: 30}
active: {line: 1, character: 30}
marks: {}
finalState:
documentContents: |-
abstract class Foo {
protected abstract (): void;
}
selections:
- anchor: {line: 1, character: 23}
active: {line: 1, character: 23}
fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: containingScope, scopeType: {type: functionName}}]}]

View File

@ -0,0 +1,35 @@
languageId: typescript
command:
spokenForm: ditch funk
version: 3
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: namedFunction}
usePrePhraseSnapshot: true
action: {name: remove}
initialState:
documentContents: |-
abstract class Foo {
protected abstract bar(): void;
protected abstract bongo(): void;
baz() {}
}
selections:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 4}
marks: {}
finalState:
documentContents: |-
abstract class Foo {
protected abstract bar(): void;
baz() {}
}
selections:
- anchor: {line: 2, character: 0}
active: {line: 2, character: 0}
fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: containingScope, scopeType: {type: namedFunction}}]}]

View File

@ -0,0 +1,29 @@
languageId: typescript
command:
spokenForm: ditch funk
version: 3
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: namedFunction}
usePrePhraseSnapshot: true
action: {name: remove}
initialState:
documentContents: |-
abstract class Foo {
protected abstract bongo(): void;
}
selections:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
marks: {}
finalState:
documentContents: |-
abstract class Foo {
}
selections:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 0}
fullTargets: [{type: primitive, mark: {type: cursor}, modifiers: [{type: containingScope, scopeType: {type: namedFunction}}]}]

View File

@ -101,6 +101,24 @@ function getNextMatchingSiblingNodeOrLast(
return currentNode;
}
/**
* Creates an extractor that will extend past the next node if it has one of the
* types defined in {@link delimiters}
* @param delimiters Allowable next node type
* @returns An extractor
*/
export function extendForwardPastOptional(...delimiters: string[]) {
return function (editor: TextEditor, node: SyntaxNode): SelectionWithContext {
const nextNode: SyntaxNode | null = node.nextSibling;
if (nextNode != null && delimiters.includes(nextNode.type)) {
return pairSelectionExtractor(editor, node, nextNode);
}
return simpleSelectionExtractor(editor, node);
};
}
/**
* Extracts a selection from the first node to the second node.
* Both nodes are included in the selected nodes