Skip to content

Commit

Permalink
Version 3.0.0-28.0.dev
Browse files Browse the repository at this point in the history
Merge ce99386 into dev
  • Loading branch information
Dart CI committed Dec 14, 2022
2 parents 9d208a1 + ce99386 commit 1dd5b1b
Show file tree
Hide file tree
Showing 339 changed files with 4,593 additions and 3,372 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ class ForwardingListener implements Listener {
Token? inlineToken,
Token? sealedToken,
Token? augmentToken,
Token? mixinToken,
Token name) {
listener?.beginClassDeclaration(begin, abstractToken, macroToken,
inlineToken, sealedToken, augmentToken, name);
inlineToken, sealedToken, augmentToken, mixinToken, name);
}

@override
Expand Down Expand Up @@ -404,9 +405,10 @@ class ForwardingListener implements Listener {
Token? inlineToken,
Token? sealedToken,
Token? augmentToken,
Token? mixinToken,
Token name) {
listener?.beginNamedMixinApplication(begin, abstractToken, macroToken,
inlineToken, sealedToken, augmentToken, name);
inlineToken, sealedToken, augmentToken, mixinToken, name);
}

@override
Expand Down
2 changes: 2 additions & 0 deletions pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ class Listener implements UnescapeErrorListener {
Token? inlineToken,
Token? sealedToken,
Token? augmentToken,
Token? mixinToken,
Token name) {}

/// Handle an extends clause in a class declaration. Substructures:
Expand Down Expand Up @@ -785,6 +786,7 @@ class Listener implements UnescapeErrorListener {
Token? inlineToken,
Token? sealedToken,
Token? augmentToken,
Token? mixinToken,
Token name) {}

