blob: e590d9ab8cae251a7d9a828c3009ce3cd6188d8a [file] [log] [blame]
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/services/snippets/dart_snippet_request.dart';
import 'package:analysis_server/src/services/snippets/snippet_context.dart';
import 'package:analyzer/src/test_utilities/platform.dart';
import 'package:analyzer/src/test_utilities/test_code_format.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../abstract_single_unit.dart';
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(SnippetRequestTest);
});
}
@reflectiveTest
class SnippetRequestTest extends AbstractSingleUnitTest {
@override
void setUp() {
super.setUp();
verifyNoTestUnitErrors = false;
}
Future<void> test_annotation() async {
await testRequest(r'''
@[!depre^!]
class A {}
''', SnippetContext.inAnnotation);
}
Future<void> test_argumentName() async {
await testRequest(r'''
void({required int switch}) {
f([!sw^!]:);
}
''', SnippetContext.inName);
}
Future<void> test_block_forBody() async {
await testRequest(r'''
foo() {
for (var i = 0; i < 10; i++) {
[!^!]
}
}
''', SnippetContext.inBlock);
}
Future<void> test_class_atEnd() async {
await testRequest(r'''
class A {
foo() {}
[!^!]
}
''', SnippetContext.inClass);
}
Future<void> test_class_atEnd_partialIdentifier() async {
await testRequest(r'''
class A {
foo() {}
[!mysnip^!]
}
''', SnippetContext.inClass);
}
Future<void> test_class_atStart() async {
await testRequest(r'''
class A {
[!^!]
foo() {}
}
''', SnippetContext.inClass);
}
Future<void> test_class_atStart_partialIdentifier() async {
await testRequest(r'''
class A {
[!mysnip^!]
foo() {}
}
''', SnippetContext.inClass);
}
Future<void> test_class_betweenMembers() async {
await testRequest(r'''
class A {
foo() {}
[!^!]
bar() {}
}
''', SnippetContext.inClass);
}
Future<void> test_class_betweenMembers_partialIdentifier() async {
await testRequest(r'''
class A {
foo() {}
[!mysnip^!]
bar() {}
}
''', SnippetContext.inClass);
}
Future<void> test_class_empty() async {
await testRequest(r'''
class A {
[!^!]
}
''', SnippetContext.inClass);
}
Future<void> test_class_empty_partialIdentifier() async {
await testRequest(r'''
class A {
[!mysnip^!]
}
''', SnippetContext.inClass);
}
Future<void> test_comment_dartDoc() async {
await testRequest(r'''
/// [!^!]
class A {}
''', SnippetContext.inComment);
}
Future<void> test_comment_dartDoc_reference_member() async {
await testRequest(r'''
class A {
/// [ [!A^!] ]
foo() {}
}
''', SnippetContext.inComment);
}
Future<void> test_comment_dartDoc_reference_topLevel() async {
await testRequest(r'''
/// [ [!A^!] ]
class A {}
''', SnippetContext.inComment);
}
Future<void> test_comment_multiline_member() async {
await testRequest(r'''
class A {
/*
* [!^!]
*/
foo() {}
}
''', SnippetContext.inComment);
}
Future<void> test_comment_multiline_topLevel() async {
await testRequest(r'''
/*
* [!^!]
*/
class A {}
''', SnippetContext.inComment);
}
Future<void> test_comment_singleLine_member() async {
await testRequest(r'''
class A {
// [!^!]
foo () {}
}
''', SnippetContext.inComment);
}
Future<void> test_comment_singleLine_topLevel() async {
await testRequest(r'''
// [!^!]
class A {}
''', SnippetContext.inComment);
}
Future<void> test_enum() async {
await testRequest(r'''
enum A {
[!^!]
}
''', SnippetContext.inClass);
}
Future<void> test_expression_constructor() async {
await testRequest(r'''
final a = new [!^!]
''', SnippetContext.inConstructorInvocation);
}
Future<void> test_expression_constructorName() async {
await testRequest(r'''
class A {
A.foo();
}
final a = new A.[!fo^!]
''', SnippetContext.inConstructorInvocation);
}
Future<void> test_expression_functionCall() async {
await testRequest(r'''
foo() {
print([!^!]
}
''', SnippetContext.inExpression);
}
Future<void> test_extension() async {
await testRequest(r'''
extension on Object {
[!^!]
}
''', SnippetContext.inClass);
}
Future<void> test_function_atEnd() async {
await testRequest(r'''
foo() {
var a = 1;
[!^!]
}
''', SnippetContext.inBlock);
}
Future<void> test_function_atEnd_partialIdentifier() async {
await testRequest(r'''
foo() {
var a = 1;
[!mysnip^!]
}
''', SnippetContext.inBlock);
}
Future<void> test_function_atStart() async {
await testRequest(r'''
foo() {
[!^!]
var a = 1;
}
''', SnippetContext.inBlock);
}
Future<void> test_function_atStart_partialIdentifier() async {
await testRequest(r'''
foo() {
[!mysnip^!]
var a = 1;
}
''', SnippetContext.inBlock);
}
Future<void> test_function_betweenStatements() async {
await testRequest(r'''
foo() {
var a = 1;
[!^!]
var b = 1;
}
''', SnippetContext.inBlock);
}
Future<void> test_function_betweenStatements_partialIdentifier() async {
await testRequest(r'''
foo() {
var a = 1;
[!mysnip^!]
var b = 1;
}
''', SnippetContext.inBlock);
}
Future<void> test_function_empty() async {
await testRequest(r'''
foo() {
[!^!]
}
''', SnippetContext.inBlock);
}
Future<void> test_function_empty_partialIdentifier() async {
await testRequest(r'''
foo() {
[!mysnip^!]
}
''', SnippetContext.inBlock);
}
Future<void> test_importPrefixMember() async {
await testRequest(r'''
import 'dart:async' as a;
void f() {
a.[!^!]
}
''', SnippetContext.inQualifiedMemberAccess);
}
Future<void> test_initializingFormal() async {
await testRequest(r'''
class A {
int a;
A(this.[!f^!]);
}
''', SnippetContext.inQualifiedMemberAccess);
}
Future<void> test_method_atEnd() async {
await testRequest(r'''
class A {
foo() {
var a = 1;
[!^!]
}
}
''', SnippetContext.inBlock);
}
Future<void> test_method_atEnd_partialIdentifier() async {
await testRequest(r'''
class A {
foo() {
var a = 1;
[!mysnip^!]
}
}
''', SnippetContext.inBlock);
}
Future<void> test_method_atStart() async {
await testRequest(r'''
class A {
foo() {
[!^!]
var a = 1;
}
}
''', SnippetContext.inBlock);
}
Future<void> test_method_atStart_partialIdentifier() async {
await testRequest(r'''
class A {
foo() {
[!mysnip^!]
var a = 1;
}
}
''', SnippetContext.inBlock);
}
Future<void> test_method_betweenStatements() async {
await testRequest(r'''
class A {
foo() {
var a = 1;
[!^!]
var b = 1;
}
}
''', SnippetContext.inBlock);
}
Future<void> test_method_betweenStatements_partialIdentifier() async {
await testRequest(r'''
class A {
foo() {
var a = 1;
[!mysnip^!]
var b = 1;
}
}
''', SnippetContext.inBlock);
}
Future<void> test_method_call() async {
await testRequest(r'''
class A {
void foo() {
this.[!^!]
}
}
''', SnippetContext.inQualifiedMemberAccess);
}
Future<void> test_method_call_partialIdentifier() async {
await testRequest(r'''
class A {
void foo() {
this.[!fo^!]
}
}
''', SnippetContext.inQualifiedMemberAccess);
}
Future<void> test_method_declaration() async {
await testRequest(r'''
class A {
void [!foo^!]
}
''', SnippetContext.inIdentifierDeclaration);
}
Future<void> test_method_empty() async {
await testRequest(r'''
class A {
foo() {
[!^!]
}
}
''', SnippetContext.inBlock);
}
Future<void> test_method_empty_partialIdentifier() async {
await testRequest(r'''
class A {
foo() {
[!mysnip^!]
}
}
''', SnippetContext.inBlock);
}
Future<void> test_mixin() async {
await testRequest(r'''
mixin A {
[!^!]
}
''', SnippetContext.inClass);
}
Future<void> test_pattern_switch() async {
await testRequest(r'''
f(String a) => switch (a) {
[!^!]
};
''', SnippetContext.inPattern);
}
Future<void> test_pattern_switch_partialIdentifier() async {
await testRequest(r'''
f(String a) => switch (a) {
[!sw^!]
};
''', SnippetContext.inPattern);
}
Future<void> test_prefixedEnumMember() async {
await testRequest(r'''
import 'test.dart' as self;
enum MyEnum {
one,
two,
}
void f() {
self.MyEnum.[!^!]
}
''', SnippetContext.inQualifiedMemberAccess);
}
Future<void> test_return_expression() async {
await testRequest(r'''
int f() {
return [!sw^!]
}
''', SnippetContext.inExpression);
}
Future<void> test_return_expression_empty() async {
await testRequest(r'''
int f() {
return [!^!]
}
''', SnippetContext.inExpression);
}
Future<void> test_statement_forCondition() async {
await testRequest(r'''
foo() {
for (var i = [!^!]
}
''', SnippetContext.inExpression);
}
Future<void> test_statement_forCondition_partialIdentifier() async {
await testRequest(r'''
foo() {
for (var i = [!a^!]
}
''', SnippetContext.inExpression);
}
Future<void> test_string() async {
await testRequest(r'''
const a = '[!^!]';
''', SnippetContext.inString);
}
Future<void> test_string_raw() async {
await testRequest(r'''
const a = r'[!^!]';
''', SnippetContext.inString);
}
Future<void> test_string_unterminated() async {
await testRequest(r'''
const a = r'[!^!]
''', SnippetContext.inString);
}
Future<void> test_topLevel_atEnd() async {
await testRequest(r'''
class A {}
[!^!]
''', SnippetContext.atTopLevel);
}
Future<void> test_topLevel_atEnd_partialIdentifier() async {
await testRequest(r'''
class A {}
[!mysnip^!]
''', SnippetContext.atTopLevel);
}
Future<void> test_topLevel_atStart() async {
await testRequest(r'''
[!^!]
class A {}
''', SnippetContext.atTopLevel);
}
Future<void> test_topLevel_atStart_partialIdentifier() async {
await testRequest(r'''
[!mysnip^!]
class A {}
''', SnippetContext.atTopLevel);
}
Future<void> test_topLevel_betweenClasses() async {
await testRequest(r'''
class A {}
[!^!]
class B {}
''', SnippetContext.atTopLevel);
}
Future<void> test_topLevel_betweenClasses_partialIdentifier() async {
await testRequest(r'''
class A {}
[!mysnip^!]
class B {}
''', SnippetContext.atTopLevel);
}
Future<void> test_topLevel_empty() async {
await testRequest('[!^!]', SnippetContext.atTopLevel);
}
Future<void> test_topLevel_empty_partialIdentifier() async {
await testRequest('[!mysnip^!]', SnippetContext.atTopLevel);
}
Future<void> test_variable_value_partialIdentifier() async {
await testRequest(r'''
foo() {
var a = [!a^!]
}
''', SnippetContext.inExpression);
}
Future<void> test_variableDeclaration() async {
await testRequest(r'''
foo() {
var [!^!]
}
''', SnippetContext.inIdentifierDeclaration);
}
Future<void> test_variableDeclaration_partialIdentifier() async {
await testRequest(r'''
foo() {
var [!a^!]
}
''', SnippetContext.inIdentifierDeclaration);
}
Future<void> test_variableDeclaration_value() async {
await testRequest(r'''
foo() {
var a = [!^!]
}
''', SnippetContext.inExpression);
}
/// Checks that [content] produces a context of [expectedContext] where the
/// character '^' in [content] represents the supplied offset and the range
/// surrounded `[!` by brackets `!]` is the expected replacement range.
///
/// `^`, `[!` and `!]` will be removed from the code before resolving.
Future<void> testRequest(
String content,
SnippetContext expectedContext,
) async {
var code = TestCode.parse(normalizeNewlinesForPlatform(content));
var offset = code.position.offset;
var expectedReplacementRange = code.range.sourceRange;
await resolveTestCode(code.code);
var request = DartSnippetRequest(unit: testAnalysisResult, offset: offset);
expect(request.filePath, testFile.path);
expect(request.offset, offset);
expect(request.context, expectedContext);
expect(request.replacementRange, expectedReplacementRange);
}
}