| // 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:front_end/src/api_unstable/ddc.dart' show DartScopeBuilder2; | |
| import 'package:kernel/ast.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, | |
| ActualDataMap<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 null; | |
| } | |
| } |