Skip to content

Commit

Permalink
Version 3.3.0-251.0.dev
Browse files Browse the repository at this point in the history
Merge 64aa1a9 into dev
  • Loading branch information
Dart CI committed Dec 21, 2023
2 parents 63a452b + 64aa1a9 commit 1d0c3ec
Show file tree
Hide file tree
Showing 22 changed files with 680 additions and 89 deletions.
6 changes: 5 additions & 1 deletion pkg/analyzer/lib/src/dart/element/element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4039,7 +4039,7 @@ class LibraryElementImpl extends LibraryOrAugmentationElementImpl
@override
late TypeSystemImpl typeSystem;

late final List<ExportedReference> exportedReferences;
late List<ExportedReference> exportedReferences;

@override
LibraryElementLinkedData? linkedData;
Expand Down Expand Up @@ -4791,6 +4791,10 @@ abstract class LibraryOrAugmentationElementImpl extends ElementImpl
return _definingCompilationUnit.source;
}

void resetScope() {
_scope = null;
}

void _readLinkedData();

static List<PrefixElementImpl> buildPrefixesFromImports(
Expand Down
27 changes: 22 additions & 5 deletions pkg/analyzer/lib/src/summary2/library_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ class LibraryBuilder {
final Map<String, Reference> _declaredReferences = {};

/// The export scope of the library.
final ExportScope exportScope = ExportScope();
ExportScope exportScope = ExportScope();

/// The `export` directives that export this library.
final List<Export> exports = [];
Expand Down Expand Up @@ -319,6 +319,7 @@ class LibraryBuilder {
}

void buildInitialExportScope() {
exportScope = ExportScope();
_declaredReferences.forEach((name, reference) {
if (name.startsWith('_')) return;
if (reference.isPrefix) return;
Expand Down Expand Up @@ -361,12 +362,12 @@ class LibraryBuilder {
/// because we ran all, or those that we have not run yet have dependencies
/// of interfaces declared in other libraries that, and we have not run yet
/// declarations phase macro applications for them.
Future<bool> executeMacroDeclarationsPhase({
Future<MacroDeclarationsPhaseStepResult> executeMacroDeclarationsPhase({
required Element? targetElement,
}) async {
final macroApplier = linker.macroApplier;
if (macroApplier == null) {
return false;
return MacroDeclarationsPhaseStepResult.nothing;
}

final results = await macroApplier.executeDeclarationsPhase(
Expand All @@ -376,11 +377,21 @@ class LibraryBuilder {

// No more applications to execute.
if (results == null) {
return false;
return MacroDeclarationsPhaseStepResult.nothing;
}

await _addMacroResults(macroApplier, results, buildTypes: true);
return true;

// Check if a new top-level declaration was added.
final augmentationUnit = units.last.element;
if (augmentationUnit.functions.isNotEmpty ||
augmentationUnit.topLevelVariables.isNotEmpty) {
element.resetScope();
return MacroDeclarationsPhaseStepResult.topDeclaration;
}

// Probably class member declarations.
return MacroDeclarationsPhaseStepResult.otherProgress;
}

Future<void> executeMacroDefinitionsPhase({
Expand Down Expand Up @@ -1197,6 +1208,12 @@ class LinkingUnit {
});
}

enum MacroDeclarationsPhaseStepResult {
nothing,
otherProgress,
topDeclaration,
}

/// This class examines all the [InterfaceElement]s in a library and determines
/// which fields are promotable within that library.
class _FieldPromotability extends FieldPromotability<InterfaceElement,
Expand Down
109 changes: 61 additions & 48 deletions pkg/analyzer/lib/src/summary2/link.dart
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,56 @@ class Linker {
}
}

void _buildExportScopes() {
for (var library in builders.values) {
library.buildInitialExportScope();
}

var exportingBuilders = <LibraryBuilder>{};
var exportedBuilders = <LibraryBuilder>{};

for (var library in builders.values) {
library.addExporters();
}

for (var library in builders.values) {
if (library.exports.isNotEmpty) {
exportedBuilders.add(library);
for (var export in library.exports) {
exportingBuilders.add(export.exporter);
}
}
}

var both = <LibraryBuilder>{};
for (var exported in exportedBuilders) {
if (exportingBuilders.contains(exported)) {
both.add(exported);
}
for (var export in exported.exports) {
exported.exportScope.forEach(export.addToExportScope);
}
}

while (true) {
var hasChanges = false;
for (var exported in both) {
for (var export in exported.exports) {
exported.exportScope.forEach((name, reference) {
if (export.addToExportScope(name, reference)) {
hasChanges = true;
}
});
}
}
if (!hasChanges) break;
}

for (var library in builders.values) {
library.storeExportScope();
}
}

Future<LibraryMacroApplier?> _buildMacroApplier() async {
final macroExecutor = this.macroExecutor;
if (macroExecutor == null) {
Expand Down Expand Up @@ -245,53 +295,7 @@ class Linker {
},
);

for (var library in builders.values) {
library.buildInitialExportScope();
}

var exportingBuilders = <LibraryBuilder>{};
var exportedBuilders = <LibraryBuilder>{};

for (var library in builders.values) {
library.addExporters();
}

for (var library in builders.values) {
if (library.exports.isNotEmpty) {
exportedBuilders.add(library);
for (var export in library.exports) {
exportingBuilders.add(export.exporter);
}
}
}

var both = <LibraryBuilder>{};
for (var exported in exportedBuilders) {
if (exportingBuilders.contains(exported)) {
both.add(exported);
}
for (var export in exported.exports) {
exported.exportScope.forEach(export.addToExportScope);
}
}

while (true) {
var hasChanges = false;
for (var exported in both) {
for (var export in exported.exports) {
exported.exportScope.forEach((name, reference) {
if (export.addToExportScope(name, reference)) {
hasChanges = true;
}
});
}
}
if (!hasChanges) break;
}

for (var library in builders.values) {
library.storeExportScope();
}
_buildExportScopes();
}

void _createTypeSystem() {
Expand Down Expand Up @@ -324,9 +328,18 @@ class Linker {
while (true) {
var hasProgress = false;
for (final library in builders.values) {
hasProgress |= await library.executeMacroDeclarationsPhase(
final stepResult = await library.executeMacroDeclarationsPhase(
targetElement: targetElement,
);
switch (stepResult) {
case MacroDeclarationsPhaseStepResult.nothing:
break;
case MacroDeclarationsPhaseStepResult.otherProgress:
hasProgress = true;
case MacroDeclarationsPhaseStepResult.topDeclaration:
hasProgress = true;
_buildExportScopes();
}
}
if (!hasProgress) {
break;
Expand Down
9 changes: 8 additions & 1 deletion pkg/analyzer/lib/src/summary2/macro_application.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,14 @@ class _TypePhaseIntrospector implements macro.TypePhaseIntrospector {
if (element is PropertyAccessorElement && element.isSynthetic) {
element = element.variable;
}
return declarationBuilder.fromElement.identifier(element!);
if (element == null) {
throw ArgumentError([
'Unresolved identifier.',
'library: $library',
'name: $name',
].join('\n'));
}
return declarationBuilder.fromElement.identifier(element);
}
}

Expand Down
63 changes: 63 additions & 0 deletions pkg/analyzer/test/src/dart/resolution/macro_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,69 @@ augment class A {
name: NotType
element: <null>
type: InvalidType
''');
}

test_getResolvedLibrary_reference_declaredGetter() async {
newFile(
'$testPackageLibPath/append.dart',
getMacroCode('append.dart'),
);

newFile('$testPackageLibPath/test.dart', r'''
import 'append.dart';
@DeclareInLibrary('{{dart:core@int}} get x => 0;')
void f() {
x;
}
''');

final session = contextFor(testFile).currentSession;
final result = await session.getResolvedLibrary(testFile.path);

// 1. `get x` was declared.
// 2. The reference to `x` can be resolved in the library unit.
assertResolvedLibraryResultText(result, configure: (configuration) {
configuration.unitConfiguration
..nodeSelector = (unitResult) {
switch (unitResult.uriStr) {
case 'package:test/test.dart':
return unitResult.findNode.singleBlock;
}
return null;
}
..withContentPredicate = (unitResult) {
return unitResult.isAugmentation;
};
}, r'''
ResolvedLibraryResult
element: package:test/test.dart
units
/home/test/lib/test.dart
flags: exists isLibrary
uri: package:test/test.dart
selectedNode: Block
leftBracket: {
statements
ExpressionStatement
expression: SimpleIdentifier
token: x
staticElement: package:test/test.dart::@augmentation::package:test/test.macro.dart::@accessor::x
staticType: int
semicolon: ;
rightBracket: }
/home/test/lib/test.macro.dart
flags: exists isAugmentation isMacroAugmentation
uri: package:test/test.macro.dart
content
---
library augment 'test.dart';
import 'dart:core' as prefix0;
prefix0.int get x => 0;
---
''');
}
}
2 changes: 2 additions & 0 deletions pkg/analyzer/test/src/dart/resolution/resolution.dart
Original file line number Diff line number Diff line change
Expand Up @@ -652,4 +652,6 @@ extension ResolvedUnitResultExtension on ResolvedUnitResult {
FindNode get findNode {
return FindNode(content, unit);
}

String get uriStr => '$uri';
}
33 changes: 3 additions & 30 deletions pkg/analyzer/test/src/summary/macro/add_augment_declaration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import 'package:_fe_analyzer_shared/src/macros/api.dart';

import 'append.dart';

/*macro*/ class AddConstructor extends _AddMacroClass {
const AddConstructor();

Expand Down Expand Up @@ -127,39 +129,10 @@ class _AddMacro {
String withIdentifiers,
) async {
final withoutEOL = withIdentifiers.trimRight();
final parts = await _resolveIdentifiers(builder, withoutEOL);
final parts = await resolveIdentifiers(builder, withoutEOL);
final code = DeclarationCode.fromParts(parts);
builder.declareInType(code);
}

/// Resolves top-level identifier references of form `{{uri@name}}`.
static Future<List<Object>> _resolveIdentifiers(
TypePhaseIntrospector introspector,
String withIdentifiers,
) async {
final result = <Object>[];
var lastMatchEnd = 0;

void addStringPart(int end) {
final str = withIdentifiers.substring(lastMatchEnd, end);
result.add(str);
}

final pattern = RegExp(r'\{\{(.+)@(\w+)\}\}');
for (final match in pattern.allMatches(withIdentifiers)) {
addStringPart(match.start);
// ignore: deprecated_member_use
final identifier = await introspector.resolveIdentifier(
Uri.parse(match.group(1)!),
match.group(2)!,
);
result.add(identifier);
lastMatchEnd = match.end;
}

addStringPart(withIdentifiers.length);
return result;
}
}

abstract class _AddMacroClass extends _AddMacro
Expand Down
Loading

0 comments on commit 1d0c3ec

Please sign in to comment.