[ddc] Add constructor symbol information

- Adds tests for various types of constructors.
- Recognize when a constructor is const and mark the class symbol
  accordingly.

Change-Id: I9ae7fc2837a6821b196f06a267603fd18c3e5075
Issue: https://github.com/dart-lang/sdk/issues/40273
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208362
Reviewed-by: Anna Gringauze <annagrin@google.com>
Commit-Queue: Nicholas Shahan <nshahan@google.com>
This commit is contained in:
Nicholas Shahan 2021-10-01 22:57:09 +00:00 committed by commit-bot@chromium.org
parent 6f4d79a7e9
commit ea4302d029
3 changed files with 368 additions and 73 deletions

View file

@ -1046,8 +1046,9 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
if (name != '' || hasUnnamedSuper)
_emitSuperConstructorCall(className, name, jsParams),
];
body.add(_addConstructorToClass(
c, className, name, js_ast.Fun(jsParams, js_ast.Block(ctorBody))));
// TODO(nshahan) Record the name for this constructor in memberNames.
body.add(_addConstructorToClass(c, className, _constructorName(name),
js_ast.Fun(jsParams, js_ast.Block(ctorBody))));
}
}
@ -1197,14 +1198,17 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
return body;
}
void addConstructor(String name, js_ast.Expression jsCtor) {
void addConstructor(js_ast.LiteralString name, js_ast.Expression jsCtor) {
body.add(_addConstructorToClass(c, className, name, jsCtor));
}
var fields = c.fields;
for (var ctor in c.constructors) {
if (ctor.isExternal) continue;
addConstructor(ctor.name.text, _emitConstructor(ctor, fields, className));
var constructorName = _constructorName(ctor.name.text);
memberNames[ctor] = constructorName.valueWithoutQuotes;
addConstructor(
constructorName, _emitConstructor(ctor, fields, className));
}
// If classElement has only factory constructors, and it can be mixed in,
@ -1617,7 +1621,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
return body;
}
js_ast.Expression _constructorName(String name) {
js_ast.LiteralString _constructorName(String name) {
if (name == '') {
// Default constructors (factory or not) use `new` as their name.
return propertyName('new');
@ -1773,8 +1777,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
}
js_ast.Statement _addConstructorToClass(Class c, js_ast.Expression className,
String name, js_ast.Expression jsCtor) {
jsCtor = defineValueOnClass(c, className, _constructorName(name), jsCtor);
js_ast.LiteralString name, js_ast.Expression jsCtor) {
jsCtor = defineValueOnClass(c, className, name, jsCtor);
return js.statement('#.prototype = #.prototype;', [jsCtor, className]);
}
@ -2084,9 +2088,10 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
/// [_emitFunction] instead.
var name = node.name.text;
var jsBody = _emitSyncFunctionBody(function, name);
var jsName = _constructorName(name);
memberNames[node] = jsName.valueWithoutQuotes;
return js_ast.Method(
_constructorName(name), js_ast.Fun(_emitParameters(function), jsBody),
return js_ast.Method(jsName, js_ast.Fun(_emitParameters(function), jsBody),
isStatic: true)
..sourceInformation = _nodeEnd(node.fileEndOffset);
}

View file

@ -49,12 +49,38 @@ class ModuleSymbolsCollector extends RecursiveVisitor {
// TODO(nshahan) How to handle function types or types from other modules?
type is InterfaceType ? _classJsNames[type.classNode] : null;
/// Returns the symbol for the function defined by [node].
void _createFunctionSymbol(Member node) {
var functionSymbol = FunctionSymbol(
name: node.name.text,
// TODO(nshahan) typeId - probably should canonicalize but keep original
// type argument names.
// TODO(nshahan) Should we mark all constructors static?
isStatic: node is Procedure ? node.isStatic : false,
isConst: node.isConst,
localId: _memberJsNames[node] ?? _procedureJsNames[node],
scopeId: _scopes.last.id,
variableIds: <String>[],
scopeIds: <String>[],
location: SourceLocation(
scriptId: _scriptId(node.location.file),
tokenPos: node.fileOffset,
endTokenPos: node.fileEndOffset));
_scopes.add(functionSymbol);
node.visitChildren(this);
_scopes
..removeLast()
..last.scopeIds.add(functionSymbol.id);
_moduleSymbols.functions.add(functionSymbol);
}
@override
void visitClass(Class node) {
var classSymbol = ClassSymbol(
name: node.name,
isAbstract: node.isAbstract,
// TODO(nshahan) isConst - Does this mean has a const constructor?
isConst: node.constructors.any((constructor) => constructor.isConst),
superClassId: _classJsNames[node.superclass],
interfaceIds: [
for (var type in node.implementedTypes) _classJsNames[type.classNode]
@ -82,6 +108,9 @@ class ModuleSymbolsCollector extends RecursiveVisitor {
_moduleSymbols.classes.add(classSymbol);
}
@override
void visitConstructor(Constructor node) => _createFunctionSymbol(node);
@override
void visitField(Field node) {
var fieldSymbol = VariableSymbol(
@ -149,27 +178,7 @@ class ModuleSymbolsCollector extends RecursiveVisitor {
// Also avoid adding information for the static methods introduced by the
// CFE lowering for constructor tearoffs.
if (node.function.body == null || isTearOffLowering(node)) return;
var functionSymbol = FunctionSymbol(
name: node.name.text,
// TODO(nshahan) typeId - probably should canonicalize but keep original
// type argument names.
isStatic: node.isStatic,
isConst: node.isConst,
localId: _memberJsNames[node] ?? _procedureJsNames[node],
scopeId: _scopes.last.id,
variableIds: <String>[],
scopeIds: <String>[],
location: SourceLocation(
scriptId: _scriptId(node.location.file),
tokenPos: node.fileOffset,
endTokenPos: node.fileEndOffset));
_scopes.add(functionSymbol);
node.visitChildren(this);
_scopes
..removeLast()
..last.scopeIds.add(functionSymbol.id);
_moduleSymbols.functions.add(functionSymbol);
_createFunctionSymbol(node);
}
@override

View file

@ -10,6 +10,13 @@ import 'package:test/test.dart';
import '../shared_test_options.dart';
import 'module_symbols_test_shared.dart';
/// Returns the [FunctionSymbol] from [ModuleSymbols] with the [name] in the
/// original Dart source code or throws an error if there isn't exactly one.
FunctionSymbol _symbolForDartFunction(ModuleSymbols symbols, String name) =>
symbols.functions
.where((functionSymbol) => functionSymbol.name == name)
.single;
void main() async {
for (var mode in [
NullSafetyTestOption('Sound Mode:', true),
@ -20,6 +27,7 @@ void main() async {
group('simple class debug symbols', () {
TestDriver driver;
ClassSymbol classSymbol;
FunctionSymbol functionSymbol;
final source = '''
${options.dartLangComment}
@ -29,6 +37,7 @@ void main() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
functionSymbol = result.symbols.functions.single;
});
tearDownAll(() {
driver.cleanUp();
@ -39,7 +48,9 @@ void main() async {
test('is not abstract', () async {
expect(classSymbol.isAbstract, isFalse);
});
// TODO test isConst
test('is not const', () async {
expect(classSymbol.isConst, isFalse);
});
test('has no superclassId', () async {
expect(classSymbol.superClassId, isNull);
});
@ -71,7 +82,14 @@ void main() async {
test('no fields', () async {
expect(classSymbol.variableIds, isEmpty);
});
// TODO only has the implicit constructor in scopeIds.
test('only default constructor in functionIds', () {
var constructorId = classSymbol.functionIds.single;
expect(constructorId, functionSymbol.id);
// Default constructor has no name in Dart Kernel AST.
expect(functionSymbol.name, isEmpty);
// Default constructor is named 'new' in JavaScript.
expect(functionSymbol.id, endsWith('A|new'));
});
});
group('abstract class debug symbols', () {
TestDriver driver;
@ -308,14 +326,15 @@ void main() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = result.symbols.functions.single;
methodSymbol =
_symbolForDartFunction(result.symbols, 'publicInstanceMethod');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|publicInstanceMethod'));
expect(methodSymbol.id, classSymbol.functionIds.single);
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
@ -340,14 +359,15 @@ void main() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = result.symbols.functions.single;
methodSymbol =
_symbolForDartFunction(result.symbols, '_privateInstanceMethod');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|Symbol(_privateInstanceMethod)'));
expect(methodSymbol.id, classSymbol.functionIds.single);
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
@ -372,14 +392,15 @@ void main() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = result.symbols.functions.single;
methodSymbol =
_symbolForDartFunction(result.symbols, 'publicStaticMethod');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|publicStaticMethod'));
expect(methodSymbol.id, classSymbol.functionIds.single);
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
@ -404,14 +425,15 @@ void main() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = result.symbols.functions.single;
methodSymbol =
_symbolForDartFunction(result.symbols, '_privateStaticMethod');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|_privateStaticMethod'));
expect(methodSymbol.id, classSymbol.functionIds.single);
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
@ -429,21 +451,22 @@ void main() async {
${options.dartLangComment}
class A {
String get publicGetter() => 'Fosse';
String get publicInstanceGetter() => 'Fosse';
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = result.symbols.functions.single;
methodSymbol =
_symbolForDartFunction(result.symbols, 'publicInstanceGetter');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|publicGetter'));
expect(methodSymbol.id, classSymbol.functionIds.single);
expect(methodSymbol.id, endsWith('A|publicInstanceGetter'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
@ -461,21 +484,22 @@ void main() async {
${options.dartLangComment}
class A {
String get _privateGetter() => 'Fosse';
String get _privateInstanceGetter() => 'Fosse';
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = result.symbols.functions.single;
methodSymbol =
_symbolForDartFunction(result.symbols, '_privateInstanceGetter');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|Symbol(_privateGetter)'));
expect(methodSymbol.id, classSymbol.functionIds.single);
expect(methodSymbol.id, endsWith('A|Symbol(_privateInstanceGetter)'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
@ -494,21 +518,22 @@ void main() async {
class A {
var _value
set publicSetter(String v) => _value = v;
set publicInstanceSetter(String v) => _value = v;
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = result.symbols.functions.single;
methodSymbol =
_symbolForDartFunction(result.symbols, 'publicInstanceSetter');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|publicSetter'));
expect(methodSymbol.id, classSymbol.functionIds.single);
expect(methodSymbol.id, endsWith('A|publicInstanceSetter'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
@ -527,21 +552,22 @@ void main() async {
class A {
var _value
set _privateSetter(String v) => _value = v;
set _privateInstanceSetter(String v) => _value = v;
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = result.symbols.functions.single;
methodSymbol =
_symbolForDartFunction(result.symbols, '_privateInstanceSetter');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|Symbol(_privateSetter)'));
expect(methodSymbol.id, classSymbol.functionIds.single);
expect(methodSymbol.id, endsWith('A|Symbol(_privateInstanceSetter)'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
@ -559,21 +585,22 @@ void main() async {
${options.dartLangComment}
class A {
static String get publicGetter() => 'Fosse';
static String get publicStaticGetter() => 'Fosse';
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = result.symbols.functions.single;
methodSymbol =
_symbolForDartFunction(result.symbols, 'publicStaticGetter');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|publicGetter'));
expect(methodSymbol.id, classSymbol.functionIds.single);
expect(methodSymbol.id, endsWith('A|publicStaticGetter'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
@ -591,21 +618,22 @@ void main() async {
${options.dartLangComment}
class A {
static String get _privateGetter() => 'Fosse';
static String get _privateStaticGetter() => 'Fosse';
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = result.symbols.functions.single;
methodSymbol =
_symbolForDartFunction(result.symbols, '_privateStaticGetter');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|_privateGetter'));
expect(methodSymbol.id, classSymbol.functionIds.single);
expect(methodSymbol.id, endsWith('A|_privateStaticGetter'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
@ -624,21 +652,22 @@ void main() async {
class A {
var _value;
static set publicSetter(String v) => _value = v;
static set publicStaticSetter(String v) => _value = v;
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = result.symbols.functions.single;
methodSymbol =
_symbolForDartFunction(result.symbols, 'publicStaticSetter');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|publicSetter'));
expect(methodSymbol.id, classSymbol.functionIds.single);
expect(methodSymbol.id, endsWith('A|publicStaticSetter'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
@ -657,21 +686,22 @@ void main() async {
class A {
var _value;
static set _privateSetter(String v) => _value = v;
static set _privateStaticSetter(String v) => _value = v;
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = result.symbols.functions.single;
methodSymbol =
_symbolForDartFunction(result.symbols, '_privateStaticSetter');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|_privateSetter'));
expect(methodSymbol.id, classSymbol.functionIds.single);
expect(methodSymbol.id, endsWith('A|_privateStaticSetter'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
@ -681,6 +711,257 @@ void main() async {
expect(methodSymbol.isStatic, isTrue);
});
});
group('class public const constructor debug symbols', () {
TestDriver driver;
ClassSymbol classSymbol;
FunctionSymbol methodSymbol;
final source = '''
${options.dartLangComment}
class A {
const A();
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = _symbolForDartFunction(result.symbols, '');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|new'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
expect(methodSymbol.scopeId, classSymbol.id);
});
test('is const', () async {
expect(methodSymbol.isConst, isTrue);
expect(classSymbol.isConst, isTrue);
});
});
group('class public named constructor debug symbols', () {
TestDriver driver;
ClassSymbol classSymbol;
FunctionSymbol methodSymbol;
final source = '''
${options.dartLangComment}
class A {
A.named();
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = _symbolForDartFunction(result.symbols, 'named');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|named'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
expect(methodSymbol.scopeId, classSymbol.id);
});
});
group('class private named constructor debug symbols', () {
TestDriver driver;
ClassSymbol classSymbol;
FunctionSymbol methodSymbol;
final source = '''
${options.dartLangComment}
class A {
var _value;
A._(this._value);
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = _symbolForDartFunction(result.symbols, '_');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|__'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
expect(methodSymbol.scopeId, classSymbol.id);
});
});
group('class unnamed factory debug symbols', () {
TestDriver driver;
ClassSymbol classSymbol;
FunctionSymbol methodSymbol;
final source = '''
${options.dartLangComment}
class A {
var _value;
A._(this._value);
factory A() => A._(10);
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol = _symbolForDartFunction(result.symbols, '');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|new'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
expect(methodSymbol.scopeId, classSymbol.id);
});
});
group('class public named factory debug symbols', () {
TestDriver driver;
ClassSymbol classSymbol;
FunctionSymbol methodSymbol;
final source = '''
${options.dartLangComment}
class A {
var _value;
A._(this._value);
factory A.publicFactory() => A._(10);
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol =
_symbolForDartFunction(result.symbols, 'publicFactory');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|publicFactory'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
expect(methodSymbol.scopeId, classSymbol.id);
});
});
group('class private named factory debug symbols', () {
TestDriver driver;
ClassSymbol classSymbol;
FunctionSymbol methodSymbol;
final source = '''
${options.dartLangComment}
class A {
var _value;
A._(this._value);
factory A._privateFactory() => A._(10);
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol =
_symbolForDartFunction(result.symbols, '_privateFactory');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|_privateFactory'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
expect(methodSymbol.scopeId, classSymbol.id);
});
});
group('class public redirecting constructor debug symbols', () {
TestDriver driver;
ClassSymbol classSymbol;
FunctionSymbol methodSymbol;
final source = '''
${options.dartLangComment}
class A {
var _value;
A(this._value);
A.publicRedirecting() : this(10);
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol =
_symbolForDartFunction(result.symbols, 'publicRedirecting');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|publicRedirecting'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
expect(methodSymbol.scopeId, classSymbol.id);
});
});
group('class private redirecting constructor debug symbols', () {
TestDriver driver;
ClassSymbol classSymbol;
FunctionSymbol methodSymbol;
final source = '''
${options.dartLangComment}
class A {
var _value;
A(this._value);
A._privateRedirecting() : this(10);
}
''';
setUpAll(() async {
driver = TestDriver(options, source);
var result = await driver.compile();
classSymbol = result.symbols.classes.single;
methodSymbol =
_symbolForDartFunction(result.symbols, '_privateRedirecting');
});
tearDownAll(() {
driver.cleanUp();
});
test('functionId in classSymbol', () async {
expect(methodSymbol.id, endsWith('A|_privateRedirecting'));
expect(classSymbol.functionIds, contains(methodSymbol.id));
});
test('has class scopeId', () async {
expect(methodSymbol.scopeId, endsWith('|A'));
expect(methodSymbol.scopeId, classSymbol.id);
});
});
});
}
}