Skip to content

Commit

Permalink
Augment. Fixes for augmented extensions and exported declarations.
Browse files Browse the repository at this point in the history
Change-Id: I06a68850850abaccdd1eeb444adddbc1f9f62d08
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/366163
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
  • Loading branch information
scheglov authored and Commit Queue committed May 13, 2024
1 parent 03a0467 commit 299ddd0
Show file tree
Hide file tree
Showing 9 changed files with 510 additions and 10 deletions.
3 changes: 1 addition & 2 deletions pkg/analyzer/lib/src/dart/element/member.dart
Original file line number Diff line number Diff line change
Expand Up @@ -992,8 +992,7 @@ class PropertyAccessorMember extends ExecutableMember

@override
PropertyAccessorElement? get augmentation {
// TODO(scheglov): implement
throw UnimplementedError();
return declaration.augmentation;
}

@override
Expand Down
4 changes: 4 additions & 0 deletions pkg/analyzer/lib/src/dart/element/scope.dart
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ class LibraryOrAugmentationScope extends EnclosedScope {
}

void _addExtension(ExtensionElement element) {
if (element.isAugmentation) {
return;
}

_addGetter(element);
if (!extensions.contains(element)) {
extensions.add(element);
Expand Down
6 changes: 3 additions & 3 deletions pkg/analyzer/lib/src/dart/resolver/applicable_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
if (baseName == '[]') {
ExecutableElement? getter;
ExecutableElement? setter;
for (var method in extension.methods) {
for (var method in extension.augmented.methods) {
if (method.name == '[]') {
getter = method;
} else if (method.name == '[]=') {
Expand All @@ -139,7 +139,7 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
);
}
} else {
for (var field in extension.fields) {
for (var field in extension.augmented.fields) {
if (field.name == baseName) {
result.add(
_NotInstantiatedExtensionWithMember(
Expand All @@ -151,7 +151,7 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
break;
}
}
for (var method in extension.methods) {
for (var method in extension.augmented.methods) {
if (method.name == baseName) {
result.add(
_NotInstantiatedExtensionWithMember(
Expand Down
12 changes: 9 additions & 3 deletions pkg/analyzer/lib/src/summary2/element_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
_linker.elementNodes[element] = node;

var reference = _enclosingContext.addClass(name, element);
_libraryBuilder.declare(name, reference);
if (!element.isAugmentation) {
_libraryBuilder.declare(name, reference);
}

var holder = _EnclosingContext(reference, element);
_withEnclosing(holder, () {
Expand Down Expand Up @@ -245,7 +247,9 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
_linker.elementNodes[element] = node;

var reference = _enclosingContext.addEnum(name, element);
_libraryBuilder.declare(name, reference);
if (!element.isAugmentation) {
_libraryBuilder.declare(name, reference);
}

_libraryBuilder.updateAugmentationTarget(name, element);

Expand Down Expand Up @@ -472,7 +476,9 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
var reference = _enclosingContext.addExtension(refName, element);

if (name != null) {
_libraryBuilder.declare(name, reference);
if (!element.isAugmentation) {
_libraryBuilder.declare(name, reference);
}
}

var holder = _EnclosingContext(reference, element);
Expand Down
152 changes: 152 additions & 0 deletions pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,70 @@ IndexExpression
''');
}

test_read_ofExtension() async {
await assertNoErrorsInCode(r'''
extension E on int {
bool operator[](int index) => false;
}
void f() {
0[1];
}
''');

var indexExpression = findNode.singleIndexExpression;
assertResolvedNodeText(indexExpression, r'''
IndexExpression
target: IntegerLiteral
literal: 0
staticType: int
leftBracket: [
index: IntegerLiteral
literal: 1
parameter: self::@extension::E::@method::[]::@parameter::index
staticType: int
rightBracket: ]
staticElement: self::@extension::E::@method::[]
staticType: bool
''');
}

test_read_ofExtension_augmentation() async {
newFile('$testPackageLibPath/a.dart', r'''
augment library 'test.dart';
augment extension E {
bool operator[](int index) => false;
}
''');

await assertNoErrorsInCode(r'''
import augment 'a.dart';
extension E on int {}
void f() {
0[1];
}
''');

var indexExpression = findNode.singleIndexExpression;
assertResolvedNodeText(indexExpression, r'''
IndexExpression
target: IntegerLiteral
literal: 0
staticType: int
leftBracket: [
index: IntegerLiteral
literal: 1
parameter: self::@augmentation::package:test/a.dart::@extensionAugmentation::E::@method::[]::@parameter::index
staticType: int
rightBracket: ]
staticElement: self::@augmentation::package:test/a.dart::@extensionAugmentation::E::@method::[]
staticType: bool
''');
}

test_read_switchExpression() async {
await assertNoErrorsInCode(r'''
class A {
Expand Down Expand Up @@ -826,6 +890,94 @@ AssignmentExpression
''');
}

test_write_ofExtension() async {
await assertNoErrorsInCode(r'''
extension E on int {
operator[]=(int index, num value) {}
}
void f() {
0[1] = 2.3;
}
''');

var indexExpression = findNode.singleAssignmentExpression;
assertResolvedNodeText(indexExpression, r'''
AssignmentExpression
leftHandSide: IndexExpression
target: IntegerLiteral
literal: 0
staticType: int
leftBracket: [
index: IntegerLiteral
literal: 1
parameter: self::@extension::E::@method::[]=::@parameter::index
staticType: int
rightBracket: ]
staticElement: <null>
staticType: null
operator: =
rightHandSide: DoubleLiteral
literal: 2.3
parameter: self::@extension::E::@method::[]=::@parameter::value
staticType: double
readElement: <null>
readType: null
writeElement: self::@extension::E::@method::[]=
writeType: num
staticElement: <null>
staticType: double
''');
}

test_write_ofExtension_augmentation() async {
newFile('$testPackageLibPath/a.dart', r'''
augment library 'test.dart';
augment extension E {
operator[]=(int index, num value) {}
}
''');

await assertNoErrorsInCode(r'''
import augment 'a.dart';
extension E on int {}
void f() {
0[1] = 2.3;
}
''');

var indexExpression = findNode.singleAssignmentExpression;
assertResolvedNodeText(indexExpression, r'''
AssignmentExpression
leftHandSide: IndexExpression
target: IntegerLiteral
literal: 0
staticType: int
leftBracket: [
index: IntegerLiteral
literal: 1
parameter: self::@augmentation::package:test/a.dart::@extensionAugmentation::E::@method::[]=::@parameter::index
staticType: int
rightBracket: ]
staticElement: <null>
staticType: null
operator: =
rightHandSide: DoubleLiteral
literal: 2.3
parameter: self::@augmentation::package:test/a.dart::@extensionAugmentation::E::@method::[]=::@parameter::value
staticType: double
readElement: <null>
readType: null
writeElement: self::@augmentation::package:test/a.dart::@extensionAugmentation::E::@method::[]=
writeType: num
staticElement: <null>
staticType: double
''');
}

test_write_switchExpression() async {
await assertNoErrorsInCode(r'''
class A {
Expand Down
101 changes: 101 additions & 0 deletions pkg/analyzer/test/src/dart/resolution/library_element_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:collection/collection.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../../../util/element_printer.dart';
import '../../../util/tree_string_sink.dart';
import 'context_collection_resolution.dart';

main() {
Expand Down Expand Up @@ -206,6 +212,76 @@ extension on int {}
);
}

test_lookup_extensions_imported() async {
newFile('$testPackageLibPath/a.dart', r'''
extension E on int {}
''');

await assertErrorsInCode(r'''
import 'a.dart';
''', [
error(WarningCode.UNUSED_IMPORT, 7, 8),
]);

_assertLibraryExtensions(result.libraryElement, r'''
extensions
package:test/a.dart::@extension::E
dart:core::@extension::EnumName
''');
}

test_lookup_extensions_imported_withPrefix() async {
newFile('$testPackageLibPath/a.dart', r'''
extension E on int {}
''');

await assertErrorsInCode(r'''
import 'a.dart' as prefix;
''', [
error(WarningCode.UNUSED_IMPORT, 7, 8),
]);

_assertLibraryExtensions(result.libraryElement, r'''
extensions
package:test/a.dart::@extension::E
dart:core::@extension::EnumName
''');
}

test_lookup_extensions_local() async {
await assertNoErrorsInCode(r'''
extension E on int {}
''');

_assertLibraryExtensions(result.libraryElement, r'''
extensions
self::@extension::E
dart:core::@extension::EnumName
''');
}

test_lookup_extensions_local_withAugmentation() async {
newFile('$testPackageLibPath/a.dart', r'''
augment library 'test.dart';
augment extension E {
void foo() {}
}
''');

await assertNoErrorsInCode(r'''
import augment 'a.dart';
extension E on int {}
''');

_assertLibraryExtensions(result.libraryElement, r'''
extensions
self::@extension::E
dart:core::@extension::EnumName
''');
}

test_lookup_implicitCoreImport() async {
await assertNoErrorsInCode('');

Expand Down Expand Up @@ -306,6 +382,31 @@ import 'dart:math' show sin;
scope.lookup('cos').getter,
);
}

void _assertLibraryExtensions(LibraryElement library, String expected) {
library as LibraryElementImpl;

var buffer = StringBuffer();
var sink = TreeStringSink(sink: buffer, indent: '');
var elementPrinter = ElementPrinter(
sink: sink,
configuration: ElementPrinterConfiguration(),
selfUriStr: result.uri.toString(),
);

var extensions = library.scope.extensions;
extensions = extensions.sortedBy((e) => e.name ?? '');
elementPrinter.writeElementList('extensions', extensions);

var actual = buffer.toString();
if (actual != expected) {
fail('''
\r${'-' * 28} Actual ${'-' * 28}
\r${actual.trimRight().split('\n').join('\n\r')}
\r${'-' * 64}
''');
}
}
}

@reflectiveTest
Expand Down

0 comments on commit 299ddd0

Please sign in to comment.