diff --git a/pkg/front_end/lib/src/kernel/body_builder.dart b/pkg/front_end/lib/src/kernel/body_builder.dart index 23b3769154f..e0f6e990cf0 100644 --- a/pkg/front_end/lib/src/kernel/body_builder.dart +++ b/pkg/front_end/lib/src/kernel/body_builder.dart @@ -10016,10 +10016,15 @@ class BodyBuilder extends StackListenerImpl assert(checkState(token, [ValueKinds.Selector])); Selector selector = pop() as Selector; if (libraryFeatures.dotShorthands.isEnabled) { - // TODO(kallentu): Handle invocations. - - push(forest.createDotShorthandPropertyGet( - offsetForToken(token), selector.name)); + if (selector is InvocationSelector) { + // e.g. `.parse(2)` + push(forest.createDotShorthandInvocation( + offsetForToken(token), selector.name, selector.arguments)); + } else if (selector is PropertySelector) { + // e.g. `.zero` + push(forest.createDotShorthandPropertyGet( + offsetForToken(token), selector.name)); + } } } } diff --git a/pkg/front_end/lib/src/kernel/forest.dart b/pkg/front_end/lib/src/kernel/forest.dart index da00ea784fe..4c92229b9bd 100644 --- a/pkg/front_end/lib/src/kernel/forest.dart +++ b/pkg/front_end/lib/src/kernel/forest.dart @@ -933,6 +933,11 @@ class Forest { return new DotShorthand(innerExpression)..fileOffset = fileOffset; } + DotShorthandInvocation createDotShorthandInvocation( + int fileOffset, Name name, Arguments arguments) { + return new DotShorthandInvocation(name, arguments)..fileOffset = fileOffset; + } + DotShorthandPropertyGet createDotShorthandPropertyGet( int fileOffset, Name name) { return new DotShorthandPropertyGet(name)..fileOffset = fileOffset; diff --git a/pkg/front_end/lib/src/kernel/internal_ast.dart b/pkg/front_end/lib/src/kernel/internal_ast.dart index b6d2012e8f4..db71ecf1dea 100644 --- a/pkg/front_end/lib/src/kernel/internal_ast.dart +++ b/pkg/front_end/lib/src/kernel/internal_ast.dart @@ -3248,6 +3248,38 @@ class DotShorthand extends InternalExpression { } } +/// Internal expression for a dot shorthand head with arguments. +/// (e.g. `.parse(42)`). +/// +/// This node could represent a shorthand of a static method or a named +/// constructor. +class DotShorthandInvocation extends InternalExpression { + Name name; + + Arguments arguments; + + DotShorthandInvocation(this.name, this.arguments); + + @override + ExpressionInferenceResult acceptInference( + InferenceVisitorImpl visitor, DartType typeContext) { + return visitor.visitDotShorthandInvocation(this, typeContext); + } + + @override + String toString() { + return "DotShorthandInvocation(${toStringInternal()})"; + } + + @override + // Coverage-ignore(suite): Not run. + void toTextInternal(AstPrinter printer) { + printer.write('.'); + printer.writeName(name); + printer.writeArguments(arguments); + } +} + /// Internal expression for a dot shorthand head with no arguments. /// (e.g. `.zero`). /// diff --git a/pkg/front_end/lib/src/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/type_inference/inference_visitor.dart index 784e75eaf1b..4202ef2855c 100644 --- a/pkg/front_end/lib/src/type_inference/inference_visitor.dart +++ b/pkg/front_end/lib/src/type_inference/inference_visitor.dart @@ -30,7 +30,7 @@ import '../base/instrumentation.dart' InstrumentationValueForType, InstrumentationValueForTypeArgs; import '../base/problems.dart' as problems - show internalProblem, unhandled, unsupported; + show internalProblem, unhandled, unsupported, unimplemented; import '../base/uri_offset.dart'; import '../codes/cfe_codes.dart'; import '../kernel/body_builder.dart' show combineStatements; @@ -12111,6 +12111,63 @@ class InferenceVisitorImpl extends InferenceVisitorBase return new ExpressionInferenceResult(rewrittenType, rewrittenExpr); } + ExpressionInferenceResult visitDotShorthandInvocation( + DotShorthandInvocation node, DartType typeContext) { + // Use the previously cached context type to determine the declaration + // member that we're trying to find. + DartType cachedContext = getDotShorthandContext().unwrapTypeSchemaView(); + Member? member = findInterfaceMember( + cachedContext, node.name, node.fileOffset, + includeExtensionMethods: false, + isSetter: false, + isDotShorthand: true) + .member; + + Expression expr; + if (member is Procedure) { + expr = new StaticInvocation(member, node.arguments) + ..fileOffset = node.fileOffset; + } else if (member == null && cachedContext is TypeDeclarationType) { + // Couldn't find a static method in the declaration so we'll try and find + // a constructor of that name instead. + Member? constructor = + findConstructor(cachedContext, node.name, node.fileOffset); + if (constructor is Constructor) { + // TODO(kallentu): Const constructors. + expr = new ConstructorInvocation(constructor, node.arguments, + isConst: false) + ..fileOffset = node.fileOffset; + } else if (constructor is Procedure) { + // [constructor] can be a [Procedure] if we have an extension type + // constructor. + expr = new StaticInvocation(constructor, node.arguments) + ..fileOffset = node.fileOffset; + } else { + // Coverage-ignore-block(suite): Not run. + // TODO(kallentu): This is temporary. Build a problem with an error + // specific to not being able to find a member named [node.name]. + problems.unimplemented( + 'Cannot find dot shorthand member of name ${node.name}', + node.fileOffset, + helper.uri); + } + } else { + // Coverage-ignore-block(suite): Not run. + // TODO(kallentu): This is temporary. Build a problem with an error on the + // bad context type. + problems.unimplemented( + 'Cannot find dot shorthand member of name ${node.name} with ' + 'context $cachedContext', + node.fileOffset, + helper.uri); + } + + ExpressionInferenceResult expressionInferenceResult = + inferExpression(expr, cachedContext); + flowAnalysis.forwardExpression(expressionInferenceResult.expression, node); + return expressionInferenceResult; + } + ExpressionInferenceResult visitDotShorthandPropertyGet( DotShorthandPropertyGet node, DartType typeContext) { // Use the previously cached context type to determine the declaration @@ -12123,9 +12180,13 @@ class InferenceVisitorImpl extends InferenceVisitorBase ExpressionInferenceResult expressionInferenceResult; if (member == null) { + // Coverage-ignore-block(suite): Not run. // TODO(kallentu): This is temporary. Build a problem with an error // specific to not being able to find a member named [node.name]. - throw 'Error: Cannot find dot shorthand member.'; + problems.unimplemented( + 'Cannot find dot shorthand member of name ${node.name}', + node.fileOffset, + helper.uri); } else if (member is Procedure && !member.isGetter) { // Tearoff like `Object.new`; expressionInferenceResult = diff --git a/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart b/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart index f17efc12f51..f2951e935ea 100644 --- a/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart +++ b/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart @@ -1169,6 +1169,28 @@ abstract class InferenceVisitorBase implements InferenceVisitor { return defaultTarget; } + /// Finds a constructor of [type] called [name]. + Member? findConstructor(TypeDeclarationType type, Name name, int fileOffset) { + assert(isKnown(type)); + + // TODO(Dart Model team): Seems like an abstraction level issue to require + // going from `Class` objects back to builders to find a `Member`. + DeclarationBuilder builder; + switch (type) { + case InterfaceType(): + builder = engine.hierarchyBuilder.loader + .computeClassBuilderFromTargetClass(type.classNode); + case ExtensionType(): + builder = engine.hierarchyBuilder.loader + .computeExtensionTypeBuilderFromTargetExtensionType( + type.extensionTypeDeclaration); + } + + MemberBuilder? constructorBuilder = builder.findConstructorOrFactory( + name.text, fileOffset, helper.uri, libraryBuilder); + return constructorBuilder?.invokeTarget; + } + /// Finds a member of [receiverType] called [name], and if it is found, /// reports it through instrumentation using [fileOffset]. /// diff --git a/pkg/front_end/test/coverage_suite_expected.dart b/pkg/front_end/test/coverage_suite_expected.dart index ec1472a5dbb..ebef4242486 100644 --- a/pkg/front_end/test/coverage_suite_expected.dart +++ b/pkg/front_end/test/coverage_suite_expected.dart @@ -590,7 +590,7 @@ const Map _expect = { ), // 100.0%. "package:front_end/src/kernel/body_builder.dart": ( - hitCount: 7205, + hitCount: 7213, missCount: 0, ), // 100.0%. @@ -660,7 +660,7 @@ const Map _expect = { ), // 100.0%. "package:front_end/src/kernel/forest.dart": ( - hitCount: 402, + hitCount: 405, missCount: 0, ), // 100.0%. @@ -720,7 +720,7 @@ const Map _expect = { ), // 100.0%. "package:front_end/src/kernel/internal_ast.dart": ( - hitCount: 551, + hitCount: 554, missCount: 0, ), // 100.0%. @@ -976,12 +976,12 @@ const Map _expect = { ), // 100.0%. "package:front_end/src/type_inference/inference_visitor.dart": ( - hitCount: 8178, + hitCount: 8208, missCount: 0, ), // 100.0%. "package:front_end/src/type_inference/inference_visitor_base.dart": ( - hitCount: 2451, + hitCount: 2477, missCount: 0, ), // 100.0%. diff --git a/pkg/front_end/testcases/dot_shorthands/constructor.dart b/pkg/front_end/testcases/dot_shorthands/constructor.dart new file mode 100644 index 00000000000..403c69be864 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/constructor.dart @@ -0,0 +1,13 @@ +// 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. + +class Color { + final int x; + Color.red() : x = 1; + Color(this.x); +} + +void main() { + Color c = .red(); +} diff --git a/pkg/front_end/testcases/dot_shorthands/constructor.dart.strong.expect b/pkg/front_end/testcases/dot_shorthands/constructor.dart.strong.expect new file mode 100644 index 00000000000..67d7482e896 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/constructor.dart.strong.expect @@ -0,0 +1,16 @@ +library; +import self as self; +import "dart:core" as core; + +class Color extends core::Object { + final field core::int x; + constructor red() → self::Color + : self::Color::x = 1, super core::Object::•() + ; + constructor •(core::int x) → self::Color + : self::Color::x = x, super core::Object::•() + ; +} +static method main() → void { + self::Color c = new self::Color::red(); +} diff --git a/pkg/front_end/testcases/dot_shorthands/constructor.dart.strong.modular.expect b/pkg/front_end/testcases/dot_shorthands/constructor.dart.strong.modular.expect new file mode 100644 index 00000000000..67d7482e896 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/constructor.dart.strong.modular.expect @@ -0,0 +1,16 @@ +library; +import self as self; +import "dart:core" as core; + +class Color extends core::Object { + final field core::int x; + constructor red() → self::Color + : self::Color::x = 1, super core::Object::•() + ; + constructor •(core::int x) → self::Color + : self::Color::x = x, super core::Object::•() + ; +} +static method main() → void { + self::Color c = new self::Color::red(); +} diff --git a/pkg/front_end/testcases/dot_shorthands/constructor.dart.strong.outline.expect b/pkg/front_end/testcases/dot_shorthands/constructor.dart.strong.outline.expect new file mode 100644 index 00000000000..d62f2535e60 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/constructor.dart.strong.outline.expect @@ -0,0 +1,13 @@ +library; +import self as self; +import "dart:core" as core; + +class Color extends core::Object { + final field core::int x; + constructor red() → self::Color + ; + constructor •(core::int x) → self::Color + ; +} +static method main() → void + ; diff --git a/pkg/front_end/testcases/dot_shorthands/constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/dot_shorthands/constructor.dart.strong.transformed.expect new file mode 100644 index 00000000000..67d7482e896 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/constructor.dart.strong.transformed.expect @@ -0,0 +1,16 @@ +library; +import self as self; +import "dart:core" as core; + +class Color extends core::Object { + final field core::int x; + constructor red() → self::Color + : self::Color::x = 1, super core::Object::•() + ; + constructor •(core::int x) → self::Color + : self::Color::x = x, super core::Object::•() + ; +} +static method main() → void { + self::Color c = new self::Color::red(); +} diff --git a/pkg/front_end/testcases/dot_shorthands/constructor.dart.textual_outline.expect b/pkg/front_end/testcases/dot_shorthands/constructor.dart.textual_outline.expect new file mode 100644 index 00000000000..fe680f9b33f --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/constructor.dart.textual_outline.expect @@ -0,0 +1,7 @@ +class Color { + final int x; + Color.red() : x = 1; + Color(this.x); +} + +void main() {} diff --git a/pkg/front_end/testcases/dot_shorthands/constructor.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dot_shorthands/constructor.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..38acbc6ee0c --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/constructor.dart.textual_outline_modelled.expect @@ -0,0 +1,7 @@ +class Color { + Color(this.x); + Color.red() : x = 1; + final int x; +} + +void main() {} diff --git a/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart new file mode 100644 index 00000000000..bea8b5c3907 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart @@ -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) { + IntegerExt.regular(this.integer); +} + +void main() { + IntegerExt c = .regular(1); +} diff --git a/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.strong.expect b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.strong.expect new file mode 100644 index 00000000000..7ecc213d2a9 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.strong.expect @@ -0,0 +1,26 @@ +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; + constructor • = self::IntegerExt|constructor#; + constructor tearoff • = self::IntegerExt|constructor#_#new#tearOff; + constructor regular = self::IntegerExt|constructor#regular; + constructor tearoff regular = self::IntegerExt|constructor#_#regular#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 method IntegerExt|constructor#regular(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#_#regular#tearOff(core::int integer) → self::IntegerExt% /* erasure=core::int, declared=! */ + return self::IntegerExt|constructor#regular(integer); +static method main() → void { + self::IntegerExt% /* erasure=core::int, declared=! */ c = self::IntegerExt|constructor#regular(1); +} diff --git a/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.strong.modular.expect b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.strong.modular.expect new file mode 100644 index 00000000000..7ecc213d2a9 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.strong.modular.expect @@ -0,0 +1,26 @@ +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; + constructor • = self::IntegerExt|constructor#; + constructor tearoff • = self::IntegerExt|constructor#_#new#tearOff; + constructor regular = self::IntegerExt|constructor#regular; + constructor tearoff regular = self::IntegerExt|constructor#_#regular#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 method IntegerExt|constructor#regular(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#_#regular#tearOff(core::int integer) → self::IntegerExt% /* erasure=core::int, declared=! */ + return self::IntegerExt|constructor#regular(integer); +static method main() → void { + self::IntegerExt% /* erasure=core::int, declared=! */ c = self::IntegerExt|constructor#regular(1); +} diff --git a/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.strong.outline.expect b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.strong.outline.expect new file mode 100644 index 00000000000..4ed11e379c5 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.strong.outline.expect @@ -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; + constructor • = self::IntegerExt|constructor#; + constructor tearoff • = self::IntegerExt|constructor#_#new#tearOff; + constructor regular = self::IntegerExt|constructor#regular; + constructor tearoff regular = self::IntegerExt|constructor#_#regular#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 method IntegerExt|constructor#regular(core::int integer) → self::IntegerExt% /* erasure=core::int, declared=! */ + ; +static extension-type-member method IntegerExt|constructor#_#regular#tearOff(core::int integer) → self::IntegerExt% /* erasure=core::int, declared=! */ + return self::IntegerExt|constructor#regular(integer); +static method main() → void + ; diff --git a/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.strong.transformed.expect new file mode 100644 index 00000000000..7ecc213d2a9 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.strong.transformed.expect @@ -0,0 +1,26 @@ +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; + constructor • = self::IntegerExt|constructor#; + constructor tearoff • = self::IntegerExt|constructor#_#new#tearOff; + constructor regular = self::IntegerExt|constructor#regular; + constructor tearoff regular = self::IntegerExt|constructor#_#regular#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 method IntegerExt|constructor#regular(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#_#regular#tearOff(core::int integer) → self::IntegerExt% /* erasure=core::int, declared=! */ + return self::IntegerExt|constructor#regular(integer); +static method main() → void { + self::IntegerExt% /* erasure=core::int, declared=! */ c = self::IntegerExt|constructor#regular(1); +} diff --git a/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.textual_outline.expect b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.textual_outline.expect new file mode 100644 index 00000000000..5223b2782ae --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.textual_outline.expect @@ -0,0 +1,5 @@ +extension type IntegerExt(int integer) { + IntegerExt.regular(this.integer); +} + +void main() {} diff --git a/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..5223b2782ae --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/extension_type_constructor.dart.textual_outline_modelled.expect @@ -0,0 +1,5 @@ +extension type IntegerExt(int integer) { + IntegerExt.regular(this.integer); +} + +void main() {} diff --git a/pkg/front_end/testcases/dot_shorthands/static_method.dart b/pkg/front_end/testcases/dot_shorthands/static_method.dart new file mode 100644 index 00000000000..b254782429f --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/static_method.dart @@ -0,0 +1,13 @@ +// 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. + +class Color { + final int x; + static Color red() => Color(1); + Color(this.x); +} + +void main() { + Color c = .red(); +} diff --git a/pkg/front_end/testcases/dot_shorthands/static_method.dart.strong.expect b/pkg/front_end/testcases/dot_shorthands/static_method.dart.strong.expect new file mode 100644 index 00000000000..c39e6d55941 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/static_method.dart.strong.expect @@ -0,0 +1,15 @@ +library; +import self as self; +import "dart:core" as core; + +class Color extends core::Object { + final field core::int x; + constructor •(core::int x) → self::Color + : self::Color::x = x, super core::Object::•() + ; + static method red() → self::Color + return new self::Color::•(1); +} +static method main() → void { + self::Color c = self::Color::red(); +} diff --git a/pkg/front_end/testcases/dot_shorthands/static_method.dart.strong.modular.expect b/pkg/front_end/testcases/dot_shorthands/static_method.dart.strong.modular.expect new file mode 100644 index 00000000000..c39e6d55941 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/static_method.dart.strong.modular.expect @@ -0,0 +1,15 @@ +library; +import self as self; +import "dart:core" as core; + +class Color extends core::Object { + final field core::int x; + constructor •(core::int x) → self::Color + : self::Color::x = x, super core::Object::•() + ; + static method red() → self::Color + return new self::Color::•(1); +} +static method main() → void { + self::Color c = self::Color::red(); +} diff --git a/pkg/front_end/testcases/dot_shorthands/static_method.dart.strong.outline.expect b/pkg/front_end/testcases/dot_shorthands/static_method.dart.strong.outline.expect new file mode 100644 index 00000000000..b8c6d4e3253 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/static_method.dart.strong.outline.expect @@ -0,0 +1,13 @@ +library; +import self as self; +import "dart:core" as core; + +class Color extends core::Object { + final field core::int x; + constructor •(core::int x) → self::Color + ; + static method red() → self::Color + ; +} +static method main() → void + ; diff --git a/pkg/front_end/testcases/dot_shorthands/static_method.dart.strong.transformed.expect b/pkg/front_end/testcases/dot_shorthands/static_method.dart.strong.transformed.expect new file mode 100644 index 00000000000..c39e6d55941 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/static_method.dart.strong.transformed.expect @@ -0,0 +1,15 @@ +library; +import self as self; +import "dart:core" as core; + +class Color extends core::Object { + final field core::int x; + constructor •(core::int x) → self::Color + : self::Color::x = x, super core::Object::•() + ; + static method red() → self::Color + return new self::Color::•(1); +} +static method main() → void { + self::Color c = self::Color::red(); +} diff --git a/pkg/front_end/testcases/dot_shorthands/static_method.dart.textual_outline.expect b/pkg/front_end/testcases/dot_shorthands/static_method.dart.textual_outline.expect new file mode 100644 index 00000000000..b38adf41185 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/static_method.dart.textual_outline.expect @@ -0,0 +1,7 @@ +class Color { + final int x; + static Color red() => Color(1); + Color(this.x); +} + +void main() {} diff --git a/pkg/front_end/testcases/dot_shorthands/static_method.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dot_shorthands/static_method.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..6705aa79199 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/static_method.dart.textual_outline_modelled.expect @@ -0,0 +1,7 @@ +class Color { + Color(this.x); + final int x; + static Color red() => Color(1); +} + +void main() {}