blob: d4689fefc0a68de651233107eadd721417973431 [file] [log] [blame]
// Copyright (c) 2014, 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 'dart:async';
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/inherited_reference_contributor.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'completion_contributor_util.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(InheritedReferenceContributorTest);
});
}
@reflectiveTest
class InheritedReferenceContributorTest extends DartCompletionContributorTest {
@override
bool get isNullExpectedReturnTypeConsideredDynamic => false;
@override
DartCompletionContributor createContributor() {
return new InheritedReferenceContributor();
}
/// Sanity check. Permutations tested in local_ref_contributor.
test_ArgDefaults_inherited_method_with_required_named() async {
addMetaPackageSource();
resolveSource('/testB.dart', '''
import 'package:meta/meta.dart';
lib libB;
class A {
bool foo(int bar, {bool boo, @required int baz}) => false;
}''');
addTestSource('''
import "testB.dart";
class B extends A {
b() => f^
}
''');
await computeSuggestions();
assertSuggestMethod('foo', 'A', 'bool',
defaultArgListString: 'bar, baz: null');
}
test_AwaitExpression_inherited() async {
// SimpleIdentifier AwaitExpression ExpressionStatement
resolveSource('/testB.dart', '''
lib libB;
class A {
Future y() async {return 0;}
}''');
addTestSource('''
import "testB.dart";
class B extends A {
Future a() async {return 0;}
foo() async {await ^}
}
''');
await computeSuggestions();
expect(replacementOffset, completionOffset);
expect(replacementLength, 0);
assertNotSuggested('a');
assertNotSuggested('foo');
assertNotSuggested('B');
assertNotSuggested('A');
assertNotSuggested('Object');
assertSuggestMethod('y', 'A', 'dynamic');
}
test_Block_inherited_imported() async {
// Block BlockFunctionBody MethodDeclaration ClassDeclaration
resolveSource('/testB.dart', '''
lib B;
class F { var f1; f2() { } get f3 => 0; set f4(fx) { } var _pf; }
class E extends F { var e1; e2() { } }
class I { int i1; i2() { } }
class M { var m1; int m2() { } }''');
addTestSource('''
import "testB.dart";
class A extends E implements I with M {a() {^}}''');
await computeSuggestions();
expect(replacementOffset, completionOffset);
expect(replacementLength, 0);
assertSuggestField('e1', null);
assertSuggestField('f1', null);
assertSuggestField('i1', 'int');
assertSuggestField('m1', null);
assertSuggestGetter('f3', null);
assertSuggestSetter('f4');
assertSuggestMethod('e2', 'E', null);
assertSuggestMethod('f2', 'F', null);
assertSuggestMethod('i2', 'I', null);
assertSuggestMethod('m2', 'M', 'int');
assertNotSuggested('==');
}
test_Block_inherited_local() async {
// Block BlockFunctionBody MethodDeclaration ClassDeclaration
addTestSource('''
class F { var f1; f2() { } get f3 => 0; set f4(fx) { } }
class E extends F { var e1; e2() { } }
class I { int i1; i2() { } }
class M { var m1; int m2() { } }
class A extends E implements I with M {a() {^}}''');
await computeSuggestions();
expect(replacementOffset, completionOffset);
expect(replacementLength, 0);
assertSuggestField('e1', null);
assertSuggestField('f1', null);
assertSuggestField('i1', 'int');
assertSuggestField('m1', null);
assertSuggestGetter('f3', null);
assertSuggestSetter('f4');
assertSuggestMethod('e2', 'E', null);
assertSuggestMethod('f2', 'F', null);
assertSuggestMethod('i2', 'I', null);
assertSuggestMethod('m2', 'M', 'int');
}
test_flutter_setState_hasPrefix() async {
var spaces_4 = ' ' * 4;
var spaces_6 = ' ' * 6;
await _check_flutter_setState(
' setSt',
'''
setState(() {
$spaces_6
$spaces_4});''',
20);
}
test_flutter_setState_longPrefix() async {
var spaces_6 = ' ' * 6;
var spaces_8 = ' ' * 8;
await _check_flutter_setState(
' setSt',
'''
setState(() {
$spaces_8
$spaces_6});''',
22);
}
test_flutter_setState_noPrefix() async {
var spaces_4 = ' ' * 4;
var spaces_6 = ' ' * 6;
await _check_flutter_setState(
' ',
'''
setState(() {
$spaces_6
$spaces_4});''',
20);
}
test_inherited() async {
resolveSource('/testB.dart', '''
lib libB;
class A2 {
int x;
int y() {return 0;}
int x2;
int y2() {return 0;}
}''');
addTestSource('''
import "testB.dart";
class A1 {
int x;
int y() {return 0;}
int x1;
int y1() {return 0;}
}
class B extends A1 with A2 {
int a;
int b() {return 0;}
foo() {^}
}
''');
await computeSuggestions();
expect(replacementOffset, completionOffset);
expect(replacementLength, 0);
assertNotSuggested('Object');
assertNotSuggested('B');
assertNotSuggested('a');
assertNotSuggested('b');
assertNotSuggested('foo');
assertNotSuggested('A');
assertSuggestField('x', 'int');
assertSuggestMethod('y', 'A1', 'int');
assertSuggestField('x1', 'int');
assertSuggestMethod('y1', 'A1', 'int');
assertSuggestField('x2', 'int');
assertSuggestMethod('y2', 'A2', 'int');
}
test_method_inClass() async {
addTestSource('''
class A {
void m(x, int y) {}
main() {^}
}
''');
await computeSuggestions();
assertNotSuggested('m');
}
test_method_inMixin() async {
addTestSource('''
mixin A {
void m(x, int y) {}
main() {^}
}
''');
await computeSuggestions();
assertNotSuggested('m');
}
test_method_inMixin_fromSuperclassConstraint() async {
addTestSource('''
class C {
void c(x, int y) {}
}
mixin M on C {
m() {^}
}
''');
await computeSuggestions();
assertSuggestMethod('c', 'C', 'void');
}
test_method_parameters_mixed_required_and_named() async {
resolveSource('/libA.dart', '''
class A {
void m(x, {int y}) {}
}
''');
addTestSource('''
import 'libA.dart';
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestMethod('m', 'A', 'void');
expect(suggestion.parameterNames, hasLength(2));
expect(suggestion.parameterNames[0], 'x');
expect(suggestion.parameterTypes[0], 'dynamic');
expect(suggestion.parameterNames[1], 'y');
expect(suggestion.parameterTypes[1], 'int');
expect(suggestion.requiredParameterCount, 1);
expect(suggestion.hasNamedParameters, true);
}
test_method_parameters_mixed_required_and_named_local() async {
addTestSource('''
class A {
void m(x, {int y}) {}
}
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestMethod('m', 'A', 'void');
expect(suggestion.parameterNames, hasLength(2));
expect(suggestion.parameterNames[0], 'x');
expect(suggestion.parameterTypes[0], 'dynamic');
expect(suggestion.parameterNames[1], 'y');
expect(suggestion.parameterTypes[1], 'int');
expect(suggestion.requiredParameterCount, 1);
expect(suggestion.hasNamedParameters, true);
}
test_method_parameters_mixed_required_and_positional() async {
resolveSource('/libA.dart', '''
class A {
void m(x, [int y]) {}
}
''');
addTestSource('''
import 'libA.dart';
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestMethod('m', 'A', 'void');
expect(suggestion.parameterNames, hasLength(2));
expect(suggestion.parameterNames[0], 'x');
expect(suggestion.parameterTypes[0], 'dynamic');
expect(suggestion.parameterNames[1], 'y');
expect(suggestion.parameterTypes[1], 'int');
expect(suggestion.requiredParameterCount, 1);
expect(suggestion.hasNamedParameters, false);
}
test_method_parameters_mixed_required_and_positional_local() async {
addTestSource('''
class A {
void m(x, [int y]) {}
}
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestMethod('m', 'A', 'void');
expect(suggestion.parameterNames, hasLength(2));
expect(suggestion.parameterNames[0], 'x');
expect(suggestion.parameterTypes[0], 'dynamic');
expect(suggestion.parameterNames[1], 'y');
expect(suggestion.parameterTypes[1], 'int');
expect(suggestion.requiredParameterCount, 1);
expect(suggestion.hasNamedParameters, false);
}
test_method_parameters_named() async {
resolveSource('/libA.dart', '''
class A {
void m({x, int y}) {}
}
''');
addTestSource('''
import 'libA.dart';
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestMethod('m', 'A', 'void');
expect(suggestion.parameterNames, hasLength(2));
expect(suggestion.parameterNames[0], 'x');
expect(suggestion.parameterTypes[0], 'dynamic');
expect(suggestion.parameterNames[1], 'y');
expect(suggestion.parameterTypes[1], 'int');
expect(suggestion.requiredParameterCount, 0);
expect(suggestion.hasNamedParameters, true);
}
test_method_parameters_named_local() async {
addTestSource('''
class A {
void m({x, int y}) {}
}
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestMethod('m', 'A', 'void');
expect(suggestion.parameterNames, hasLength(2));
expect(suggestion.parameterNames[0], 'x');
expect(suggestion.parameterTypes[0], 'dynamic');
expect(suggestion.parameterNames[1], 'y');
expect(suggestion.parameterTypes[1], 'int');
expect(suggestion.requiredParameterCount, 0);
expect(suggestion.hasNamedParameters, true);
}
test_method_parameters_none() async {
resolveSource('/libA.dart', '''
class A {
void m() {}
}
''');
addTestSource('''
import 'libA.dart';
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestMethod('m', 'A', 'void');
expect(suggestion.parameterNames, isEmpty);
expect(suggestion.parameterTypes, isEmpty);
expect(suggestion.requiredParameterCount, 0);
expect(suggestion.hasNamedParameters, false);
}
test_method_parameters_none_local() async {
addTestSource('''
class A {
void m() {}
}
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestMethod('m', 'A', 'void');
expect(suggestion.parameterNames, isEmpty);
expect(suggestion.parameterTypes, isEmpty);
expect(suggestion.requiredParameterCount, 0);
expect(suggestion.hasNamedParameters, false);
}
test_method_parameters_positional() async {
resolveSource('/libA.dart', '''
class A {
void m([x, int y]) {}
}
''');
addTestSource('''
import 'libA.dart';
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestMethod('m', 'A', 'void');
expect(suggestion.parameterNames, hasLength(2));
expect(suggestion.parameterNames[0], 'x');
expect(suggestion.parameterTypes[0], 'dynamic');
expect(suggestion.parameterNames[1], 'y');
expect(suggestion.parameterTypes[1], 'int');
expect(suggestion.requiredParameterCount, 0);
expect(suggestion.hasNamedParameters, false);
}
test_method_parameters_positional_local() async {
addTestSource('''
class A {
void m([x, int y]) {}
}
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestMethod('m', 'A', 'void');
expect(suggestion.parameterNames, hasLength(2));
expect(suggestion.parameterNames[0], 'x');
expect(suggestion.parameterTypes[0], 'dynamic');
expect(suggestion.parameterNames[1], 'y');
expect(suggestion.parameterTypes[1], 'int');
expect(suggestion.requiredParameterCount, 0);
expect(suggestion.hasNamedParameters, false);
}
test_method_parameters_required() async {
resolveSource('/libA.dart', '''
class A {
void m(x, int y) {}
}
''');
addTestSource('''
import 'libA.dart';
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestMethod('m', 'A', 'void');
expect(suggestion.parameterNames, hasLength(2));
expect(suggestion.parameterNames[0], 'x');
expect(suggestion.parameterTypes[0], 'dynamic');
expect(suggestion.parameterNames[1], 'y');
expect(suggestion.parameterTypes[1], 'int');
expect(suggestion.requiredParameterCount, 2);
expect(suggestion.hasNamedParameters, false);
}
test_mixin_ordering() async {
resolveSource('/libA.dart', '''
class B {}
class M1 {
void m() {}
}
class M2 {
void m() {}
}
''');
addTestSource('''
import 'libA.dart';
class C extends B with M1, M2 {
void f() {
^
}
}
''');
await computeSuggestions();
assertSuggestMethod('m', 'M1', 'void');
}
test_no_parameters_field() async {
resolveSource('/libA.dart', '''
class A {
int x;
}
''');
addTestSource('''
import 'libA.dart';
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestField('x', 'int');
assertHasNoParameterInfo(suggestion);
}
test_no_parameters_getter() async {
resolveSource('/libA.dart', '''
class A {
int get x => null;
}
''');
addTestSource('''
import 'libA.dart';
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestGetter('x', 'int');
assertHasNoParameterInfo(suggestion);
}
test_no_parameters_setter() async {
resolveSource('/libA.dart', '''
class A {
set x(int value) {};
}
''');
addTestSource('''
import 'libA.dart';
class B extends A {
main() {^}
}
''');
await computeSuggestions();
CompletionSuggestion suggestion = assertSuggestSetter('x');
assertHasNoParameterInfo(suggestion);
}
test_outside_class() async {
resolveSource('/testB.dart', '''
lib libB;
class A2 {
int x;
int y() {return 0;}
int x2;
int y2() {return 0;}
}''');
addTestSource('''
import "testB.dart";
class A1 {
int x;
int y() {return 0;}
int x1;
int y1() {return 0;}
}
class B extends A1 with A2 {
int a;
int b() {return 0;}
}
foo() {^}
''');
await computeSuggestions();
expect(replacementOffset, completionOffset);
expect(replacementLength, 0);
assertNotSuggested('Object');
assertNotSuggested('B');
assertNotSuggested('a');
assertNotSuggested('b');
assertNotSuggested('foo');
assertNotSuggested('A');
assertNotSuggested('x');
assertNotSuggested('y');
assertNotSuggested('x1');
assertNotSuggested('y1');
assertNotSuggested('x2');
assertNotSuggested('y2');
}
test_static_field() async {
resolveSource('/testB.dart', '''
lib libB;
class A2 {
int x;
int y() {return 0;}
int x2;
int y2() {return 0;}
}''');
addTestSource('''
import "testB.dart";
class A1 {
int x;
int y() {return 0;}
int x1;
int y1() {return 0;}
}
class B extends A1 with A2 {
int a;
int b() {return 0;}
static foo = ^
}
''');
await computeSuggestions();
expect(replacementOffset, completionOffset);
expect(replacementLength, 0);
assertNotSuggested('Object');
assertNotSuggested('B');
assertNotSuggested('a');
assertNotSuggested('b');
assertNotSuggested('foo');
assertNotSuggested('A');
assertNotSuggested('x');
assertNotSuggested('y');
assertNotSuggested('x1');
assertNotSuggested('y1');
assertNotSuggested('x2');
assertNotSuggested('y2');
}
test_static_method() async {
resolveSource('/testB.dart', '''
lib libB;
class A2 {
int x;
int y() {return 0;}
int x2;
int y2() {return 0;}
}''');
addTestSource('''
import "testB.dart";
class A1 {
int x;
int y() {return 0;}
int x1;
int y1() {return 0;}
}
class B extends A1 with A2 {
int a;
int b() {return 0;}
static foo() {^}
}
''');
await computeSuggestions();
expect(replacementOffset, completionOffset);
expect(replacementLength, 0);
assertNotSuggested('Object');
assertNotSuggested('B');
assertNotSuggested('a');
assertNotSuggested('b');
assertNotSuggested('foo');
assertNotSuggested('A');
assertNotSuggested('x');
assertNotSuggested('y');
assertNotSuggested('x1');
assertNotSuggested('y1');
assertNotSuggested('x2');
assertNotSuggested('y2');
}
Future<void> _check_flutter_setState(
String line, String completion, int selectionOffset) async {
addFlutterPackage();
addTestSource('''
import 'package:flutter/widgets.dart';
class TestWidget extends StatefulWidget {
@override
TestWidgetState createState() {
return new TestWidgetState();
}
}
class TestWidgetState extends State<TestWidget> {
@override
Widget build(BuildContext context) {
$line^
}
}
''');
await computeSuggestions();
CompletionSuggestion cs =
assertSuggest(completion, selectionOffset: selectionOffset);
expect(cs.selectionLength, 0);
// It is an invocation, but we don't need any additional info for it.
// So, all parameter information is absent.
expect(cs.parameterNames, isNull);
expect(cs.parameterTypes, isNull);
expect(cs.requiredParameterCount, isNull);
expect(cs.hasNamedParameters, isNull);
}
}