blob: e70da8899d5bea994b3585cea158060269d509ff [file] [log] [blame]
// Copyright (c) 2025, 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:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../src/dart/resolution/context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(FragmentOffsetTest);
});
}
@reflectiveTest
class FragmentOffsetTest extends PubPackageResolutionTest {
void checkOffset<F extends Fragment>(
AstNode declaration,
Fragment fragment,
int expectedOffset,
) {
var offset = checkOffsetInRange<F>(declaration, fragment);
expect(offset, expectedOffset);
}
/// Checks that the offset is in the range of the declaration, but doesn't
/// check the precise offset.
///
/// Used in the case of error recovery, where the precise offset is
/// unspecified.
int checkOffsetInRange<F extends Fragment>(
AstNode declaration,
Fragment fragment,
) {
expect(fragment, isA<F>());
var offset = fragment.offset;
expect(offset, greaterThanOrEqualTo(declaration.offset));
expect(offset, lessThanOrEqualTo(declaration.end));
return offset;
}
test_bindPatternVariableFragment() async {
await assertNoErrorsInCode(r'''
void f() {
// ignore: unused_local_variable
var (int i,) = (0,);
}
''');
var declaredVariablePattern = findNode.declaredVariablePattern('int i');
checkOffset<BindPatternVariableFragment>(
declaredVariablePattern,
declaredVariablePattern.declaredFragment!,
declaredVariablePattern.name.offset,
);
}
test_classFragment() async {
await assertNoErrorsInCode(r'''
class C {}
''');
var classDeclaration = findNode.classDeclaration('C');
checkOffset<ClassFragment>(
classDeclaration,
classDeclaration.declaredFragment!,
classDeclaration.name.offset,
);
}
test_classFragment_classTypeAlias() async {
await assertNoErrorsInCode(r'''
mixin M {}
class C = Object with M;
''');
var classTypeAlias = findNode.classTypeAlias('C');
checkOffset<ClassFragment>(
classTypeAlias,
classTypeAlias.declaredFragment!,
classTypeAlias.name.offset,
);
}
test_classFragment_classTypeAlias_missingName() async {
await assertErrorsInCode(
r'''
mixin M {}
class = Object with M;
''',
[error(ParserErrorCode.MISSING_IDENTIFIER, 17, 1)],
);
var classTypeAlias = findNode.classTypeAlias('Object with M');
checkOffsetInRange<ClassFragment>(
classTypeAlias,
classTypeAlias.declaredFragment!,
);
}
test_classFragment_missingName() async {
await assertErrorsInCode(
r'''
library; // Ensures that the class declaration isn't at offset 0
class {}
''',
[error(ParserErrorCode.MISSING_IDENTIFIER, 72, 1)],
);
var classDeclaration = findNode.classDeclaration('class {}');
checkOffsetInRange<ClassFragment>(
classDeclaration,
classDeclaration.declaredFragment!,
);
}
test_constructorFragment_implicit() async {
await assertNoErrorsInCode(r'''
class C {}
''');
var classDeclaration = findNode.classDeclaration('C');
checkOffset<ConstructorFragment>(
classDeclaration,
classDeclaration
.declaredFragment!
.element
.unnamedConstructor2!
.firstFragment,
classDeclaration.name.offset,
);
}
test_constructorFragment_missingName() async {
await assertErrorsInCode(
r'''
class C {
C.();
}
''',
[error(ParserErrorCode.MISSING_IDENTIFIER, 14, 1)],
);
var constructorDeclaration = findNode.constructor('C.()');
checkOffsetInRange<ConstructorFragment>(
constructorDeclaration,
constructorDeclaration.declaredFragment!,
);
}
test_constructorFragment_named() async {
await assertNoErrorsInCode(r'''
class C {
C.foo();
}
''');
var constructorDeclaration = findNode.constructor('foo');
checkOffset<ConstructorFragment>(
constructorDeclaration,
constructorDeclaration.declaredFragment!,
constructorDeclaration.name!.offset,
);
}
test_constructorFragment_unnamed() async {
await assertNoErrorsInCode(r'''
class C {
C();
}
''');
var constructorDeclaration = findNode.constructor('C()');
checkOffset<ConstructorFragment>(
constructorDeclaration,
constructorDeclaration.declaredFragment!,
constructorDeclaration.returnType.offset,
);
}
test_dynamicFragment() async {
await assertNoErrorsInCode(r'''
dynamic d;
''');
var namedType =
findNode.topLevelVariableDeclaration('dynamic d').variables.type
as NamedType;
expect(namedType.element2!.kind, ElementKind.DYNAMIC);
// `dynamic` isn't defined in the source code anywhere, so its offset is 0.
expect(namedType.element2!.firstFragment.offset, 0);
}
test_enumFragment() async {
await assertNoErrorsInCode(r'''
enum E { e1 }
''');
var enumDeclaration = findNode.enumDeclaration('E');
checkOffset<EnumFragment>(
enumDeclaration,
enumDeclaration.declaredFragment!,
enumDeclaration.name.offset,
);
}
test_enumFragment_missingName() async {
await assertErrorsInCode(
r'''
library; // Ensures that the enum declaration isn't at offset 0
enum { e1 }
''',
[error(ParserErrorCode.MISSING_IDENTIFIER, 70, 1)],
);
var enumDeclaration = findNode.enumDeclaration('enum { e1 }');
checkOffsetInRange<EnumFragment>(
enumDeclaration,
enumDeclaration.declaredFragment!,
);
}
test_extensionFragment_named() async {
await assertNoErrorsInCode(r'''
library; // Ensures that the extension declaration isn't at offset 0
/// Documentation comment
extension E on int {}
''');
var extensionDeclaration = findNode.extensionDeclaration('on int');
checkOffset<ExtensionFragment>(
extensionDeclaration,
extensionDeclaration.declaredFragment!,
extensionDeclaration.name!.offset,
);
}
test_extensionFragment_unnamed() async {
await assertNoErrorsInCode(r'''
extension on int {}
''');
var extensionDeclaration = findNode.extensionDeclaration('on int');
checkOffset<ExtensionFragment>(
extensionDeclaration,
extensionDeclaration.declaredFragment!,
extensionDeclaration.extensionKeyword.offset,
);
}
test_extensionTypeFragment() async {
await assertNoErrorsInCode(r'''
extension type E(int i) {}
''');
var extensionTypeDeclaration = findNode.extensionTypeDeclaration('E');
checkOffset<ExtensionTypeFragment>(
extensionTypeDeclaration,
extensionTypeDeclaration.declaredFragment!,
extensionTypeDeclaration.name.offset,
);
}
test_extensionTypeFragment_missingName() async {
await assertErrorsInCode(
r'''
library; // Ensures that the extension type declaration isn't at offset 0
extension type(int i) {}
''',
[error(ParserErrorCode.MISSING_IDENTIFIER, 89, 1)],
);
var extensionTypeDeclaration = findNode.extensionTypeDeclaration(
'extension type(int i)',
);
checkOffsetInRange<ExtensionTypeFragment>(
extensionTypeDeclaration,
extensionTypeDeclaration.declaredFragment!,
);
}
test_fieldFormalParameterFragment() async {
await assertNoErrorsInCode(r'''
class C {
final int i;
C(this.i);
}
''');
var parameter = findNode.fieldFormalParameter('this.i');
checkOffset<FieldFormalParameterFragment>(
parameter,
parameter.declaredFragment!,
parameter.name.offset,
);
}
test_fieldFormalParameterFragment_missingName() async {
await assertErrorsInCode(
r'''
class C {
int? x;
C(this.);
}
''',
[
error(
CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD,
24,
5,
),
error(ParserErrorCode.MISSING_IDENTIFIER, 29, 1),
],
);
var parameter = findNode.fieldFormalParameter('this.');
checkOffsetInRange<FieldFormalParameterFragment>(
parameter,
parameter.declaredFragment!,
);
}
test_fieldFormalParameterFragment_withDefaultValue() async {
await assertNoErrorsInCode(r'''
class C {
final int i;
C({this.i = 0});
}
''');
var parameter = findNode.fieldFormalParameter('this.i');
checkOffset<FieldFormalParameterFragment>(
parameter,
parameter.declaredFragment!,
parameter.name.offset,
);
}
test_fieldFragment() async {
await assertNoErrorsInCode(r'''
class C {
int? x;
}
''');
var fieldDeclaration = findNode.fieldDeclaration('x').fields.variables[0];
checkOffset<FieldFragment>(
fieldDeclaration,
fieldDeclaration.declaredFragment!,
fieldDeclaration.name.offset,
);
}
test_fieldFragment_const() async {
await assertNoErrorsInCode(r'''
class C {
static const int x = 0;
}
''');
var fieldDeclaration = findNode.fieldDeclaration('x').fields.variables[0];
checkOffset<FieldFragment>(
fieldDeclaration,
fieldDeclaration.declaredFragment!,
fieldDeclaration.name.offset,
);
}
test_fieldFragment_enum_constant() async {
await assertNoErrorsInCode(r'''
enum E { e1 }
''');
var enumConstantDeclaration = findNode.enumConstantDeclaration('e1');
checkOffset<FieldFragment>(
enumConstantDeclaration,
enumConstantDeclaration.declaredFragment!,
enumConstantDeclaration.name.offset,
);
}
test_fieldFragment_enum_values() async {
await assertNoErrorsInCode(r'''
enum E { e1 }
''');
var enumDeclaration = findNode.enumDeclaration('E');
checkOffset<FieldFragment>(
enumDeclaration,
enumDeclaration.declaredFragment!.element
.getField('values')!
.firstFragment,
enumDeclaration.name.offset,
);
}
test_fieldFragment_extensionTypeRepresentationField() async {
await assertNoErrorsInCode(r'''
extension type E(int i) {}
''');
var representationDeclaration =
findNode.extensionTypeDeclaration('int i').representation;
checkOffset<FieldFragment>(
representationDeclaration,
representationDeclaration.fieldFragment!,
representationDeclaration.fieldName.offset,
);
}
test_formalParameterFragment() async {
await assertNoErrorsInCode(r'''
void f(int x) {}
''');
var parameter = findNode.simpleFormalParameter('x');
checkOffset<FormalParameterFragment>(
parameter,
parameter.declaredFragment!,
parameter.name!.offset,
);
}
test_formalParameterFragment_missingName() async {
await assertErrorsInCode(
r'''
void f((int x)) {}
''',
[error(ParserErrorCode.MISSING_IDENTIFIER, 7, 1)],
);
var function = findNode.functionDeclaration('f(');
var parameter =
function.functionExpression.parameters!.parameters[0]
as FunctionTypedFormalParameter;
expect(parameter.name.isSynthetic, true);
checkOffsetInRange<FormalParameterFragment>(
parameter,
parameter.declaredFragment!,
);
}
test_formalParameterFragment_missingName2() async {
await assertErrorsInCode(
r'''
void f(void (int x)) {}
''',
[error(ParserErrorCode.MISSING_IDENTIFIER, 12, 1)],
);
var function = findNode.functionDeclaration('f(');
var parameter =
function.functionExpression.parameters!.parameters[0]
as FunctionTypedFormalParameter;
expect(parameter.name.isSynthetic, true);
checkOffsetInRange<FormalParameterFragment>(
parameter,
parameter.declaredFragment!,
);
}
test_formalParameterFragment_ofImplicitSetter_member_implicit() async {
await assertNoErrorsInCode(r'''
class C {
int? x;
}
''');
var fieldDeclaration = findNode.fieldDeclaration('x').fields.variables[0];
checkOffset<FormalParameterFragment>(
fieldDeclaration,
(fieldDeclaration.declaredFragment as FieldFragment)
.element
.setter2!
.formalParameters
.single
.firstFragment,
fieldDeclaration.name.offset,
);
}
test_formalParameterFragment_ofImplicitSetter_topLevel_implicit() async {
await assertNoErrorsInCode(r'''
int? x;
''');
var topLevelVariableDeclaration =
findNode.topLevelVariableDeclaration('x').variables.variables[0];
checkOffset<FormalParameterFragment>(
topLevelVariableDeclaration,
(topLevelVariableDeclaration.declaredFragment as TopLevelVariableFragment)
.element
.setter2!
.formalParameters
.single
.firstFragment,
topLevelVariableDeclaration.name.offset,
);
}
test_formalParameterFragment_withDefaultValue() async {
await assertNoErrorsInCode(r'''
void f({int x = 0}) {}
''');
var parameter = findNode.simpleFormalParameter('x');
checkOffset<FormalParameterFragment>(
parameter,
parameter.declaredFragment!,
parameter.name!.offset,
);
}
test_genericFunctionTypeFragment() async {
await assertNoErrorsInCode(r'''
library; // Ensures that the generic function type isn't at offset 0
void Function(int x)? f;
''');
var genericFunctionType = findNode.genericFunctionType(
'void Function(int x)?',
);
checkOffset<GenericFunctionTypeFragment>(
genericFunctionType,
genericFunctionType.declaredFragment!,
genericFunctionType.offset,
);
}
test_getterFragment_member() async {
await assertNoErrorsInCode(r'''
class C {
int get foo => 0;
}
''');
var getterDeclaration = findNode.methodDeclaration('foo');
checkOffset<GetterFragment>(
getterDeclaration,
getterDeclaration.declaredFragment!,
getterDeclaration.name.offset,
);
}
test_getterFragment_member_implicit() async {
await assertNoErrorsInCode(r'''
class C {
int? x;
}
''');
var fieldDeclaration = findNode.fieldDeclaration('x').fields.variables[0];
checkOffset<GetterFragment>(
fieldDeclaration,
(fieldDeclaration.declaredFragment as FieldFragment)
.element
.getter2!
.firstFragment,
fieldDeclaration.name.offset,
);
}
test_getterFragment_topLevel() async {
await assertNoErrorsInCode(r'''
int get foo => 0;
''');
var getterDeclaration = findNode.functionDeclaration('foo');
checkOffset<GetterFragment>(
getterDeclaration,
getterDeclaration.declaredFragment!,
getterDeclaration.name.offset,
);
}
test_getterFragment_topLevel_implicit() async {
await assertNoErrorsInCode(r'''
int? x;
''');
var topLevelVariableDeclaration =
findNode.topLevelVariableDeclaration('x').variables.variables[0];
checkOffset<GetterFragment>(
topLevelVariableDeclaration,
(topLevelVariableDeclaration.declaredFragment as TopLevelVariableFragment)
.element
.getter2!
.firstFragment,
topLevelVariableDeclaration.name.offset,
);
}
test_joinPatternVariableFragment() async {
await assertNoErrorsInCode(r'''
void f() {
switch ((0,) as dynamic) {
// ignore: unused_local_variable
case (var i,) || (:var i,):
break;
}
}
''');
var firstDeclaredVariablePattern = findNode.declaredVariablePattern(
'var i,) ||',
);
checkOffset<JoinPatternVariableFragment>(
firstDeclaredVariablePattern,
firstDeclaredVariablePattern.declaredFragment!.join2!,
firstDeclaredVariablePattern.name.offset,
);
}
test_labelFragment() async {
await assertNoErrorsInCode(r'''
void f() {
// ignore: unused_label
L: while(true) {}
}
''');
var label = findNode.label('L');
checkOffset<LabelFragment>(
label,
label.declaredFragment!,
label.label.offset,
);
}
test_libraryFragment_first_named() async {
await assertNoErrorsInCode(r'''
// Comment to ensure that the library declaration isn't at offset 0
library L;
class C {}
''');
var unit = findNode.unit;
checkOffset<LibraryFragment>(
unit,
unit.declaredFragment!,
findNode.library('L').name2!.offset,
);
}
test_libraryFragment_first_unnamed_withLibraryDeclaration() async {
await assertNoErrorsInCode(r'''
// Comment to ensure that the library declaration isn't at offset 0
library;
class C {}
''');
var unit = findNode.unit;
checkOffset<LibraryFragment>(unit, unit.declaredFragment!, 0);
}
test_libraryFragment_first_unnamed_withoutLibraryDeclaration() async {
await assertNoErrorsInCode(r'''
// Comment to ensure that the class declaration isn't at offset 0
class C {}
''');
var unit = findNode.unit;
checkOffset<LibraryFragment>(unit, unit.declaredFragment!, 0);
}
test_libraryFragment_notFirst_named() async {
newFile('$testPackageLibPath/lib.dart', r'''
library L;
part 'part.dart';
''');
newFile('$testPackageLibPath/part.dart', r'''
// Comment to ensure that the "part of" declaration isn't at offset 0
part of 'lib.dart';
class C {}
''');
await resolveFile2(getFile('$testPackageLibPath/part.dart'));
assertErrorsInResolvedUnit(result, const []);
var unit = findNode.unit;
checkOffset<LibraryFragment>(unit, unit.declaredFragment!, 0);
}
test_libraryFragment_notFirst_unnamed() async {
newFile('$testPackageLibPath/lib.dart', r'''
part 'part.dart';
''');
newFile('$testPackageLibPath/part.dart', r'''
// Comment to ensure that the "part of" declaration isn't at offset 0
part of 'lib.dart';
class C {}
''');
await resolveFile2(getFile('$testPackageLibPath/part.dart'));
assertErrorsInResolvedUnit(result, const []);
var unit = findNode.unit;
checkOffset<LibraryFragment>(unit, unit.declaredFragment!, 0);
}
test_local_variable_fragment() async {
await assertNoErrorsInCode(r'''
void f() {
// ignore: unused_local_variable
int i = 0;
}
''');
var localVariable = findNode.variableDeclaration('i = 0');
checkOffset<LocalVariableFragment>(
localVariable,
localVariable.declaredFragment!,
localVariable.name.offset,
);
}
test_local_variable_fragment_const() async {
await assertNoErrorsInCode(r'''
void f() {
// ignore: unused_local_variable
const int i = 0;
}
''');
var localVariable = findNode.variableDeclaration('i = 0');
checkOffset<LocalVariableFragment>(
localVariable,
localVariable.declaredFragment!,
localVariable.name.offset,
);
}
test_localFunctionFragment_named() async {
await assertNoErrorsInCode(r'''
void f() {
// ignore: unused_element
void g() {}
}
''');
var localFunction =
findNode.functionDeclarationStatement('g()').functionDeclaration;
checkOffset<LocalFunctionFragment>(
localFunction,
localFunction.declaredFragment!,
localFunction.name.offset,
);
}
test_localFunctionFragment_unnamed() async {
await assertNoErrorsInCode(r'''
dynamic f() {
return () {};
}
''');
var localFunction = findNode.functionExpression('() {}');
checkOffset<LocalFunctionFragment>(
localFunction,
localFunction.declaredFragment!,
localFunction.parameters!.leftParenthesis.offset,
);
}
test_methodFragment() async {
await assertNoErrorsInCode(r'''
class C {
void foo() {}
}
''');
var methodDeclaration = findNode.methodDeclaration('foo');
checkOffset<MethodFragment>(
methodDeclaration,
methodDeclaration.declaredFragment!,
methodDeclaration.name.offset,
);
}
test_mixinFragment() async {
await assertNoErrorsInCode(r'''
mixin M {}
''');
var mixinDeclaration = findNode.mixinDeclaration('M');
checkOffset<MixinFragment>(
mixinDeclaration,
mixinDeclaration.declaredFragment!,
mixinDeclaration.name.offset,
);
}
test_mixinFragment_missingName() async {
await assertErrorsInCode(
r'''
library; // Ensures that the mixin declaration isn't at offset 0
mixin {}
''',
[error(ParserErrorCode.MISSING_IDENTIFIER, 72, 1)],
);
var mixinDeclaration = findNode.mixinDeclaration('mixin {}');
checkOffsetInRange<MixinFragment>(
mixinDeclaration,
mixinDeclaration.declaredFragment!,
);
}
test_neverFragment() async {
await assertNoErrorsInCode(r'''
Never n = throw '';
''');
var namedType =
findNode.topLevelVariableDeclaration('Never n').variables.type
as NamedType;
expect(namedType.element2!.kind, ElementKind.NEVER);
// `Never` isn't defined in the source code anywhere, so its offset is 0.
expect(namedType.element2!.firstFragment.offset, 0);
}
test_prefixFragment() async {
await assertNoErrorsInCode(r'''
// ignore: unused_import
import 'dart:async' as a;
''');
var importDirective = findNode.import('as a');
checkOffset<PrefixFragment>(
importDirective,
importDirective.libraryImport!.prefix2!,
importDirective.prefix!.offset,
);
}
test_prefixFragment_inMultipleImports() async {
await assertNoErrorsInCode(r'''
// ignore: unused_import
import 'dart:async' as a; // first
// ignore: unused_import
import 'dart:math' as a; // second
''');
var firstImportDirective = findNode.import('as a; // first');
checkOffset<PrefixFragment>(
firstImportDirective,
firstImportDirective.libraryImport!.prefix2!,
firstImportDirective.prefix!.offset,
);
}
test_prefixFragment_missingName() async {
await assertErrorsInCode(
r'''
// ignore: unused_import
import 'dart:async' as;
''',
[error(ParserErrorCode.MISSING_IDENTIFIER, 47, 1)],
);
var importDirective = findNode.import('as;');
checkOffsetInRange<PrefixFragment>(
importDirective,
importDirective.libraryImport!.prefix2!,
);
}
test_setterFragment_member() async {
await assertNoErrorsInCode(r'''
class C {
set foo(int value) {}
}
''');
var setterDeclaration = findNode.methodDeclaration('foo');
checkOffset<SetterFragment>(
setterDeclaration,
setterDeclaration.declaredFragment!,
setterDeclaration.name.offset,
);
}
test_setterFragment_member_implicit() async {
await assertNoErrorsInCode(r'''
class C {
int? x;
}
''');
var fieldDeclaration = findNode.fieldDeclaration('x').fields.variables[0];
checkOffset<SetterFragment>(
fieldDeclaration,
(fieldDeclaration.declaredFragment as FieldFragment)
.element
.setter2!
.firstFragment,
fieldDeclaration.name.offset,
);
}
test_setterFragment_topLevel() async {
await assertNoErrorsInCode(r'''
set foo(int value) {}
''');
var setterDeclaration = findNode.functionDeclaration('foo');
checkOffset<SetterFragment>(
setterDeclaration,
setterDeclaration.declaredFragment!,
setterDeclaration.name.offset,
);
}
test_setterFragment_topLevel_implicit() async {
await assertNoErrorsInCode(r'''
int? x;
''');
var topLevelVariableDeclaration =
findNode.topLevelVariableDeclaration('x').variables.variables[0];
checkOffset<SetterFragment>(
topLevelVariableDeclaration,
(topLevelVariableDeclaration.declaredFragment as TopLevelVariableFragment)
.element
.setter2!
.firstFragment,
topLevelVariableDeclaration.name.offset,
);
}
test_superFormalParameterFragment() async {
await assertNoErrorsInCode(r'''
class B {
B(int i);
}
class C extends B {
C(super.i);
}
''');
var parameter = findNode.superFormalParameter('super.i');
checkOffset<SuperFormalParameterFragment>(
parameter,
parameter.declaredFragment!,
parameter.name.offset,
);
}
test_superFormalParameterFragment_missingName() async {
await assertErrorsInCode(
r'''
class B {
B([int? i]);
}
class C extends B {
C(super.);
}
''',
[error(ParserErrorCode.MISSING_IDENTIFIER, 58, 1)],
);
var parameter = findNode.superFormalParameter('super.');
checkOffsetInRange<SuperFormalParameterFragment>(
parameter,
parameter.declaredFragment!,
);
}
test_superFormalParameterFragment_withDefaultValue() async {
await assertNoErrorsInCode(r'''
class B {
B({int? i});
}
class C extends B {
C({super.i = 0});
}
''');
var parameter = findNode.superFormalParameter('super.i');
checkOffset<SuperFormalParameterFragment>(
parameter,
parameter.declaredFragment!,
parameter.name.offset,
);
}
test_topLevelFunctionFragment() async {
await assertNoErrorsInCode(r'''
void foo() {}
''');
var topLevelFunctionDeclaration = findNode.functionDeclaration('foo');
checkOffset<TopLevelFunctionFragment>(
topLevelFunctionDeclaration,
topLevelFunctionDeclaration.declaredFragment!,
topLevelFunctionDeclaration.name.offset,
);
}
test_topLevelVariableFragment() async {
await assertNoErrorsInCode(r'''
int? x;
''');
var topLevelVariableDeclaration =
findNode.topLevelVariableDeclaration('x').variables.variables[0];
checkOffset<TopLevelVariableFragment>(
topLevelVariableDeclaration,
topLevelVariableDeclaration.declaredFragment!,
topLevelVariableDeclaration.name.offset,
);
}
test_topLevelVariableFragment_const() async {
await assertNoErrorsInCode(r'''
const int x = 0;
''');
var topLevelVariableDeclaration =
findNode.topLevelVariableDeclaration('x').variables.variables[0];
checkOffset<TopLevelVariableFragment>(
topLevelVariableDeclaration,
topLevelVariableDeclaration.declaredFragment!,
topLevelVariableDeclaration.name.offset,
);
}
test_typeAliasFragment_functionTypeAlias() async {
await assertNoErrorsInCode(r'''
typedef void F();
''');
var functionTypeAlias = findNode.functionTypeAlias('F');
checkOffset<TypeAliasFragment>(
functionTypeAlias,
functionTypeAlias.declaredFragment!,
functionTypeAlias.name.offset,
);
}
test_typeAliasFragment_functionTypeAlias_missingName() async {
await assertErrorsInCode(
r'''
library; // Ensures that the function type alias declaration isn't at offset 0
typedef void();
''',
[
error(WarningCode.UNUSED_ELEMENT, 0, 0),
error(ParserErrorCode.MISSING_IDENTIFIER, 92, 1),
],
);
var functionTypeAlias = findNode.functionTypeAlias('void()');
checkOffsetInRange<TypeAliasFragment>(
functionTypeAlias,
functionTypeAlias.declaredFragment!,
);
}
test_typeAliasFragment_genericTypeAlias() async {
await assertNoErrorsInCode(r'''
typedef T = int;
''');
var genericTypeAlias = findNode.genericTypeAlias('T');
checkOffset<TypeAliasFragment>(
genericTypeAlias,
genericTypeAlias.declaredFragment!,
genericTypeAlias.name.offset,
);
}
test_typeAliasFragment_genericTypeAlias_missingName() async {
await assertErrorsInCode(
r'''
library; // Ensures that the generic type alias declaration isn't at offset 0
typedef = int;
''',
[
error(WarningCode.UNUSED_ELEMENT, 0, 0),
error(ParserErrorCode.MISSING_IDENTIFIER, 87, 1),
],
);
var genericTypeAlias = findNode.genericTypeAlias('= int');
checkOffsetInRange<TypeAliasFragment>(
genericTypeAlias,
genericTypeAlias.declaredFragment!,
);
}
test_typeParameterFragment() async {
await assertNoErrorsInCode(r'''
class C<T> {}
''');
var typeParameter = findNode.typeParameter('T');
checkOffset<TypeParameterFragment>(
typeParameter,
typeParameter.declaredFragment!,
typeParameter.name.offset,
);
}
}