| // Copyright (c) 2023, 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:io' show Directory, Platform; |
| |
| import 'package:_fe_analyzer_shared/src/testing/features.dart'; |
| import 'package:_fe_analyzer_shared/src/testing/id.dart'; |
| import 'package:_fe_analyzer_shared/src/testing/id_testing.dart' |
| show DataInterpreter, ddcMarker, runTests; |
| import 'package:front_end/src/api_prototype/experimental_flags.dart' as fe; |
| import 'package:kernel/ast.dart'; |
| import 'package:kernel/dart_scope_calculator.dart'; |
| import 'package:kernel/src/printer.dart' show AstPrinter, AstTextStrategy; |
| |
| import '../id_testing_helper.dart'; |
| |
| Future<void> main(List<String> args) async { |
| var dataDir = Directory.fromUri( |
| Platform.script.resolve('../../../front_end/test/scopes/data'), |
| ); |
| await runTests<Features>( |
| dataDir, |
| args: args, |
| createUriForFileName: createUriForFileName, |
| onFailure: onFailure, |
| runTest: runTestFor(const ScopeDataComputer(), [ |
| DdcTestConfig( |
| ddcMarker, |
| 'ddc', |
| experimentalFlags: {fe.ExperimentalFlag.inlineClass: true}, |
| ), |
| ]), |
| ); |
| } |
| |
| class Tags { |
| static const String cls = 'class'; |
| static const String member = 'member'; |
| static const String isStatic = 'static'; |
| static const String typeParameter = 'typeParameters'; |
| static const String variables = 'variables'; |
| } |
| |
| class ScopeDataComputer extends DdcDataComputer<Features> { |
| const ScopeDataComputer(); |
| |
| @override |
| void computeMemberData( |
| DdcTestResultData testResultData, |
| Member member, |
| Map<Id, ActualData<Features>> actualMap, { |
| bool? verbose, |
| }) { |
| member.accept( |
| ScopeDataExtractor( |
| member.enclosingLibrary, |
| testResultData.compilerResult, |
| actualMap, |
| ), |
| ); |
| } |
| |
| @override |
| DataInterpreter<Features> get dataValidator => |
| const FeaturesDataInterpreter(); |
| } |
| |
| class ScopeDataExtractor extends DdcDataExtractor<Features> { |
| final Library library; |
| |
| ScopeDataExtractor(this.library, super.compilerResult, super.actualMap); |
| |
| Component get component => compilerResult.ddcResult.component; |
| |
| @override |
| Features? computeNodeValue(Id id, TreeNode node) { |
| // We use references to a static variable 'x' as the marker for where we |
| // want to compute the scope. |
| if (node is StaticGet && node.target.name.text == 'x') { |
| var location = node.location; |
| if (location != null) { |
| final offset = component.getOffset( |
| library.fileUri, |
| location.line, |
| location.column, |
| ); |
| var scope = DartScopeBuilder2.findScopeFromOffset( |
| library, |
| library.fileUri, |
| offset, |
| ); |
| var features = Features(); |
| if (scope.cls != null) { |
| features[Tags.cls] = scope.cls!.name; |
| } |
| if (scope.member != null) { |
| features[Tags.member] = scope.member!.name.text; |
| } |
| if (scope.isStatic) { |
| features.add(Tags.isStatic); |
| } |
| for (var typeParameter in scope.typeParameters) { |
| var printer = AstPrinter( |
| const AstTextStrategy( |
| useQualifiedTypeParameterNames: true, |
| useQualifiedTypeParameterNamesRecurseOnNamedLocalFunctions: true, |
| includeLibraryNamesInTypes: false, |
| ), |
| ); |
| printer.writeTypeParameterName(typeParameter); |
| features.addElement(Tags.typeParameter, printer.getText()); |
| } |
| for (var variable in scope.variables.keys) { |
| features.addElement(Tags.variables, variable); |
| } |
| return features; |
| } |
| } |
| return super.computeNodeValue(id, node); |
| } |
| } |