Skip to content

Commit

Permalink
[cfe] Handle extension type declarations with dot shorthands.
Browse files Browse the repository at this point in the history
This CL adds the work needed to be able to use dot shorthands with extension types.

Also, there's some additional work to set `isSetter` to false for dot shorthands. Static setters don't work together with shorthands.

Bug: #59758
Change-Id: I2c14606cf2970ee249f48189c686ea5cb963df0b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/412784
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Kallen Tu <kallentu@google.com>
  • Loading branch information
kallentu authored and Commit Queue committed Feb 28, 2025
1 parent f042e6e commit 41abb29
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 9 deletions.
12 changes: 12 additions & 0 deletions pkg/front_end/lib/src/kernel/hierarchy/extension_type_members.dart
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,18 @@ class ExtensionTypeMembersNode {
}
return result;
}

ClassMember? getStaticMember(Name name, bool isSetter) {
ClassMember? result = isSetter
? (extensionTypeSetableMap?[name] ?? nonExtensionTypeSetableMap?[name])
: (extensionTypeGetableMap?[name] ?? nonExtensionTypeGetableMap?[name]);
if (result == null) {
return null;
} else if (result.isStatic) {
return result;
}
return null;
}
}

class _Tuple {
Expand Down
7 changes: 7 additions & 0 deletions pkg/front_end/lib/src/kernel/hierarchy/members_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,13 @@ class ClassMembersBuilder implements ClassHierarchyMembers {
.getMember(name, setter);
}

ClassMember? getExtensionTypeStaticClassMember(
ExtensionTypeDeclaration extensionTypeDeclaration, Name name,
{bool setter = false}) {
return getNodeFromExtensionTypeDeclaration(extensionTypeDeclaration)
.getStaticMember(name, setter);
}

@override
Member? getDispatchTarget(Class cls, Name name, {bool setter = false}) {
return getNodeFromClass(cls)
Expand Down
3 changes: 2 additions & 1 deletion pkg/front_end/lib/src/kernel/hierarchy/members_node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1189,7 +1189,8 @@ class ClassMembersNode {
}

ClassMember? getStaticMember(Name name, bool isSetter) {
ClassMember? result = classMemberMap[name];
ClassMember? result =
isSetter ? classSetterMap[name] : classMemberMap[name];
if (result == null) {
return null;
} else if (result.isStatic) {
Expand Down
4 changes: 1 addition & 3 deletions pkg/front_end/lib/src/type_inference/inference_visitor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12120,9 +12120,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
DartType cachedContext = getDotShorthandContext().unwrapTypeSchemaView();
Member? member = findInterfaceMember(
cachedContext, node.name, node.fileOffset,
includeExtensionMethods: false,
isSetter: false,
isDotShorthand: true)
isSetter: false, isDotShorthand: true)
.member;

ExpressionInferenceResult expressionInferenceResult;
Expand Down
28 changes: 23 additions & 5 deletions pkg/front_end/lib/src/type_inference/inference_visitor_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -968,9 +968,14 @@ abstract class InferenceVisitorBase implements InferenceVisitor {

ObjectAccessTarget? _findExtensionTypeMember(DartType receiverType,
ExtensionType extensionType, Name name, int fileOffset,
{required bool isSetter, required bool hasNonObjectMemberAccess}) {
ClassMember? classMember = _getExtensionTypeMember(
extensionType.extensionTypeDeclaration, name, isSetter);
{required bool isSetter,
required bool hasNonObjectMemberAccess,
bool isDotShorthand = false}) {
ClassMember? classMember = isDotShorthand
? _getExtensionTypeStaticMember(
extensionType.extensionTypeDeclaration, name, false)
: _getExtensionTypeMember(
extensionType.extensionTypeDeclaration, name, isSetter);
if (classMember == null) {
return null;
}
Expand Down Expand Up @@ -3752,6 +3757,18 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
return member;
}

ClassMember? _getExtensionTypeStaticMember(
ExtensionTypeDeclaration extensionTypeDeclaration,
Name name,
bool setter) {
ClassMember? member = engine.membersBuilder
.getExtensionTypeStaticClassMember(extensionTypeDeclaration, name,
setter: setter);
TypeInferenceEngine.resolveInferenceNode(
member?.getMember(engine.membersBuilder), hierarchyBuilder);
return member;
}

bool _isLoweredSetLiteral(Expression expression) {
if (libraryBuilder.loader.target.backendTarget.supportsSetLiterals) {
return false;
Expand Down Expand Up @@ -4720,15 +4737,16 @@ class _ObjectAccessDescriptor {
ObjectAccessTarget? target = visitor._findExtensionTypeMember(
receiverType, receiverBound, name, fileOffset,
isSetter: isSetter,
hasNonObjectMemberAccess: hasNonObjectMemberAccess);
hasNonObjectMemberAccess: hasNonObjectMemberAccess,
isDotShorthand: isDotShorthand);
if (target != null) {
return target;
}
}

ObjectAccessTarget? target;
Member? interfaceMember = isDotShorthand
? visitor._getStaticMember(classNode, name, isSetter)
? visitor._getStaticMember(classNode, name, false)
: visitor._getInterfaceMember(classNode, name, isSetter);
if (interfaceMember != null) {
target = new ObjectAccessTarget.interfaceMember(
Expand Down
11 changes: 11 additions & 0 deletions pkg/front_end/testcases/dot_shorthands/extension_type.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) 2025, 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.

extension type IntegerExt(int integer) {
static IntegerExt get one => IntegerExt(1);
}

void main() {
IntegerExt c = .one;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
library;
import self as self;
import "dart:core" as core;

extension type IntegerExt(core::int integer) {
abstract extension-type-member representation-field get integer() → core::int;
static get one = get self::IntegerExt|one;
constructor • = self::IntegerExt|constructor#;
constructor tearoff • = self::IntegerExt|constructor#_#new#tearOff;
}
static extension-type-member method IntegerExt|constructor#(core::int integer) → self::IntegerExt% /* erasure=core::int, declared=! */ {
lowered final self::IntegerExt% /* erasure=core::int, declared=! */ #this = integer;
return #this;
}
static extension-type-member method IntegerExt|constructor#_#new#tearOff(core::int integer) → self::IntegerExt% /* erasure=core::int, declared=! */
return self::IntegerExt|constructor#(integer);
static extension-type-member get IntegerExt|one() → self::IntegerExt% /* erasure=core::int, declared=! */
return self::IntegerExt|constructor#(1);
static method main() → void {
self::IntegerExt% /* erasure=core::int, declared=! */ c = self::IntegerExt|one;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
library;
import self as self;
import "dart:core" as core;

extension type IntegerExt(core::int integer) {
abstract extension-type-member representation-field get integer() → core::int;
static get one = get self::IntegerExt|one;
constructor • = self::IntegerExt|constructor#;
constructor tearoff • = self::IntegerExt|constructor#_#new#tearOff;
}
static extension-type-member method IntegerExt|constructor#(core::int integer) → self::IntegerExt% /* erasure=core::int, declared=! */ {
lowered final self::IntegerExt% /* erasure=core::int, declared=! */ #this = integer;
return #this;
}
static extension-type-member method IntegerExt|constructor#_#new#tearOff(core::int integer) → self::IntegerExt% /* erasure=core::int, declared=! */
return self::IntegerExt|constructor#(integer);
static extension-type-member get IntegerExt|one() → self::IntegerExt% /* erasure=core::int, declared=! */
return self::IntegerExt|constructor#(1);
static method main() → void {
self::IntegerExt% /* erasure=core::int, declared=! */ c = self::IntegerExt|one;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
library;
import self as self;
import "dart:core" as core;

extension type IntegerExt(core::int integer) {
abstract extension-type-member representation-field get integer() → core::int;
static get one = get self::IntegerExt|one;
constructor • = self::IntegerExt|constructor#;
constructor tearoff • = self::IntegerExt|constructor#_#new#tearOff;
}
static extension-type-member method IntegerExt|constructor#(core::int integer) → self::IntegerExt% /* erasure=core::int, declared=! */
;
static extension-type-member method IntegerExt|constructor#_#new#tearOff(core::int integer) → self::IntegerExt% /* erasure=core::int, declared=! */
return self::IntegerExt|constructor#(integer);
static extension-type-member get IntegerExt|one() → self::IntegerExt% /* erasure=core::int, declared=! */
;
static method main() → void
;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
library;
import self as self;
import "dart:core" as core;

extension type IntegerExt(core::int integer) {
abstract extension-type-member representation-field get integer() → core::int;
static get one = get self::IntegerExt|one;
constructor • = self::IntegerExt|constructor#;
constructor tearoff • = self::IntegerExt|constructor#_#new#tearOff;
}
static extension-type-member method IntegerExt|constructor#(core::int integer) → self::IntegerExt% /* erasure=core::int, declared=! */ {
lowered final self::IntegerExt% /* erasure=core::int, declared=! */ #this = integer;
return #this;
}
static extension-type-member method IntegerExt|constructor#_#new#tearOff(core::int integer) → self::IntegerExt% /* erasure=core::int, declared=! */
return self::IntegerExt|constructor#(integer);
static extension-type-member get IntegerExt|one() → self::IntegerExt% /* erasure=core::int, declared=! */
return self::IntegerExt|constructor#(1);
static method main() → void {
self::IntegerExt% /* erasure=core::int, declared=! */ c = self::IntegerExt|one;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
extension type IntegerExt(int integer) {
static IntegerExt get one => IntegerExt(1);
}

void main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
extension type IntegerExt(int integer) {
static IntegerExt get one => IntegerExt(1);
}

void main() {}

0 comments on commit 41abb29

Please sign in to comment.