mirror of
https://github.com/dart-lang/sdk
synced 2024-09-20 00:11:50 +00:00
[analysis_server] Add snippet for function definitions
Fixes https://github.com/Dart-Code/Dart-Code/issues/4017. Change-Id: I1017be3abe73a8cfcd6354f1c2ca99ad729dcf47 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/247553 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
4894ae493f
commit
5b3bfe4137
|
@ -166,6 +166,47 @@ class DartForLoopSnippetProducer extends DartSnippetProducer {
|
|||
DartForLoopSnippetProducer._(request);
|
||||
}
|
||||
|
||||
/// Produces a [Snippet] that creates a function definition.
|
||||
class DartFunctionSnippetProducer extends DartSnippetProducer {
|
||||
static const prefix = 'fun';
|
||||
static const label = 'fun';
|
||||
|
||||
DartFunctionSnippetProducer._(super.request);
|
||||
|
||||
@override
|
||||
Future<Snippet> compute() async {
|
||||
final builder = ChangeBuilder(session: request.analysisSession);
|
||||
final indent = utils.getLinePrefix(request.offset);
|
||||
|
||||
await builder.addDartFileEdit(request.filePath, (builder) {
|
||||
builder.addReplacement(request.replacementRange, (builder) {
|
||||
void writeIndented(String string) => builder.write('$indent$string');
|
||||
|
||||
builder.addSimpleLinkedEdit('returnType', 'void');
|
||||
builder.write(' ');
|
||||
builder.addSimpleLinkedEdit('name', 'name');
|
||||
builder.write('(');
|
||||
builder.addSimpleLinkedEdit('params', 'params');
|
||||
builder.writeln(') {');
|
||||
writeIndented(' ');
|
||||
builder.selectHere();
|
||||
builder.writeln();
|
||||
writeIndented('}');
|
||||
});
|
||||
});
|
||||
|
||||
return Snippet(
|
||||
prefix,
|
||||
label,
|
||||
'Insert a function definition.',
|
||||
builder.sourceChange,
|
||||
);
|
||||
}
|
||||
|
||||
static DartFunctionSnippetProducer newInstance(DartSnippetRequest request) =>
|
||||
DartFunctionSnippetProducer._(request);
|
||||
}
|
||||
|
||||
/// Produces a [Snippet] that creates an if/else statement.
|
||||
class DartIfElseSnippetProducer extends DartSnippetProducer {
|
||||
static const prefix = 'ife';
|
||||
|
|
|
@ -29,8 +29,10 @@ class DartSnippetManager {
|
|||
FlutterStatefulWidgetWithAnimationControllerSnippetProducer.newInstance,
|
||||
FlutterStatelessWidgetSnippetProducer.newInstance,
|
||||
DartClassSnippetProducer.newInstance,
|
||||
DartFunctionSnippetProducer.newInstance,
|
||||
],
|
||||
SnippetContext.inBlock: [
|
||||
DartFunctionSnippetProducer.newInstance,
|
||||
DartDoWhileLoopSnippetProducer.newInstance,
|
||||
DartForInLoopSnippetProducer.newInstance,
|
||||
DartForLoopSnippetProducer.newInstance,
|
||||
|
@ -42,6 +44,9 @@ class DartSnippetManager {
|
|||
DartTestBlockSnippetProducer.newInstance,
|
||||
DartTestGroupBlockSnippetProducer.newInstance,
|
||||
],
|
||||
SnippetContext.inClass: [
|
||||
DartFunctionSnippetProducer.newInstance,
|
||||
]
|
||||
};
|
||||
|
||||
Future<List<Snippet>> computeSnippets(
|
||||
|
|
|
@ -2639,6 +2639,71 @@ void f() {
|
|||
''');
|
||||
}
|
||||
|
||||
Future<void> test_snippets_functionClassMember() async {
|
||||
final content = '''
|
||||
class A {
|
||||
fun^
|
||||
}
|
||||
''';
|
||||
|
||||
await initializeWithSnippetSupport();
|
||||
final updated = await expectAndApplySnippet(
|
||||
content,
|
||||
prefix: DartFunctionSnippetProducer.prefix,
|
||||
label: DartFunctionSnippetProducer.label,
|
||||
);
|
||||
|
||||
expect(updated, r'''
|
||||
class A {
|
||||
${1:void} ${2:name}(${3:params}) {
|
||||
$0
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_snippets_functionNested() async {
|
||||
final content = '''
|
||||
void a() {
|
||||
fun^
|
||||
}
|
||||
''';
|
||||
|
||||
await initializeWithSnippetSupport();
|
||||
final updated = await expectAndApplySnippet(
|
||||
content,
|
||||
prefix: DartFunctionSnippetProducer.prefix,
|
||||
label: DartFunctionSnippetProducer.label,
|
||||
);
|
||||
|
||||
expect(updated, r'''
|
||||
void a() {
|
||||
${1:void} ${2:name}(${3:params}) {
|
||||
$0
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_snippets_functionTopLevel() async {
|
||||
final content = '''
|
||||
fun^
|
||||
''';
|
||||
|
||||
await initializeWithSnippetSupport();
|
||||
final updated = await expectAndApplySnippet(
|
||||
content,
|
||||
prefix: DartFunctionSnippetProducer.prefix,
|
||||
label: DartFunctionSnippetProducer.label,
|
||||
);
|
||||
|
||||
expect(updated, r'''
|
||||
${1:void} ${2:name}(${3:params}) {
|
||||
$0
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_snippets_if() async {
|
||||
final content = '''
|
||||
void f() {
|
||||
|
|
|
@ -23,6 +23,7 @@ void main() {
|
|||
defineReflectiveTests(DartTryCatchSnippetProducerTest);
|
||||
defineReflectiveTests(DartWhileLoopSnippetProducerTest);
|
||||
defineReflectiveTests(DartClassSnippetProducerTest);
|
||||
defineReflectiveTests(DartFunctionSnippetProducerTest);
|
||||
defineReflectiveTests(DartTestBlockSnippetProducerTest);
|
||||
defineReflectiveTests(DartTestGroupBlockSnippetProducerTest);
|
||||
});
|
||||
|
@ -215,6 +216,160 @@ void f() {
|
|||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class DartFunctionSnippetProducerTest extends DartSnippetProducerTest {
|
||||
@override
|
||||
final generator = DartFunctionSnippetProducer.newInstance;
|
||||
|
||||
@override
|
||||
String get label => DartFunctionSnippetProducer.label;
|
||||
|
||||
@override
|
||||
String get prefix => DartFunctionSnippetProducer.prefix;
|
||||
|
||||
Future<void> test_classMethod() async {
|
||||
var code = r'''
|
||||
class A {
|
||||
^
|
||||
}''';
|
||||
final snippet = await expectValidSnippet(code);
|
||||
expect(snippet.prefix, prefix);
|
||||
expect(snippet.label, label);
|
||||
expect(snippet.change.edits, hasLength(1));
|
||||
code = withoutMarkers(code);
|
||||
for (var edit in snippet.change.edits) {
|
||||
code = SourceEdit.applySequence(code, edit.edits);
|
||||
}
|
||||
expect(code, '''
|
||||
class A {
|
||||
void name(params) {
|
||||
|
||||
}
|
||||
}''');
|
||||
expect(snippet.change.selection!.file, testFile);
|
||||
expect(snippet.change.selection!.offset, 36);
|
||||
expect(snippet.change.linkedEditGroups.map((group) => group.toJson()), [
|
||||
{
|
||||
'positions': [
|
||||
{'file': testFile, 'offset': 12},
|
||||
],
|
||||
'length': 4,
|
||||
'suggestions': []
|
||||
},
|
||||
{
|
||||
'positions': [
|
||||
{'file': testFile, 'offset': 17},
|
||||
],
|
||||
'length': 4,
|
||||
'suggestions': []
|
||||
},
|
||||
{
|
||||
'positions': [
|
||||
{'file': testFile, 'offset': 22},
|
||||
],
|
||||
'length': 6,
|
||||
'suggestions': []
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> test_nested() async {
|
||||
var code = r'''
|
||||
void a() {
|
||||
^
|
||||
}''';
|
||||
final snippet = await expectValidSnippet(code);
|
||||
expect(snippet.prefix, prefix);
|
||||
expect(snippet.label, label);
|
||||
expect(snippet.change.edits, hasLength(1));
|
||||
code = withoutMarkers(code);
|
||||
for (var edit in snippet.change.edits) {
|
||||
code = SourceEdit.applySequence(code, edit.edits);
|
||||
}
|
||||
expect(code, '''
|
||||
void a() {
|
||||
void name(params) {
|
||||
|
||||
}
|
||||
}''');
|
||||
expect(snippet.change.selection!.file, testFile);
|
||||
expect(snippet.change.selection!.offset, 37);
|
||||
expect(snippet.change.linkedEditGroups.map((group) => group.toJson()), [
|
||||
{
|
||||
'positions': [
|
||||
{'file': testFile, 'offset': 13},
|
||||
],
|
||||
'length': 4,
|
||||
'suggestions': []
|
||||
},
|
||||
{
|
||||
'positions': [
|
||||
{'file': testFile, 'offset': 18},
|
||||
],
|
||||
'length': 4,
|
||||
'suggestions': []
|
||||
},
|
||||
{
|
||||
'positions': [
|
||||
{'file': testFile, 'offset': 23},
|
||||
],
|
||||
'length': 6,
|
||||
'suggestions': []
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> test_topLevel() async {
|
||||
var code = r'''
|
||||
class A {}
|
||||
|
||||
^
|
||||
|
||||
class B {}''';
|
||||
final snippet = await expectValidSnippet(code);
|
||||
expect(snippet.prefix, prefix);
|
||||
expect(snippet.label, label);
|
||||
expect(snippet.change.edits, hasLength(1));
|
||||
code = withoutMarkers(code);
|
||||
for (var edit in snippet.change.edits) {
|
||||
code = SourceEdit.applySequence(code, edit.edits);
|
||||
}
|
||||
expect(code, '''
|
||||
class A {}
|
||||
|
||||
void name(params) {
|
||||
|
||||
}
|
||||
|
||||
class B {}''');
|
||||
expect(snippet.change.selection!.file, testFile);
|
||||
expect(snippet.change.selection!.offset, 36);
|
||||
expect(snippet.change.linkedEditGroups.map((group) => group.toJson()), [
|
||||
{
|
||||
'positions': [
|
||||
{'file': testFile, 'offset': 14},
|
||||
],
|
||||
'length': 4,
|
||||
'suggestions': []
|
||||
},
|
||||
{
|
||||
'positions': [
|
||||
{'file': testFile, 'offset': 19},
|
||||
],
|
||||
'length': 4,
|
||||
'suggestions': []
|
||||
},
|
||||
{
|
||||
'positions': [
|
||||
{'file': testFile, 'offset': 24},
|
||||
],
|
||||
'length': 6,
|
||||
'suggestions': []
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class DartIfElseSnippetProducerTest extends DartSnippetProducerTest {
|
||||
@override
|
||||
|
|
Loading…
Reference in a new issue