// Copyright (c) 2020, 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. // @dart = 2.9 import 'package:dev_compiler/src/kernel/expression_compiler.dart'; import 'package:front_end/src/api_unstable/ddc.dart'; import 'package:front_end/src/compute_platform_binaries_location.dart'; import 'package:kernel/ast.dart'; import 'package:kernel/binary/ast_from_binary.dart'; import 'package:kernel/src/printer.dart'; import 'package:test/test.dart'; /// Verbose mode for debugging bool get verbose => false; Uri get sdkRoot => computePlatformBinariesLocation(); Uri get sdkSummaryPath => sdkRoot.resolve('ddc_sdk.dill'); Uri get librariesPath => sdkRoot.resolve('lib/libraries.json'); void main(List args) { test('Offsets are present on scoping nodes in SDK', () async { var entity = StandardFileSystem.instance.entityForUri(sdkSummaryPath); var bytes = await entity.readAsBytes(); var component = Component(); BinaryBuilderWithMetadata(bytes, disableLazyReading: true) .readComponent(component, checkCanonicalNames: true, createView: true); for (var lib in component.libraries) { ScopeOffsetValidator.validate(lib); } }); } class ScopeOffsetValidator extends Visitor with VisitorVoidMixin { int classCount = 0; int memberCount = 0; int blockCount = 0; ScopeOffsetValidator._(); static void validate(Library library) { var validator = ScopeOffsetValidator._(); validator.visitLibrary(library); expect(validator.classCount + validator.memberCount, greaterThan(0), reason: 'Validation was not empty'); expect(validator.blockCount, equals(0), reason: 'SDK dill only contains outlines'); } @override void defaultTreeNode(Node node) { node.visitChildren(this); } @override void visitClass(Class cls) { classCount++; expect( cls, const TypeMatcher() .having((c) => c.fileOffset, '${cls.name} : fileOffset', isNot(equals(-1))) .having((c) => c.fileEndOffset, '${cls.name} : fileEndOffset', isNot(equals(-1)))); super.visitClass(cls); } @override void defaultMember(Member member) { // exclude code that does not correspond to a dart source // location we can set a breakpoint on. var noBreakPointPossible = (member is Constructor) ? member.isSynthetic : (member is Procedure) ? member.isNoSuchMethodForwarder || member.isAbstract || member.isForwardingStub || member.stubKind == ProcedureStubKind.ConcreteMixinStub : (member is Field) ? member.name.text.contains(redirectingName) : false; if (!noBreakPointPossible) { memberCount++; expect( member, const TypeMatcher() .having( (c) => c.fileOffset, '${member.enclosingClass}.${member.name} : fileOffset', isNot(equals(-1))) .having( (c) => c.fileEndOffset, '${member.enclosingClass}.${member.name} : fileEndOffset', isNot(equals(-1)))); super.defaultMember(member); } } @override void visitFunctionNode(FunctionNode fun) { expect( fun, const TypeMatcher() .having( (c) => c.fileOffset, '${fun.parent.toText(astTextStrategyForTesting)} : fileOffset', isNot(equals(-1))) .having( (c) => c.fileEndOffset, '${fun.parent.toText(astTextStrategyForTesting)} : fileEndOffset', isNot(equals(-1)))); super.visitFunctionNode(fun); } @override void visitBlock(Block block) { blockCount++; expect( block, const TypeMatcher().having( (c) => c.fileOffset, '${block.toText(astTextStrategyForTesting)} : fileOffset', isNot(equals(-1)))); var fileEndOffset = FileEndOffsetCalculator.calculateEndOffset(block); expect(fileEndOffset, isNot(equals(-1)), reason: '${block.toText(astTextStrategyForTesting)} : fileOffset'); super.visitBlock(block); } }