/// Handle a named mixin application with clause (e.g. "A with B, C").
Expand Down
39 changes: 30 additions & 9 deletions pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -619,13 +619,8 @@ class Parser {
assert(keyword.isTopLevelKeyword);
final String? value = keyword.stringValue;
if (identical(value, 'class')) {
directiveState?.checkDeclaration();
ModifierContext context = new ModifierContext(this);
context.parseClassModifiers(start, keyword);
Token? abstractToken = context.abstractToken;
Token? augmentToken = context.augmentToken;
return parseClassOrNamedMixinApplication(abstractToken, macroToken,
inlineToken, sealedToken, augmentToken, keyword);
return _handleModifiersForClassDeclaration(start, keyword, macroToken,
inlineToken, sealedToken, null, directiveState);
} else if (identical(value, 'enum')) {
directiveState?.checkDeclaration();
ModifierContext context = new ModifierContext(this);
Expand Down Expand Up @@ -683,6 +678,10 @@ class Parser {
directiveState?.checkDeclaration();
return parseTypedef(keyword);
} else if (identical(value, 'mixin')) {
if (identical(nextValue, 'class')) {
return _handleModifiersForClassDeclaration(start, keyword.next!,
macroToken, inlineToken, sealedToken, keyword, directiveState);
}
context.parseMixinModifiers(start, keyword);
directiveState?.checkDeclaration();
return parseMixin(context.augmentToken, sealedToken, keyword);
Expand Down Expand Up @@ -710,6 +709,27 @@ class Parser {
throw "Internal error: Unhandled top level keyword '$value'.";
}

Token _handleModifiersForClassDeclaration(
Token start,
Token classKeyword,
Token? macroToken,
Token? inlineToken,
Token? sealedToken,
Token? mixinToken,
DirectiveContext? directiveState) {
directiveState?.checkDeclaration();
ModifierContext context = new ModifierContext(this);
if (mixinToken != null) {
context.parseClassModifiers(start, mixinToken);
} else {
context.parseClassModifiers(start, classKeyword);
}
Token? abstractToken = context.abstractToken;
Token? augmentToken = context.augmentToken;
return parseClassOrNamedMixinApplication(abstractToken, macroToken,
inlineToken, sealedToken, augmentToken, mixinToken, classKeyword);
}

bool _isIdentifierOrQuestionIdentifier(Token token) {
if (token.isIdentifier) return true;
if (optional("?", token)) {
Expand Down Expand Up @@ -2467,6 +2487,7 @@ class Parser {
Token? inlineToken,
Token? sealedToken,
Token? augmentToken,
Token? mixinToken,
Token classKeyword) {
assert(optional('class', classKeyword));
Token begin = abstractToken ?? classKeyword;
Expand All @@ -2481,11 +2502,11 @@ class Parser {
}
if (optional('=', token.next!)) {
listener.beginNamedMixinApplication(begin, abstractToken, macroToken,
inlineToken, sealedToken, augmentToken, name);
inlineToken, sealedToken, augmentToken, mixinToken, name);
return parseNamedMixinApplication(token, begin, classKeyword);
} else {
listener.beginClassDeclaration(begin, abstractToken, macroToken,
inlineToken, sealedToken, augmentToken, name);
inlineToken, sealedToken, augmentToken, mixinToken, name);
return parseClass(token, begin, classKeyword, name.lexeme);
}
}
Expand Down
24 changes: 19 additions & 5 deletions pkg/_fe_analyzer_shared/lib/src/type_inference/type_analyzer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1152,17 +1152,19 @@ mixin TypeAnalyzer<
return recordType(positional: positional, named: named);
}

/// Analyzes a relational pattern. [node] is the pattern itself, [operator]
/// is the resolution of the used relational operator, and [operand] is a
/// constant expression.
/// Analyzes a relational pattern. [node] is the pattern itself, and
/// [operand] is a constant expression that will be passed to the relational
/// operator.
///
/// This method will invoke [resolveRelationalPatternOperator] to obtain
/// information about the operator.
///
/// See [dispatchPattern] for the meaning of [context].
///
/// Stack effect: pushes (Expression).
void analyzeRelationalPattern(
MatchContext<Node, Expression, Pattern, Type, Variable> context,
Node node,
RelationalOperatorResolution<Type>? operator,
Pattern node,
Expression operand) {
// Stack: ()
TypeAnalyzerErrors<Node, Node, Expression, Variable, Type, Pattern>?
Expand All @@ -1171,6 +1173,9 @@ mixin TypeAnalyzer<
if (irrefutableContext != null) {
errors?.refutablePatternInIrrefutableContext(node, irrefutableContext);
}
Type matchedValueType = flow.getMatchedValueType();
RelationalOperatorResolution<Type>? operator =
resolveRelationalPatternOperator(node, matchedValueType);
Type operandContext = operator?.parameterType ?? unknownType;
Type operandType = analyzeExpression(operand, operandContext);
// Stack: (Expression)
Expand Down Expand Up @@ -1669,6 +1674,15 @@ mixin TypeAnalyzer<
required RecordPatternField<Node, Pattern> field,
});

/// Resolves the relational operator for [node] assuming that the value being
/// matched has static type [matchedValueType].
///
/// If no operator is found, `null` should be returned. (This could happen
/// either because the code is invalid, or because [matchedValueType] is
/// `dynamic`).
RelationalOperatorResolution<Type>? resolveRelationalPatternOperator(
Pattern node, Type matchedValueType);

/// Records that type inference has assigned a [type] to a [variable]. This
/// is called once per variable, regardless of whether the variable's type is
/// explicit or inferred.
Expand Down
104 changes: 81 additions & 23 deletions pkg/_fe_analyzer_shared/test/mini_ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,7 @@ Pattern objectPattern({
Pattern recordPattern(List<RecordPatternField> fields) =>
_RecordPattern(fields, location: computeLocation());

Pattern relationalPattern(
RelationalOperatorResolution<Type>? operator, Expression operand,
Pattern relationalPattern(String operator, Expression operand,
{String? errorId}) {
var result =
_RelationalPattern(operator, operand, location: computeLocation());
Expand Down Expand Up @@ -566,6 +565,11 @@ class GuardedPattern extends Node with PossiblyGuardedPattern {
}

class Harness {
static Map<String, Type> _coreMemberTypes = {
'int.>': Type('bool Function(num)'),
'int.>=': Type('bool Function(num)'),
};

final MiniAstOperations _operations = MiniAstOperations();

bool _started = false;
Expand All @@ -576,7 +580,10 @@ class Harness {

Type? _thisType;

final Map<String, _PropertyElement> _members = {};
late final Map<String, _PropertyElement?> _members = {
for (var entry in _coreMemberTypes.entries)
entry.key: _PropertyElement(entry.value)
};

late final typeAnalyzer = _MiniAstTypeAnalyzer(
this,
Expand Down Expand Up @@ -642,9 +649,21 @@ class Harness {

/// Updates the harness so that when member [memberName] is looked up on type
/// [targetType], a member is found having the given [type].
void addMember(String targetType, String memberName, String type,
///
/// If [type] is `null`, then an attempt to look up [memberName] on type
/// [targetType] should result in `null` (no such member) rather than a test
/// failure.
void addMember(String targetType, String memberName, String? type,
{bool promotable = false}) {
var query = '$targetType.$memberName';
if (type == null) {
if (promotable) {
fail("It doesn't make sense to specify `promotable: true` "
"when the type is `null`");
}
_members[query] = null;
return;
}
var member = _PropertyElement(Type(type));
_members[query] = member;
if (promotable) {
Expand All @@ -663,11 +682,44 @@ class Harness {
}

/// Attempts to look up a member named [memberName] in the given [type]. If
/// a member is found, returns its [_PropertyElement] object. Otherwise the
/// test fails.
_PropertyElement getMember(Type type, String memberName) {
/// a member is found, returns its [_PropertyElement] object; otherwise `null`
/// is returned.
///
/// If test hasn't been configured in such a way that the result of the query
/// is known, the test fails.
_PropertyElement? getMember(Type type, String memberName) {
var query = '$type.$memberName';
return _members[query] ?? fail('Unknown member query: $query');
var member = _members[query];
if (member == null && !_members.containsKey(query)) {
fail('Unknown member query: $query');
}
return member;
}

/// See [TypeAnalyzer.resolveRelationalPatternOperator].
RelationalOperatorResolution<Type>? resolveRelationalPatternOperator(
Type matchedValueType, String operator) {
if (operator == '==' || operator == '!=') {
return RelationalOperatorResolution(
isEquality: true,
parameterType: Type('Object'),
returnType: Type('bool'));
}
var member = getMember(matchedValueType, operator);
if (member == null) return null;
var memberType = member._type;
if (memberType is! FunctionType) {
fail('$matchedValueType.operator$operator has type $memberType; '
'must be a function type');
}
if (memberType.positionalParameters.isEmpty) {
fail('$matchedValueType.operator$operator has type $memberType; '
'must accept a parameter');
}
return RelationalOperatorResolution(
isEquality: operator == '==' || operator == '!=',
parameterType: memberType.positionalParameters[0],
returnType: memberType.returnType);
}

/// Runs the given [statements] through flow analysis, checking any assertions
Expand Down Expand Up @@ -3284,11 +3336,11 @@ class _MiniAstTypeAnalyzer
Expression node, Expression receiver, String propertyName) {
var receiverType = analyzeExpression(receiver, unknownType);
var member = _lookupMember(node, receiverType, propertyName);
var memberType = member?._type ?? dynamicType;
var promotedType =
flow.propertyGet(node, receiver, propertyName, member, member._type);
flow.propertyGet(node, receiver, propertyName, member, memberType);
// TODO(paulberry): handle null shorting
return new SimpleTypeAnalysisResult<Type>(
type: promotedType ?? member._type);
return new SimpleTypeAnalysisResult<Type>(type: promotedType ?? memberType);
}

void analyzeReturnStatement() {
Expand All @@ -3304,10 +3356,10 @@ class _MiniAstTypeAnalyzer
SimpleTypeAnalysisResult<Type> analyzeThisPropertyGet(
Expression node, String propertyName) {
var member = _lookupMember(node, thisType, propertyName);
var memberType = member?._type ?? dynamicType;
var promotedType =
flow.thisOrSuperPropertyGet(node, propertyName, member, member._type);
return new SimpleTypeAnalysisResult<Type>(
type: promotedType ?? member._type);
flow.thisOrSuperPropertyGet(node, propertyName, member, memberType);
return new SimpleTypeAnalysisResult<Type>(type: promotedType ?? memberType);
}

SimpleTypeAnalysisResult<Type> analyzeThrow(
Expand Down Expand Up @@ -3719,7 +3771,7 @@ class _MiniAstTypeAnalyzer
@override
Type listType(Type elementType) => PrimaryType('List', args: [elementType]);

_PropertyElement lookupInterfaceMember(
_PropertyElement? lookupInterfaceMember(
Node node, Type receiverType, String memberName) {
return _harness.getMember(receiverType, memberName);
}
Expand Down Expand Up @@ -3747,7 +3799,14 @@ class _MiniAstTypeAnalyzer
required Type receiverType,
required shared.RecordPatternField<Node, Pattern> field,
}) {
return _harness.getMember(receiverType, field.name!)._type;
return _harness.getMember(receiverType, field.name!)?._type ?? dynamicType;
}

@override
RelationalOperatorResolution<Type>? resolveRelationalPatternOperator(
covariant _RelationalPattern node, Type matchedValueType) {
return _harness.resolveRelationalPatternOperator(
matchedValueType, node.operator);
}

@override
Expand All @@ -3774,7 +3833,7 @@ class _MiniAstTypeAnalyzer
return type.recursivelyDemote(covariant: true) ?? type;
}

_PropertyElement _lookupMember(
_PropertyElement? _lookupMember(
Expression node, Type receiverType, String memberName) {
return lookupInterfaceMember(node, receiverType, memberName);
}
Expand Down Expand Up @@ -4055,7 +4114,7 @@ class _Property extends PromotableLValue {
h.typeAnalyzer.analyzeExpression(target, h.typeAnalyzer.unknownType);
var member = h.typeAnalyzer._lookupMember(this, receiverType, propertyName);
return h.flow
.promotedPropertyType(target, propertyName, member, member._type);
.promotedPropertyType(target, propertyName, member, member!._type);
}

@override
Expand Down Expand Up @@ -4122,7 +4181,7 @@ class _RecordPattern extends Pattern {
}

class _RelationalPattern extends Pattern {
final RelationalOperatorResolution<Type>? operator;
final String operator;
final Expression operand;

_RelationalPattern(this.operator, this.operand, {required super.location})
Expand All @@ -4141,10 +4200,9 @@ class _RelationalPattern extends Pattern {
@override
void visit(Harness h, SharedMatchContext context) {
var matchedType = h.typeAnalyzer.flow.getMatchedValueType();
h.typeAnalyzer.analyzeRelationalPattern(context, this, operator, operand);
h.typeAnalyzer.analyzeRelationalPattern(context, this, operand);
h.irBuilder.atom(matchedType.type, Kind.type, location: location);
h.irBuilder.apply(
'relationalPattern', [Kind.expression, Kind.type], Kind.pattern,
h.irBuilder.apply(operator, [Kind.expression, Kind.type], Kind.pattern,
names: ['matchedType'], location: location);
}

Expand Down Expand Up @@ -4413,7 +4471,7 @@ class _ThisOrSuperProperty extends PromotableLValue {
h.irBuilder.atom('this.$propertyName', Kind.expression, location: location);
var member = h.typeAnalyzer._lookupMember(this, h._thisType!, propertyName);
return h.flow
.promotedPropertyType(null, propertyName, member, member._type);
.promotedPropertyType(null, propertyName, member, member!._type);
}

@override
Expand Down
Loading

0 comments on commit 1dd5b1b

Please sign in to comment.