blob: 4f3af62f9345ba7f72334075dc5c98eb69bcf951 [file] [log] [blame]
// Copyright (c) 2018, 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/domains/execution/completion.dart';
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analyzer/file_system/overlay_file_system.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../../abstract_context.dart';
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(RuntimeCompletionComputerTest);
});
}
@reflectiveTest
class RuntimeCompletionComputerTest extends AbstractContextTest {
late OverlayResourceProvider overlayResourceProvider;
late String contextFile;
late int contextOffset;
late RuntimeCompletionResult result;
void addContextFile(String content) {
contextFile = convertPath('$testPackageLibPath/context.dart');
addSource(contextFile, content);
contextOffset = content.indexOf('// context line');
expect(contextOffset, isNonNegative,
reason: "Not found '// context line'.");
}
void assertNotSuggested(String completion) {
var suggestion = getSuggest(completion);
if (suggestion != null) {
failedCompletion('unexpected $completion');
}
}
void assertSuggested(String completion, {String? returnType}) {
var suggestion = getSuggest(completion);
if (suggestion == null) {
failedCompletion('expected $completion');
}
if (returnType != null) {
expect(suggestion.returnType, returnType);
}
}
Future<void> computeCompletion(String code) async {
var codeOffset = code.indexOf('^');
expect(codeOffset, isNonNegative);
code = code.replaceAll('^', '');
var computer = RuntimeCompletionComputer(overlayResourceProvider,
driverFor(contextFile), code, codeOffset, contextFile, contextOffset);
result = await computer.compute();
}
Never failedCompletion(String message) {
var sb = StringBuffer(message);
sb.write('\n found');
result.suggestions.toList()
..sort((a, b) => a.completion.compareTo(b.completion))
..forEach((suggestion) {
sb.write('\n ${suggestion.completion} -> $suggestion');
});
fail(sb.toString());
}
CompletionSuggestion? getSuggest(String completion) {
expect(result.suggestions, isNotNull);
for (var suggestion in result.suggestions) {
if (suggestion.completion == completion) {
return suggestion;
}
}
return null;
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_class_fields() async {
addContextFile(r'''
class A {
int a;
}
class B extends A {
double b, c;
void foo() {
// context line
}
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'int');
assertSuggested('b', returnType: 'double');
assertSuggested('c', returnType: 'double');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_class_methods() async {
addContextFile(r'''
class A {
int a() => null;
}
class B extends A {
double b() => null;
void foo() {
// context line
}
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'int');
assertSuggested('b', returnType: 'double');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_inPart() async {
addSource('$testPackageLibPath/a.dart', r'''
part 'b.dart';
part 'context.dart';
int a;
''');
addSource('$testPackageLibPath/b.dart', r'''
part of 'a.dart';
double b;
''');
addContextFile(r'''
part of 'a.dart';
String c;
void f() {
// context line
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'int');
assertSuggested('b', returnType: 'double');
assertSuggested('c', returnType: 'String');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_locals_block() async {
addContextFile(r'''
class A {
int foo;
}
void contextFunction() {
var a = new A();
// context line
}
''');
await computeCompletion('a.^');
assertSuggested('foo');
// There was an issue with cleaning up
// Check that the second time it works too.
await computeCompletion('a.^');
assertSuggested('foo');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_locals_block_codeWithClosure() async {
addContextFile(r'''
void f() {
var items = <String>[];
// context line
}
''');
await computeCompletion('items.forEach((e) => e.^)');
assertSuggested('toUpperCase');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_locals_block_nested() async {
addContextFile(r'''
void f() {
var a = 0;
var b = 0.0;
{
var a = '';
// context line
}
var c = 0;
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'String');
assertSuggested('b', returnType: 'double');
// "c" is defined after the context offset, so is not visible.
assertNotSuggested('c');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_locals_for() async {
addContextFile(r'''
void f(List<int> intItems, List<double> doubleItems) {
for (var a = 0, b = 0.0; a < 5; a++) {
// context line
}
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'int');
assertSuggested('b', returnType: 'double');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_locals_forEach() async {
addContextFile(r'''
void f(List<int> intItems, List<double> doubleItems) {
for (var a in intItems) {
for (var b in doubleItems) {
// context line
}
}
}sosol
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'int');
assertSuggested('b', returnType: 'double');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_parameters_constructor() async {
addContextFile(r'''
class C {
C(int a, double b) {
// context line
}
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'int');
assertSuggested('b', returnType: 'double');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_parameters_function() async {
addContextFile(r'''
void f(int a, double b) {
// context line
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'int');
assertSuggested('b', returnType: 'double');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_parameters_function_locals() async {
addContextFile(r'''
void f(int a, int b) {
String a;
double c;
// context line
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'String');
assertSuggested('b', returnType: 'int');
assertSuggested('c', returnType: 'double');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_parameters_function_nested() async {
addContextFile(r'''
void foo(int a, double b) {
void bar(String a, bool c) {
// context line
}
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'String');
assertSuggested('b', returnType: 'double');
assertSuggested('c', returnType: 'bool');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_parameters_functionExpression() async {
addContextFile(r'''
void f(List<int> intItems, List<double> doubleItems) {
intItems.forEach((a) {
doubleItems.forEach((b) {
// context line
});
});
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'int');
assertSuggested('b', returnType: 'double');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_parameters_method() async {
addContextFile(r'''
class C {
void f(int a, double b) {
// context line
}
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'int');
assertSuggested('b', returnType: 'double');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_parameters_method_locals() async {
addContextFile(r'''
class C {
void f(int a, int b) {
String a;
double c;
// context line
}
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'String');
assertSuggested('b', returnType: 'int');
assertSuggested('c', returnType: 'double');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_syntheticImportPrefix() async {
newFile('/test/lib/a.dart', content: 'class A {}');
newFile('/test/lib/b.dart', content: 'class B {}');
addContextFile(r'''
import 'a.dart';
impoty 'b.dart';
void f() {
var a = new A();
var b = new B();
// context line
}
''');
await computeCompletion('^');
for (var suggestion in result.suggestions) {
expect(suggestion.completion, isNot(startsWith('__prefix')));
}
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_topLevelFunctions() async {
addContextFile(r'''
int a() => null;
double b() => null;
void f() {
// context line
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'int');
assertSuggested('b', returnType: 'double');
}
@FailingTest(reason: 'No support for OverlayResourceProvider')
Future<void> test_topLevelVariables() async {
addContextFile(r'''
int a;
double b;
void f() {
// context line
}
''');
await computeCompletion('^');
assertSuggested('a', returnType: 'int');
assertSuggested('b', returnType: 'double');
}
}