Skip to content

Commit

Permalink
Add a question mark to type annotations in the AST
Browse files Browse the repository at this point in the history
Change-Id: Icb2e6e4a52d91d3ecf3c4e8a44a2d8f2a3d7a204
Reviewed-on: https://dart-review.googlesource.com/c/87167
Reviewed-by: Dan Rubel <[email protected]>
Commit-Queue: Brian Wilkerson <[email protected]>
  • Loading branch information
bwilkerson authored and [email protected] committed Dec 13, 2018
1 parent b1294e7 commit 7a968ae
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 39 deletions.
27 changes: 26 additions & 1 deletion pkg/analyzer/lib/dart/ast/ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3779,7 +3779,8 @@ abstract class FunctionTypedFormalParameter extends NormalFormalParameter {
* An anonymous function type.
*
* functionType ::=
* [TypeAnnotation]? 'Function' [TypeParameterList]? [FormalParameterList]
* [TypeAnnotation]? 'Function' [TypeParameterList]?
* [FormalParameterList] '?'?
*
* where the FormalParameterList is being used to represent the following
* grammar, despite the fact that FormalParameterList can represent a much
Expand Down Expand Up @@ -3828,6 +3829,18 @@ abstract class GenericFunctionType extends TypeAnnotation {
*/
void set parameters(FormalParameterList parameters);

/**
* The question mark indicating that the type is nullable, or `null` if there
* is no question mark.
*/
Token get question;

/**
* Set the question mark indicating that the type is nullable to the given
* [token].
*/
void set question(Token token);

/**
* Return the return type of the function type being defined, or `null` if
* no return type was given.
Expand Down Expand Up @@ -5295,6 +5308,18 @@ abstract class NamedType extends TypeAnnotation {
*/
void set name(Identifier identifier);

/**
* The question mark indicating that the type is nullable, or `null` if there
* is no question mark.
*/
Token get question;

/**
* Set the question mark indicating that the type is nullable to the given
* [token].
*/
void set question(Token token);

/**
* Set the type being named to the given [type].
*/
Expand Down
9 changes: 6 additions & 3 deletions pkg/analyzer/lib/dart/ast/ast_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,8 @@ abstract class AstFactory {
TypeAnnotation returnType,
Token functionKeyword,
TypeParameterList typeParameters,
FormalParameterList parameters);
FormalParameterList parameters,
{Token question});

/**
* Returns a newly created generic type alias. Either or both of the
Expand Down Expand Up @@ -1084,9 +1085,11 @@ abstract class AstFactory {

/**
* Returns a newly created type name. The [typeArguments] can be `null` if
* there are no type arguments.
* there are no type arguments. The [question] can be `null` if there is no
* question mark.
*/
TypeName typeName(Identifier name, TypeArgumentList typeArguments);
TypeName typeName(Identifier name, TypeArgumentList typeArguments,
{Token question});

/**
* Returns a newly created type parameter. Either or both of the [comment]
Expand Down
36 changes: 18 additions & 18 deletions pkg/analyzer/lib/src/dart/ast/ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5720,35 +5720,36 @@ class GenericFunctionTypeImpl extends TypeAnnotationImpl
*/
FormalParameterListImpl _parameters;

@override
Token question;

@override
DartType type;

/**
* Initialize a newly created generic function type.
*/
GenericFunctionTypeImpl(
TypeAnnotationImpl returnType,
this.functionKeyword,
TypeParameterListImpl typeParameters,
FormalParameterListImpl parameters) {
GenericFunctionTypeImpl(TypeAnnotationImpl returnType, this.functionKeyword,
TypeParameterListImpl typeParameters, FormalParameterListImpl parameters,
{this.question}) {
_returnType = _becomeParentOf(returnType);
_typeParameters = _becomeParentOf(typeParameters);
_parameters = _becomeParentOf(parameters);
}

@override
Token get beginToken =>
_returnType == null ? functionKeyword : _returnType.beginToken;
Token get beginToken => _returnType?.beginToken ?? functionKeyword;

@override
Iterable<SyntacticEntity> get childEntities => new ChildEntities()
..add(_returnType)
..add(functionKeyword)
..add(_typeParameters)
..add(_parameters);
..add(_parameters)
..add(question);

@override
Token get endToken => _parameters.endToken;
Token get endToken => question ?? _parameters.endToken;

@override
FormalParameterList get parameters => _parameters;
Expand Down Expand Up @@ -11031,7 +11032,7 @@ abstract class TypedLiteralImpl extends LiteralImpl implements TypedLiteral {
* The name of a type, which can optionally include type arguments.
*
* typeName ::=
* [Identifier] typeArguments?
* [Identifier] typeArguments? '?'?
*/
class TypeNameImpl extends TypeAnnotationImpl implements TypeName {
/**
Expand All @@ -11045,6 +11046,9 @@ class TypeNameImpl extends TypeAnnotationImpl implements TypeName {
*/
TypeArgumentListImpl _typeArguments;

@override
Token question;

/**
* The type being named, or `null` if the AST structure has not been resolved.
*/
Expand All @@ -11054,7 +11058,8 @@ class TypeNameImpl extends TypeAnnotationImpl implements TypeName {
* Initialize a newly created type name. The [typeArguments] can be `null` if
* there are no type arguments.
*/
TypeNameImpl(IdentifierImpl name, TypeArgumentListImpl typeArguments) {
TypeNameImpl(IdentifierImpl name, TypeArgumentListImpl typeArguments,
{this.question}) {
_name = _becomeParentOf(name);
_typeArguments = _becomeParentOf(typeArguments);
}
Expand All @@ -11064,15 +11069,10 @@ class TypeNameImpl extends TypeAnnotationImpl implements TypeName {

@override
Iterable<SyntacticEntity> get childEntities =>
new ChildEntities()..add(_name)..add(_typeArguments);
new ChildEntities()..add(_name)..add(_typeArguments)..add(question);

@override
Token get endToken {
if (_typeArguments != null) {
return _typeArguments.endToken;
}
return _name.endToken;
}
Token get endToken => question ?? _typeArguments?.endToken ?? _name.endToken;

@override
bool get isDeferred {
Expand Down
11 changes: 7 additions & 4 deletions pkg/analyzer/lib/src/dart/ast/ast_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -546,9 +546,11 @@ class AstFactoryImpl extends AstFactory {
TypeAnnotation returnType,
Token functionKeyword,
TypeParameterList typeParameters,
FormalParameterList parameters) =>
FormalParameterList parameters,
{Token question}) =>
new GenericFunctionTypeImpl(
returnType, functionKeyword, typeParameters, parameters);
returnType, functionKeyword, typeParameters, parameters,
question: question);

@override
GenericTypeAlias genericTypeAlias(
Expand Down Expand Up @@ -952,8 +954,9 @@ class AstFactoryImpl extends AstFactory {
new TypeArgumentListImpl(leftBracket, arguments, rightBracket);

@override
TypeName typeName(Identifier name, TypeArgumentList typeArguments) =>
new TypeNameImpl(name, typeArguments);
TypeName typeName(Identifier name, TypeArgumentList typeArguments,
{Token question}) =>
new TypeNameImpl(name, typeArguments, question: question);

@override
TypeParameter typeParameter(Comment comment, List<Annotation> metadata,
Expand Down
39 changes: 30 additions & 9 deletions pkg/analyzer/lib/src/dart/ast/utilities.dart
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,8 @@ class AstCloner implements AstVisitor<AstNode> {
cloneNode(node.returnType),
cloneToken(node.functionKeyword),
cloneNode(node.typeParameters),
cloneNode(node.parameters));
cloneNode(node.parameters),
question: cloneToken(node.question));

@override
AstNode visitGenericTypeAlias(GenericTypeAlias node) =>
Expand Down Expand Up @@ -958,7 +959,8 @@ class AstCloner implements AstVisitor<AstNode> {

@override
TypeName visitTypeName(TypeName node) =>
astFactory.typeName(cloneNode(node.name), cloneNode(node.typeArguments));
astFactory.typeName(cloneNode(node.name), cloneNode(node.typeArguments),
question: cloneToken(node.question));

@override
TypeParameter visitTypeParameter(TypeParameter node) =>
Expand Down Expand Up @@ -1661,7 +1663,8 @@ class AstComparator implements AstVisitor<bool> {
return isEqualNodes(node.returnType, other.returnType) &&
isEqualTokens(node.functionKeyword, other.functionKeyword) &&
isEqualNodes(node.typeParameters, other.typeParameters) &&
isEqualNodes(node.parameters, other.parameters);
isEqualNodes(node.parameters, other.parameters) &&
isEqualTokens(node.question, other.question);
}

@override
Expand Down Expand Up @@ -2140,7 +2143,8 @@ class AstComparator implements AstVisitor<bool> {
bool visitTypeName(TypeName node) {
TypeName other = _other as TypeName;
return isEqualNodes(node.name, other.name) &&
isEqualNodes(node.typeArguments, other.typeArguments);
isEqualNodes(node.typeArguments, other.typeArguments) &&
isEqualTokens(node.question, other.question);
}

@override
Expand Down Expand Up @@ -3384,7 +3388,8 @@ class IncrementalAstCloner implements AstVisitor<AstNode> {
_cloneNode(node.returnType),
_mapToken(node.functionKeyword),
_cloneNode(node.typeParameters),
_cloneNode(node.parameters));
_cloneNode(node.parameters),
question: _mapToken(node.question));

@override
AstNode visitGenericTypeAlias(GenericTypeAlias node) =>
Expand Down Expand Up @@ -3887,7 +3892,8 @@ class IncrementalAstCloner implements AstVisitor<AstNode> {
@override
TypeName visitTypeName(TypeName node) {
TypeName copy = astFactory.typeName(
_cloneNode(node.name), _cloneNode(node.typeArguments));
_cloneNode(node.name), _cloneNode(node.typeArguments),
question: _mapToken(node.question));
copy.type = node.type;
return copy;
}
Expand Down Expand Up @@ -6073,7 +6079,8 @@ class ResolutionCopier implements AstVisitor<bool> {
_isEqualNodes(node.returnType, toNode.returnType),
_isEqualTokens(node.functionKeyword, toNode.functionKeyword),
_isEqualNodes(node.typeParameters, toNode.typeParameters),
_isEqualNodes(node.parameters, toNode.parameters))) {
_isEqualNodes(node.parameters, toNode.parameters),
_isEqualTokens(node.question, toNode.question))) {
toNode.type = node.type;
return true;
}
Expand Down Expand Up @@ -6718,8 +6725,10 @@ class ResolutionCopier implements AstVisitor<bool> {
@override
bool visitTypeName(TypeName node) {
TypeName toNode = this._toNode as TypeName;
if (_and(_isEqualNodes(node.name, toNode.name),
_isEqualNodes(node.typeArguments, toNode.typeArguments))) {
if (_and(
_isEqualNodes(node.name, toNode.name),
_isEqualNodes(node.typeArguments, toNode.typeArguments),
_isEqualTokens(node.question, toNode.question))) {
toNode.type = node.type;
return true;
}
Expand Down Expand Up @@ -7595,6 +7604,9 @@ class ToSourceVisitor implements AstVisitor<void> {
_writer.print(' Function');
_visitNode(node.typeParameters);
_visitNode(node.parameters);
if (node.question != null) {
_writer.print('?');
}
}

@override
Expand Down Expand Up @@ -8035,6 +8047,9 @@ class ToSourceVisitor implements AstVisitor<void> {
void visitTypeName(TypeName node) {
_visitNode(node.name);
_visitNode(node.typeArguments);
if (node.question != null) {
_writer.print('?');
}
}

@override
Expand Down Expand Up @@ -8826,6 +8841,9 @@ class ToSourceVisitor2 implements AstVisitor<void> {
sink.write(' Function');
safelyVisitNode(node.typeParameters);
safelyVisitNode(node.parameters);
if (node.question != null) {
sink.write('?');
}
}

@override
Expand Down Expand Up @@ -9266,6 +9284,9 @@ class ToSourceVisitor2 implements AstVisitor<void> {
void visitTypeName(TypeName node) {
safelyVisitNode(node.name);
safelyVisitNode(node.typeArguments);
if (node.question != null) {
sink.write('?');
}
}

@override
Expand Down
14 changes: 10 additions & 4 deletions pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -611,9 +611,12 @@ class AstTestFactory {
parameters: formalParameterList(parameters));

static GenericFunctionType genericFunctionType(TypeAnnotation returnType,
TypeParameterList typeParameters, FormalParameterList parameters) =>
TypeParameterList typeParameters, FormalParameterList parameters,
{bool question: false}) =>
astFactory.genericFunctionType(returnType,
TokenFactory.tokenFromString("Function"), typeParameters, parameters);
TokenFactory.tokenFromString("Function"), typeParameters, parameters,
question:
question ? TokenFactory.tokenFromType(TokenType.QUESTION) : null);

static GenericTypeAlias genericTypeAlias(String name,
TypeParameterList typeParameters, GenericFunctionType functionType) =>
Expand Down Expand Up @@ -1264,8 +1267,11 @@ class AstTestFactory {
[List<TypeAnnotation> arguments]) =>
astFactory.typeName(name, typeArgumentList(arguments));

static TypeName typeName4(String name, [List<TypeAnnotation> arguments]) =>
astFactory.typeName(identifier3(name), typeArgumentList(arguments));
static TypeName typeName4(String name,
[List<TypeAnnotation> arguments, bool question = false]) =>
astFactory.typeName(identifier3(name), typeArgumentList(arguments),
question:
question ? TokenFactory.tokenFromType(TokenType.QUESTION) : null);

static TypeParameter typeParameter(String name) =>
astFactory.typeParameter(null, null, identifier3(name), null, null);
Expand Down
Loading

0 comments on commit 7a968ae

Please sign in to comment.