blob: b0f33b3e1a6d20751a51ff17fa6e78ddb05b5129 [file]
// Copyright (c) 2026, 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/utilities/extensions/selection.dart';
import 'package:analysis_server_plugin/src/utilities/selection.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../../abstract_single_unit.dart';
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(SelectionConstructorInClassTest);
defineReflectiveTests(SelectionConstructorInEnumTest);
defineReflectiveTests(SelectionConstructorInExtensionTypeTest);
});
}
/// This class has all of the invocation site tests because the structure of the
/// AST at the invocation site doesn't depend on the kind of declaration
/// containing the constructor declaration.
@reflectiveTest
class SelectionConstructorInClassTest extends _SelectionConstructorTestBase {
Future<void> test_declaration_primary_named_onConstructorName() async {
await resolveTestCode('''
class C.n^ame() {}
''');
_assertHasConstructor();
}
Future<void> test_declaration_primary_named_onContainerName() async {
await resolveTestCode('''
class C^.name() {}
''');
_assertHasConstructor();
}
Future<void> test_declaration_primary_named_overBoth() async {
await resolveTestCode('''
class [!C.nam!]e() {}
''');
_assertHasConstructor();
}
Future<void> test_declaration_primary_onKeyword() async {
await resolveTestCode('''
cla^ss C() {}
''');
_assertNoConstructor();
}
Future<void> test_declaration_primary_unnamed() async {
await resolveTestCode('''
class C^() {}
''');
_assertHasConstructor();
}
Future<void>
test_declaration_secondary_factory_named_onConstructorName() async {
await resolveTestCode('''
class C {
factory na^me() => C._();
C._();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_factory_named_onFactory() async {
await resolveTestCode('''
class C {
facto^ry name() => C._();
C._();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_factory_named_overBoth() async {
await resolveTestCode('''
class C {
fact[!ory na!]me() => C._();
C._();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_factory_unnamed() async {
await resolveTestCode('''
class C {
facto^ry () => C._();
C._();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_new_named_onConstructorName() async {
await resolveTestCode('''
class C {
new na^me();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_new_named_onNew() async {
await resolveTestCode('''
class C {
ne^w name();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_new_named_overBoth() async {
await resolveTestCode('''
class C {
ne[!w na!]me();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_new_unnamed() async {
await resolveTestCode('''
class C {
^new ();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_simple_named_onClassName() async {
await resolveTestCode('''
class C {
^C.name();
}
''');
_assertHasConstructor();
}
Future<void>
test_declaration_secondary_simple_named_onConstructorName() async {
await resolveTestCode('''
class C {
C.na^me();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_simple_named_overBoth() async {
await resolveTestCode('''
class C {
[!C.na!]me();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_simple_unnamed() async {
await resolveTestCode('''
class C {
^C();
}
''');
_assertHasConstructor();
}
Future<void> test_invocation_named_onArgumentList() async {
await resolveTestCode('''
class C {
C.name();
}
void f() {
C.name(^);
}
''');
_assertNoConstructor();
}
Future<void> test_invocation_named_onClassName() async {
await resolveTestCode('''
class C {
C.name();
}
void f() {
^C.name();
}
''');
_assertHasConstructor();
}
Future<void> test_invocation_named_onConstructorName() async {
await resolveTestCode('''
class C {
C.name();
}
void f() {
C.^name();
}
''');
_assertHasConstructor();
}
Future<void> test_invocation_named_overBoth() async {
await resolveTestCode('''
class C {
C.name();
}
void f() {
[!C.nam!]e();
}
''');
_assertHasConstructor();
}
Future<void> test_invocation_unnamed() async {
await resolveTestCode('''
class C() {}
void f() {
^C();
}
''');
_assertHasConstructor();
}
}
@reflectiveTest
class SelectionConstructorInEnumTest extends _SelectionConstructorTestBase {
Future<void> test_declaration_primary_named_onConstructorName() async {
await resolveTestCode('''
enum E.n^ame() { a.name() }
''');
_assertHasConstructor();
}
Future<void> test_declaration_primary_named_onContainerName() async {
await resolveTestCode('''
enum E^.name() { a.name() }
''');
_assertHasConstructor();
}
Future<void> test_declaration_primary_named_overBoth() async {
await resolveTestCode('''
enum [!E.nam!]e() { a.name() }
''');
_assertHasConstructor();
}
Future<void> test_declaration_primary_onKeyword() async {
await resolveTestCode('''
en^um E() { a }
''');
_assertNoConstructor();
}
Future<void> test_declaration_primary_unnamed() async {
await resolveTestCode('''
enum E^() { a }
''');
_assertHasConstructor();
}
Future<void>
test_declaration_secondary_factory_named_onConstructorName() async {
await resolveTestCode('''
enum E {
a._();
factory na^me() => a;
const E._();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_factory_named_onFactory() async {
await resolveTestCode('''
enum E {
a._();
facto^ry name() => a;
const E._();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_factory_named_overBoth() async {
await resolveTestCode('''
enum E {
a._();
fa[!ctory na!]me() => a;
const E._();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_factory_unnamed() async {
await resolveTestCode('''
enum E {
a._();
facto^ry () => a;
const E._();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_new_named_onConstructorName() async {
await resolveTestCode('''
enum E {
a.name();
const new na^me();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_new_named_onNew() async {
await resolveTestCode('''
enum E {
a.name();
const new^ name();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_new_named_overBoth() async {
await resolveTestCode('''
enum E {
a.name();
const ne[!w na!]me();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_new_unnamed() async {
await resolveTestCode('''
enum E {
a();
const ^new ();
}
''');
_assertHasConstructor();
}
Future<void>
test_declaration_secondary_simple_named_onConstructorName() async {
await resolveTestCode('''
enum E {
a.name();
const E.na^me();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_simple_named_onEnumName() async {
await resolveTestCode('''
enum E {
a.name();
const E^.name();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_simple_named_overBoth() async {
await resolveTestCode('''
enum E {
a.name();
const [!E.na!]me();
}
''');
_assertHasConstructor();
}
Future<void> test_declaration_secondary_simple_unnamed() async {
await resolveTestCode('''
enum E {
a();
const E^();
}
''');
_assertHasConstructor();
}
}
@reflectiveTest
class SelectionConstructorInExtensionTypeTest
extends _SelectionConstructorTestBase {
Future<void> test_declaration_primary_named_onConstructorName() async {
await resolveTestCode('''
extension type E.n^ame(int x) {}
''');
_assertHasConstructor();
}
Future<void> test_declaration_primary_named_onContainerName() async {
await resolveTestCode('''
extension type E^.name(int x) {}
''');
_assertHasConstructor();
}
Future<void> test_declaration_primary_named_overBoth() async {
await resolveTestCode('''
extension type [!E.nam!]e(int x) {}
''');
_assertHasConstructor();
}
Future<void> test_declaration_primary_onExtensionKeyword() async {
await resolveTestCode('''
exten^sion type E(int x) {}
''');
_assertNoConstructor();
}
Future<void> test_declaration_primary_onTypeKeyword() async {
await resolveTestCode('''
extension ^type E(int x) {}
''');
_assertNoConstructor();
}
Future<void> test_declaration_primary_unnamed() async {
await resolveTestCode('''
extension type E^(int x) {}
''');
_assertHasConstructor();
}
}
abstract class _SelectionConstructorTestBase extends AbstractSingleUnitTest {
void _assertHasConstructor() {
expect(_getConstructor(), isA<ConstructorElement>());
}
void _assertNoConstructor() {
expect(_getConstructor(), isNull);
}
ConstructorElement? _getConstructor() {
var range = _getSourceRange();
var selection = testAnalysisResult.unit.select(
offset: range.offset,
length: range.length,
);
if (selection == null) {
fail('No selection found');
}
return selection.constructor();
}
SourceRange _getSourceRange() {
if (parsedTestCode.positions.length == 1) {
return SourceRange(parsedTestCode.position.offset, 0);
} else if (parsedTestCode.ranges.length == 1) {
return parsedTestCode.range.sourceRange;
} else {
fail('Invalid source range in test code.');
}
}
}