| // Copyright (c) 2019, 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. |
| |
| import 'package:analyzer/dart/ast/token.dart'; |
| import 'package:analyzer/dart/ast/visitor.dart'; |
| import 'package:analyzer/dart/element/type.dart'; |
| import 'package:analyzer/src/dart/ast/ast.dart'; |
| import 'package:analyzer/src/summary2/ast_binary_flags.dart'; |
| import 'package:analyzer/src/summary2/ast_binary_tag.dart'; |
| import 'package:analyzer/src/summary2/bundle_writer.dart'; |
| import 'package:analyzer/src/summary2/tokens_writer.dart'; |
| |
| /// Serializer of fully resolved ASTs. |
| class AstBinaryWriter extends ThrowingAstVisitor2<void> { |
| final ResolutionSink _sink; |
| |
| AstBinaryWriter({required ResolutionSink sink}) : _sink = sink; |
| |
| @override |
| void visitAdjacentStrings(AdjacentStrings node) { |
| _sink.writeEnum(AstNodeTag.AdjacentStrings); |
| _writeNodeList(node.strings); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitAnnotation(Annotation node) { |
| _sink.writeEnum(AstNodeTag.Annotation); |
| |
| _writeNode(node.name); |
| _writeOptionalNode(node.typeArguments); |
| _writeOptionalNode(node.constructorName); |
| |
| var arguments = node.arguments; |
| if (arguments != null) { |
| if (!arguments.arguments2.every((argument) { |
| return _isSerializableExpression(argument.argumentExpression2); |
| })) { |
| arguments = null; |
| } |
| } |
| _writeOptionalNode(arguments); |
| |
| _sink.writeElement(node.element); |
| } |
| |
| @override |
| void visitArgumentList(ArgumentList node) { |
| _sink.writeEnum(AstNodeTag.ArgumentList); |
| _writeNodeList(node.arguments2); |
| } |
| |
| @override |
| void visitAsExpression(AsExpression node) { |
| _sink.writeEnum(AstNodeTag.AsExpression); |
| |
| _writeNode(node.expression2); |
| |
| _writeNode(node.type); |
| |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitAssertInitializer(AssertInitializer node) { |
| _sink.writeEnum(AstNodeTag.AssertInitializer); |
| _writeNode(node.condition2); |
| _writeOptionalNode(node.message2); |
| } |
| |
| @override |
| void visitAssignmentExpression(AssignmentExpression node) { |
| _sink.writeEnum(AstNodeTag.AssignmentExpression); |
| |
| _writeNode(node.leftHandSide2); |
| _writeNode(node.rightHandSide2); |
| |
| var operatorToken = node.operator.type; |
| var binaryToken = TokensWriter.astToBinaryTokenType(operatorToken); |
| _sink.writeEnum(binaryToken); |
| |
| _sink.writeElement(node.element); |
| _sink.writeElement(node.readElement); |
| _sink.writeType(node.readType); |
| _sink.writeElement(node.writeElement); |
| _sink.writeType(node.writeType); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitAwaitExpression(AwaitExpression node) { |
| _sink.writeEnum(AstNodeTag.AwaitExpression); |
| |
| _writeNode(node.expression2); |
| |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitBinaryOperatorInvocation(BinaryOperatorInvocation node) { |
| _sink.writeEnum(AstNodeTag.BinaryOperatorInvocation); |
| |
| _writeNode(node.leftOperand); |
| _writeNode(node.rightOperand); |
| |
| var operatorToken = node.operator.type; |
| var binaryToken = TokensWriter.astToBinaryTokenType(operatorToken); |
| _sink.writeEnum(binaryToken); |
| |
| _sink.writeElement(node.element); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitBooleanLiteral(BooleanLiteral node) { |
| _sink.writeEnum(AstNodeTag.BooleanLiteral); |
| _writeByte(node.value ? 1 : 0); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitCallInvocation(covariant CallInvocationImpl node) { |
| _sink.writeEnum(AstNodeTag.CallInvocation); |
| |
| _writeNode(node.receiver); |
| _writeOptionalNode(node.typeArguments); |
| _writeNode(node.argumentList); |
| _sink.writeType(node.staticInvokeType); |
| _sink.writeOptionalTypeList(node.typeArgumentTypes); |
| _sink.writeOptionalObject(node.resolution, _writeInvocationResolution); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitCascadeExpression(CascadeExpression node) { |
| _sink.writeEnum(AstNodeTag.CascadeExpression); |
| _writeNode(node.target2); |
| _writeNodeList(node.sections); |
| } |
| |
| @override |
| void visitCascadeIndexAssignmentTarget( |
| covariant CascadeIndexAssignmentTargetImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.CascadeIndexAssignmentTarget); |
| _writeNode(node.index); |
| _sink.writeOptionalObject(node.read, _writeIndexReadResolution); |
| _sink.writeOptionalObject(node.write, _writeIndexWriteResolution); |
| } |
| |
| @override |
| void visitCascadeIndexExpression(covariant CascadeIndexExpressionImpl node) { |
| _sink.writeEnum(AstNodeTag.CascadeIndexExpression); |
| _writeNode(node.index); |
| _sink.writeOptionalObject(node.resolution, _writeIndexReadResolution); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitCascadeMethodInvocation( |
| covariant CascadeMethodInvocationImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.CascadeMethodInvocation); |
| _writeStringReference(node.name.lexeme); |
| _writeOptionalNode(node.typeArguments); |
| _writeNode(node.argumentList); |
| _sink.writeType(node.staticInvokeType); |
| _sink.writeOptionalTypeList(node.typeArgumentTypes); |
| _sink.writeOptionalObject(node.resolution, _writeInvocationResolution); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitCascadePropertyAssignmentTarget( |
| covariant CascadePropertyAssignmentTargetImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.CascadePropertyAssignmentTarget); |
| _writeStringReference(node.name.lexeme); |
| _sink.writeOptionalObject(node.read, _writeNamedReadResolution); |
| _sink.writeOptionalObject(node.write, _writeNamedWriteResolution); |
| } |
| |
| @override |
| void visitCascadePropertyExtraction( |
| covariant CascadePropertyExtractionImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.CascadePropertyExtraction); |
| _writeStringReference(node.name.lexeme); |
| _sink.writeOptionalObject(node.resolution, _writeNamedReadResolution); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitCascadeSection(CascadeSection node) { |
| _sink.writeEnum(AstNodeTag.CascadeSection); |
| _writeByte(node.isNullAware ? 1 : 0); |
| _writeNode(node.body); |
| } |
| |
| @override |
| void visitCompoundAssignment(CompoundAssignment node) { |
| _sink.writeEnum(AstNodeTag.CompoundAssignment); |
| _writeNode(node.target); |
| _writeNode(node.value); |
| |
| var operatorToken = node.operator.type; |
| var binaryToken = TokensWriter.astToBinaryTokenType(operatorToken); |
| _sink.writeEnum(binaryToken); |
| |
| _sink.writeElement(node.element); |
| _sink.writeType(node.operatorResultType); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitConditionalExpression(ConditionalExpression node) { |
| _sink.writeEnum(AstNodeTag.ConditionalExpression); |
| _writeNode(node.condition2); |
| _writeNode(node.thenExpression2); |
| _writeNode(node.elseExpression2); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitConstructorFieldInitializer(ConstructorFieldInitializer node) { |
| _sink.writeEnum(AstNodeTag.ConstructorFieldInitializer); |
| |
| _writeByte(AstBinaryFlags.encode(hasThis: node.thisKeyword != null)); |
| |
| _writeStringReference(node.fieldName2.lexeme); |
| _sink.writeElement(node.fieldElement); |
| _writeNode(node.expression2); |
| } |
| |
| @override |
| void visitConstructorInvocation(ConstructorInvocation node) { |
| _sink.writeEnum(AstNodeTag.ConstructorInvocation); |
| |
| _writeByte( |
| AstBinaryFlags.encode( |
| isConst: node.keyword?.type == Keyword.CONST, |
| isNew: node.keyword?.type == Keyword.NEW, |
| ), |
| ); |
| |
| _writeNode(node.constructorReference); |
| _writeNode(node.argumentList); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitConstructorReference2(ConstructorReference2 node) { |
| _sink.writeEnum(AstNodeTag.ConstructorReference2); |
| _writeNode(node.typeReference); |
| _writeOptionalNode(node.selector); |
| _sink.writeElement(node.element); |
| } |
| |
| @override |
| void visitConstructorSelector(ConstructorSelector node) { |
| _sink.writeEnum(AstNodeTag.ConstructorSelector); |
| _writeStringReference(node.name2.lexeme); |
| } |
| |
| @override |
| void visitConstructorTearOff(ConstructorTearOff node) { |
| _sink.writeEnum(AstNodeTag.ConstructorTearOff); |
| _writeNode(node.typeReference); |
| _writeNode(node.selector); |
| // A substituted element can refer to type parameters declared by the |
| // tear-off's function type. Those parameters aren't in scope while the |
| // element is written, so store the declaration and recreate the |
| // substitution from the function type when reading. |
| _sink.writeElement(node.element?.baseElement); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitConstructorTypeReference(ConstructorTypeReference node) { |
| _sink.writeEnum(AstNodeTag.ConstructorTypeReference); |
| _writeOptionalNode(node.importPrefix); |
| _writeStringReference(node.name.lexeme); |
| _writeOptionalNode(node.typeArguments); |
| _sink.writeElement(node.element); |
| _sink.writeType((node as ConstructorTypeReferenceImpl).type); |
| } |
| |
| @override |
| void visitDeclaredIdentifier(DeclaredIdentifier node) { |
| _sink.writeEnum(AstNodeTag.DeclaredIdentifier); |
| _writeByte( |
| AstBinaryFlags.encode( |
| isConst: node.keyword?.keyword == Keyword.CONST, |
| isFinal: node.keyword?.keyword == Keyword.FINAL, |
| isVar: node.keyword?.keyword == Keyword.VAR, |
| ), |
| ); |
| _writeOptionalNode(node.type); |
| _writeDeclarationName(node.name); |
| _storeDeclaration(node); |
| } |
| |
| @override |
| void visitDelimitedFormalParameters(DelimitedFormalParameters node) { |
| _sink.writeEnum(AstNodeTag.DelimitedFormalParameters); |
| _writeByte(AstBinaryFlags.encode(isNamed: node.isNamed)); |
| _writeNodeList(node.formalParameters); |
| } |
| |
| @override |
| void visitDirectAssignment(DirectAssignment node) { |
| _sink.writeEnum(AstNodeTag.DirectAssignment); |
| _writeNode(node.target); |
| _writeNode(node.value); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitDotShorthandConstructorInvocation( |
| covariant DotShorthandConstructorInvocationImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.DotShorthandConstructorInvocation); |
| _writeByte( |
| AstBinaryFlags.encode( |
| isConst: node.constKeyword?.type == Keyword.CONST, |
| isDotShorthand: node.isDotShorthand, |
| ), |
| ); |
| _writeNode(node.constructorName); |
| _writeNode(node.argumentList); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitDotShorthandConstructorInvocation2( |
| covariant DotShorthandConstructorInvocation2Impl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.DotShorthandConstructorInvocation2); |
| _writeByte( |
| AstBinaryFlags.encode( |
| isConst: node.constKeyword?.type == Keyword.CONST, |
| isDotShorthand: node.isDotShorthand, |
| ), |
| ); |
| _writeStringReference(node.name.lexeme); |
| _writeOptionalNode(node.typeArguments); |
| _writeNode(node.argumentList); |
| _sink.writeOptionalObject( |
| node.shorthandContext, |
| _writeDotShorthandContextResolution, |
| ); |
| _sink.writeElement(node.element); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitDotShorthandInvocation(covariant DotShorthandInvocationImpl node) { |
| _sink.writeEnum(AstNodeTag.DotShorthandInvocation); |
| _writeByte(AstBinaryFlags.encode(isDotShorthand: node.isDotShorthand)); |
| _writeNode(node.memberName); |
| _storeInvocationExpression(node); |
| } |
| |
| @override |
| void visitDotShorthandMethodInvocation( |
| covariant DotShorthandMethodInvocationImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.DotShorthandMethodInvocation); |
| _writeByte(AstBinaryFlags.encode(isDotShorthand: node.isDotShorthand)); |
| _writeStringReference(node.name.lexeme); |
| _writeOptionalNode(node.typeArguments); |
| _writeNode(node.argumentList); |
| _sink.writeOptionalObject( |
| node.shorthandContext, |
| _writeDotShorthandContextResolution, |
| ); |
| _sink.writeType(node.staticInvokeType); |
| _sink.writeOptionalTypeList(node.typeArgumentTypes); |
| _sink.writeOptionalObject(node.resolution, _writeInvocationResolution); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitDotShorthandNameExpression( |
| covariant DotShorthandNameExpressionImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.DotShorthandNameExpression); |
| _writeByte(AstBinaryFlags.encode(isDotShorthand: node.isDotShorthand)); |
| _writeStringReference(node.name.lexeme); |
| _sink.writeOptionalObject( |
| node.shorthandContext, |
| _writeDotShorthandContextResolution, |
| ); |
| _sink.writeOptionalObject(node.resolution, _writeNamedReadResolution); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitDotShorthandPropertyAccess( |
| covariant DotShorthandPropertyAccessImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.DotShorthandPropertyAccess); |
| _writeByte(AstBinaryFlags.encode(isDotShorthand: node.isDotShorthand)); |
| _writeNode(node.propertyName); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitDottedName(DottedName node) { |
| _sink.writeEnum(AstNodeTag.DottedName); |
| _writeUint32(node.tokens.length); |
| for (var i = 0; i < node.tokens.length; i++) { |
| _writeStringReference(node.tokens[i].lexeme); |
| } |
| } |
| |
| @override |
| void visitDoubleLiteral(DoubleLiteral node) { |
| _sink.writeEnum(AstNodeTag.DoubleLiteral); |
| _writeDouble(node.value); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitExtensionOverride(ExtensionOverride node) { |
| _sink.writeEnum(AstNodeTag.ExtensionOverride); |
| |
| _writeOptionalNode(node.importPrefix); |
| _writeStringReference(node.name.lexeme); |
| _writeOptionalNode(node.typeArguments); |
| _writeNode(node.argumentList); |
| |
| _sink.writeElement(node.element); |
| _sink.writeType(node.extendedType); |
| |
| // TODO(scheglov): typeArgumentTypes? |
| } |
| |
| @override |
| void visitFieldFormalParameter(covariant FieldFormalParameterImpl node) { |
| _sink.writeEnum(AstNodeTag.FieldFormalParameter); |
| |
| _withTypeParameters(node.functionTypedSuffix?.typeParameters, () { |
| _writeOptionalNode(node.functionTypedSuffix?.typeParameters); |
| _writeOptionalNode(node.type); |
| _writeOptionalNode(node.functionTypedSuffix?.formalParameters); |
| _storeRegularFormalParameter(node, node.constFinalOrVarKeyword); |
| }); |
| } |
| |
| @override |
| void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) { |
| _sink.writeEnum(AstNodeTag.ForEachPartsWithDeclaration); |
| _writeNode(node.loopVariable); |
| _storeForEachParts(node); |
| } |
| |
| @override |
| void visitFormalParameterList(FormalParameterList node) { |
| _sink.writeEnum(AstNodeTag.FormalParameterList); |
| _writeNodeList(node.requiredPositionalFormalParameters); |
| _writeOptionalNode(node.delimitedFormalParameters); |
| } |
| |
| @override |
| void visitForPartsWithDeclarations(ForPartsWithDeclarations node) { |
| _sink.writeEnum(AstNodeTag.ForPartsWithDeclarations); |
| _writeNode(node.variables); |
| _storeForParts(node); |
| } |
| |
| @override |
| void visitForPartsWithExpression(ForPartsWithExpression node) { |
| _sink.writeEnum(AstNodeTag.ForPartsWithExpression); |
| _writeOptionalNode(node.initialization2); |
| _storeForParts(node); |
| } |
| |
| @override |
| void visitFunctionInstantiation(FunctionInstantiation node) { |
| _sink.writeEnum(AstNodeTag.FunctionInstantiation); |
| _writeNode(node.operand); |
| _writeNode(node.typeArguments); |
| _sink.writeOptionalTypeList(node.typeArgumentTypes); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitFunctionReference(FunctionReference node) { |
| _sink.writeEnum(AstNodeTag.FunctionReference); |
| _writeNode(node.function2); |
| _writeOptionalNode(node.typeArguments); |
| _sink.writeOptionalTypeList(node.typeArgumentTypes); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitGenericFunctionType(covariant GenericFunctionTypeImpl node) { |
| _sink.writeEnum(AstNodeTag.GenericFunctionType); |
| |
| _writeByte(AstBinaryFlags.encode(hasQuestion: node.question != null)); |
| |
| _withTypeParameters(node.typeParameters, () { |
| _writeOptionalNode(node.typeParameters); |
| _writeOptionalNode(node.returnType); |
| _writeNode(node.parameters); |
| _sink.writeType(node.type); |
| _storeFormalParameterListResolution(node.parameters); |
| }); |
| } |
| |
| @override |
| void visitIfElement(IfElement node) { |
| _sink.writeEnum(AstNodeTag.IfElement); |
| _writeNode(node.expression2); |
| _writeNode(node.thenElement2); |
| _writeOptionalNode(node.elseElement2); |
| } |
| |
| @override |
| void visitIfNull(IfNull node) { |
| _sink.writeEnum(AstNodeTag.IfNull); |
| _writeNode(node.leftOperand); |
| _writeNode(node.rightOperand); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitIfNullAssignment(IfNullAssignment node) { |
| _sink.writeEnum(AstNodeTag.IfNullAssignment); |
| _writeNode(node.target); |
| _writeNode(node.value); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitImplicitCallReference(ImplicitCallReference node) { |
| _sink.writeEnum(AstNodeTag.ImplicitCallReference); |
| _writeNode(node.expression2); |
| _writeOptionalNode(node.typeArguments); |
| _sink.writeOptionalTypeList(node.typeArgumentTypes); |
| |
| _sink.writeElement(node.element); |
| |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitImplicitCallTearOff(ImplicitCallTearOff node) { |
| _sink.writeEnum(AstNodeTag.ImplicitCallTearOff); |
| _writeNode(node.operand); |
| _sink.writeElement(node.element); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitImplicitFunctionInstantiation( |
| covariant ImplicitFunctionInstantiationImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.ImplicitFunctionInstantiation); |
| _writeNode(node.operand); |
| _sink.writeOptionalTypeList(node.typeArgumentTypes); |
| _sink.writeByte(node.useLegacyV1Projection ? 1 : 0); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitImportPrefixedAssignmentTarget( |
| covariant ImportPrefixedAssignmentTargetImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.ImportPrefixedAssignmentTarget); |
| _writeNode(node.importPrefix); |
| _writeStringReference(node.name.lexeme); |
| _sink.writeOptionalObject(node.read, _writeNamedReadResolution); |
| _sink.writeOptionalObject(node.write, _writeNamedWriteResolution); |
| } |
| |
| @override |
| void visitImportPrefixedFunctionInvocation( |
| covariant ImportPrefixedFunctionInvocationImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.ImportPrefixedFunctionInvocation); |
| _writeNode(node.importPrefix); |
| _writeStringReference(node.name.lexeme); |
| _writeOptionalNode(node.typeArguments); |
| _writeNode(node.argumentList); |
| _sink.writeType(node.staticInvokeType); |
| _sink.writeOptionalTypeList(node.typeArgumentTypes); |
| _sink.writeOptionalObject(node.resolution, _writeInvocationResolution); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitImportPrefixedNameExpression( |
| covariant ImportPrefixedNameExpressionImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.ImportPrefixedNameExpression); |
| _writeNode(node.importPrefix); |
| _writeStringReference(node.name.lexeme); |
| _sink.writeOptionalObject(node.resolution, _writeNamedReadResolution); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitImportPrefixReference(ImportPrefixReference node) { |
| _sink.writeEnum(AstNodeTag.ImportPrefixReference); |
| _writeStringReference(node.name.lexeme); |
| _sink.writeElement(node.element); |
| } |
| |
| @override |
| void visitIncrementOrDecrementExpression( |
| IncrementOrDecrementExpression node, |
| ) { |
| _sink.writeEnum(AstNodeTag.IncrementOrDecrementExpression); |
| _sink.writeEnum(node.operation); |
| _sink.writeEnum(node.position); |
| _writeNode(node.target); |
| _sink.writeElement(node.element); |
| _sink.writeType(node.operatorResultType); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitIndexExpression(IndexExpression node) { |
| _sink.writeEnum(AstNodeTag.IndexExpression); |
| _writeByte( |
| AstBinaryFlags.encode( |
| hasPeriod: node.period != null, |
| hasQuestion: node.question != null, |
| ), |
| ); |
| _writeOptionalNode(node.target2); |
| _writeNode(node.index2); |
| |
| _sink.writeElement(node.element); |
| |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitIntegerLiteral(IntegerLiteral node) { |
| var value = node.value; |
| |
| if (value == null) { |
| _sink.writeEnum(AstNodeTag.IntegerLiteralNull); |
| _writeStringReference(node.literal.lexeme); |
| } else { |
| var isPositive = value >= 0; |
| if (!isPositive) { |
| value = -value; |
| } |
| |
| if (value & 0xFF == value) { |
| _sink.writeEnum( |
| isPositive |
| ? AstNodeTag.IntegerLiteralPositive1 |
| : AstNodeTag.IntegerLiteralNegative1, |
| ); |
| _writeStringReference(node.literal.lexeme); |
| _writeByte(value); |
| } else { |
| _sink.writeEnum( |
| isPositive |
| ? AstNodeTag.IntegerLiteralPositive |
| : AstNodeTag.IntegerLiteralNegative, |
| ); |
| _writeStringReference(node.literal.lexeme); |
| _writeUint32(value >> 32); |
| _writeUint32(value & 0xFFFFFFFF); |
| } |
| } |
| |
| // TODO(scheglov): Don't write type, AKA separate true `int` and `double`? |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitInterpolationExpression(InterpolationExpression node) { |
| _sink.writeEnum(AstNodeTag.InterpolationExpression); |
| _writeByte( |
| AstBinaryFlags.encode( |
| isStringInterpolationIdentifier: |
| node.leftBracket.type == TokenType.STRING_INTERPOLATION_IDENTIFIER, |
| ), |
| ); |
| _writeNode(node.expression2); |
| } |
| |
| @override |
| void visitInterpolationString(InterpolationString node) { |
| _sink.writeEnum(AstNodeTag.InterpolationString); |
| _writeStringReference(node.contents.lexeme); |
| _writeStringReference(node.value); |
| } |
| |
| @override |
| void visitInvalidExpressionAssignmentTarget( |
| InvalidExpressionAssignmentTarget node, |
| ) { |
| _sink.writeEnum(AstNodeTag.InvalidExpressionAssignmentTarget); |
| _sink.writeOptionalObject(node.read, (_) {}); |
| _sink.writeOptionalObject(node.write, (_) {}); |
| _writeNode(node.expression); |
| } |
| |
| @override |
| void visitIsExpression(IsExpression node) { |
| _sink.writeEnum(AstNodeTag.IsExpression); |
| _writeByte(AstBinaryFlags.encode(hasNot: node.notOperator != null)); |
| _writeNode(node.expression2); |
| _writeNode(node.type); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitListLiteral(ListLiteral node) { |
| _sink.writeEnum(AstNodeTag.ListLiteral); |
| |
| _writeByte(AstBinaryFlags.encode(isConst: node.constKeyword != null)); |
| |
| _writeOptionalNode(node.typeArguments); |
| _writeNodeList(node.elements2); |
| |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitLogicalAnd(LogicalAnd node) { |
| _sink.writeEnum(AstNodeTag.LogicalAnd); |
| _writeNode(node.leftOperand); |
| _writeNode(node.rightOperand); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitLogicalNot(LogicalNot node) { |
| _sink.writeEnum(AstNodeTag.LogicalNot); |
| _writeNode(node.operand); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitLogicalOr(LogicalOr node) { |
| _sink.writeEnum(AstNodeTag.LogicalOr); |
| _writeNode(node.leftOperand); |
| _writeNode(node.rightOperand); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitMapLiteralEntry(MapLiteralEntry node) { |
| _sink.writeEnum(AstNodeTag.MapLiteralEntry); |
| _writeByte( |
| AstBinaryFlags.encode( |
| hasQuestion: node.keyQuestion?.type == TokenType.QUESTION, |
| ), |
| ); |
| _writeNode(node.key2); |
| _writeByte( |
| AstBinaryFlags.encode( |
| hasQuestion: node.valueQuestion?.type == TokenType.QUESTION, |
| ), |
| ); |
| _writeNode(node.value2); |
| } |
| |
| @override |
| void visitMethodInvocation(MethodInvocation node) { |
| _sink.writeEnum(AstNodeTag.MethodInvocation); |
| |
| var operatorType = node.operator?.type; |
| _writeByte( |
| AstBinaryFlags.encode( |
| hasPeriod: |
| operatorType == TokenType.PERIOD || |
| operatorType == TokenType.QUESTION_PERIOD, |
| hasPeriod2: |
| operatorType == TokenType.PERIOD_PERIOD || |
| operatorType == TokenType.QUESTION_PERIOD_PERIOD, |
| hasQuestion: |
| operatorType == TokenType.QUESTION_PERIOD || |
| operatorType == TokenType.QUESTION_PERIOD_PERIOD, |
| ), |
| ); |
| |
| _writeOptionalNode(node.target2); |
| _writeNode(node.methodName); |
| _storeInvocationExpression(node); |
| } |
| |
| @override |
| void visitNamedArgument(NamedArgument node) { |
| _sink.writeEnum(AstNodeTag.NamedArgument); |
| |
| _writeStringReference(node.name.lexeme); |
| |
| _writeNode(node.argumentExpression2); |
| } |
| |
| @override |
| void visitNamedType(NamedType node) { |
| _sink.writeEnum(AstNodeTag.NamedType); |
| |
| _writeByte( |
| AstBinaryFlags.encode( |
| hasQuestion: node.question != null, |
| hasTypeArguments: node.typeArguments != null, |
| ), |
| ); |
| |
| _writeOptionalNode(node.importPrefix); |
| _writeStringReference(node.name.lexeme); |
| _writeOptionalNode(node.typeArguments); |
| |
| _sink.writeElement(node.element); |
| _sink.writeType(node.type); |
| } |
| |
| @override |
| void visitNullAssertionExpression(NullAssertionExpression node) { |
| _sink.writeEnum(AstNodeTag.NullAssertionExpression); |
| _writeNode(node.operand); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitNullAwareElement(NullAwareElement node) { |
| _sink.writeEnum(AstNodeTag.NullAwareElement); |
| _writeNode(node.value2); |
| } |
| |
| @override |
| void visitNullLiteral(NullLiteral node) { |
| _sink.writeEnum(AstNodeTag.NullLiteral); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitParenthesizedExpression(ParenthesizedExpression node) { |
| _sink.writeEnum(AstNodeTag.ParenthesizedExpression); |
| _writeNode(node.expression2); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitPrefixedIdentifier(PrefixedIdentifier node) { |
| _sink.writeEnum(AstNodeTag.PrefixedIdentifier); |
| _writeNode(node.prefix); |
| _writeNode(node.identifier); |
| |
| // TODO(scheglov): In actual prefixed identifier, the type of the identifier. |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitPropertyAccess(PropertyAccess node) { |
| _sink.writeEnum(AstNodeTag.PropertyAccess); |
| |
| var operatorType = node.operator.type; |
| _writeByte( |
| AstBinaryFlags.encode( |
| hasPeriod: |
| operatorType == TokenType.PERIOD || |
| operatorType == TokenType.QUESTION_PERIOD, |
| hasPeriod2: |
| operatorType == TokenType.PERIOD_PERIOD || |
| operatorType == TokenType.QUESTION_PERIOD_PERIOD, |
| hasQuestion: |
| operatorType == TokenType.QUESTION_PERIOD || |
| operatorType == TokenType.QUESTION_PERIOD_PERIOD, |
| ), |
| ); |
| |
| _writeOptionalNode(node.target2); |
| _writeNode(node.propertyName); |
| // TODO(scheglov): Get from the property? |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitReceiverIndexAssignmentTarget( |
| covariant ReceiverIndexAssignmentTargetImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.ReceiverIndexAssignmentTarget); |
| _writeByte(AstBinaryFlags.encode(hasQuestion: node.question != null)); |
| _writeNode(node.receiver); |
| _writeNode(node.index); |
| _sink.writeOptionalObject(node.read, _writeIndexReadResolution); |
| _sink.writeOptionalObject(node.write, _writeIndexWriteResolution); |
| } |
| |
| @override |
| void visitReceiverIndexExpression( |
| covariant ReceiverIndexExpressionImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.ReceiverIndexExpression); |
| _writeByte(AstBinaryFlags.encode(hasQuestion: node.question != null)); |
| _writeNode(node.receiver); |
| _writeNode(node.index); |
| _sink.writeOptionalObject(node.resolution, _writeIndexReadResolution); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitReceiverMethodInvocation( |
| covariant ReceiverMethodInvocationImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.ReceiverMethodInvocation); |
| _writeNode(node.receiver); |
| _writeByte(TokensWriter.astToBinaryTokenType(node.operator.type).index); |
| _writeStringReference(node.name.lexeme); |
| _writeOptionalNode(node.typeArguments); |
| _writeNode(node.argumentList); |
| _sink.writeType(node.staticInvokeType); |
| _sink.writeOptionalTypeList(node.typeArgumentTypes); |
| _sink.writeOptionalObject(node.resolution, _writeInvocationResolution); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitReceiverPropertyAssignmentTarget( |
| covariant ReceiverPropertyAssignmentTargetImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.ReceiverPropertyAssignmentTarget); |
| _writeNode(node.receiver); |
| _sink.writeEnum(TokensWriter.astToBinaryTokenType(node.operator.type)); |
| _writeStringReference(node.name.lexeme); |
| _sink.writeOptionalObject(node.read, _writeNamedReadResolution); |
| _sink.writeOptionalObject(node.write, _writeNamedWriteResolution); |
| } |
| |
| @override |
| void visitReceiverPropertyExtraction( |
| covariant ReceiverPropertyExtractionImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.ReceiverPropertyExtraction); |
| _writeNode(node.receiver); |
| _sink.writeEnum(TokensWriter.astToBinaryTokenType(node.operator.type)); |
| _writeStringReference(node.name.lexeme); |
| _sink.writeOptionalObject(node.resolution, _writeNamedReadResolution); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitRecordLiteral(RecordLiteral node) { |
| _sink.writeEnum(AstNodeTag.RecordLiteral); |
| _writeByte(AstBinaryFlags.encode(isConst: node.constKeyword != null)); |
| _writeNodeList(node.fields2); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitRecordLiteralNamedField(RecordLiteralNamedField node) { |
| _sink.writeEnum(AstNodeTag.RecordLiteralNamedField); |
| _writeStringReference(node.name.lexeme); |
| _writeNode(node.fieldExpression2); |
| } |
| |
| @override |
| void visitRecordTypeAnnotation(RecordTypeAnnotation node) { |
| _sink.writeEnum(AstNodeTag.RecordTypeAnnotation); |
| |
| _writeByte(AstBinaryFlags.encode(hasQuestion: node.question != null)); |
| |
| _writeNodeList(node.positionalFields); |
| _writeOptionalNode(node.namedFields); |
| |
| _sink.writeType(node.type); |
| } |
| |
| @override |
| void visitRecordTypeAnnotationNamedField( |
| RecordTypeAnnotationNamedField node, |
| ) { |
| _sink.writeEnum(AstNodeTag.RecordTypeAnnotationNamedField); |
| _writeNodeList(node.metadata); |
| _writeNode(node.type); |
| _writeStringReference(node.name.lexeme); |
| } |
| |
| @override |
| void visitRecordTypeAnnotationNamedFields( |
| RecordTypeAnnotationNamedFields node, |
| ) { |
| _sink.writeEnum(AstNodeTag.RecordTypeAnnotationNamedFields); |
| _writeNodeList(node.fields); |
| } |
| |
| @override |
| void visitRecordTypeAnnotationPositionalField( |
| RecordTypeAnnotationPositionalField node, |
| ) { |
| _sink.writeEnum(AstNodeTag.RecordTypeAnnotationPositionalField); |
| _writeNodeList(node.metadata); |
| _writeNode(node.type); |
| _sink.writeOptionalObject(node.name, (name) { |
| _writeStringReference(name.lexeme); |
| }); |
| } |
| |
| @override |
| void visitRedirectingConstructorInvocation( |
| RedirectingConstructorInvocation node, |
| ) { |
| _sink.writeEnum(AstNodeTag.RedirectingConstructorInvocation); |
| |
| _writeOptionalNode(node.constructorSelector); |
| _writeNode(node.argumentList); |
| |
| _sink.writeElement(node.element); |
| } |
| |
| @override |
| void visitRegularFormalParameter(covariant RegularFormalParameterImpl node) { |
| _sink.writeEnum(AstNodeTag.RegularFormalParameter); |
| |
| _withTypeParameters(node.functionTypedSuffix?.typeParameters, () { |
| _writeOptionalNode(node.functionTypedSuffix?.typeParameters); |
| _writeOptionalNode(node.type); |
| _writeOptionalNode(node.functionTypedSuffix?.formalParameters); |
| _storeRegularFormalParameter(node, node.constFinalOrVarKeyword); |
| }); |
| } |
| |
| @override |
| void visitSetOrMapLiteral(SetOrMapLiteral node) { |
| _sink.writeEnum(AstNodeTag.SetOrMapLiteral); |
| |
| _writeByte(AstBinaryFlags.encode(isConst: node.constKeyword != null)); |
| |
| var isMapBit = node.isMap ? (1 << 0) : 0; |
| var isSetBit = node.isSet ? (1 << 1) : 0; |
| _sink.writeByte(isMapBit | isSetBit); |
| |
| _writeOptionalNode(node.typeArguments); |
| _writeNodeList(node.elements2); |
| |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitSimpleIdentifier(SimpleIdentifier node) { |
| _sink.writeEnum(AstNodeTag.SimpleIdentifier); |
| _writeStringReference(node.name); |
| |
| _sink.writeElement(node.element); |
| _sink.writeOptionalTypeList(node.tearOffTypeArgumentTypes); |
| |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitSimpleStringLiteral(SimpleStringLiteral node) { |
| _sink.writeEnum(AstNodeTag.SimpleStringLiteral); |
| _writeStringReference(node.literal.lexeme); |
| _writeStringReference(node.value); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitSpreadElement(SpreadElement node) { |
| _sink.writeEnum(AstNodeTag.SpreadElement); |
| _writeByte( |
| AstBinaryFlags.encode( |
| hasQuestion: |
| node.spreadOperator.type == TokenType.PERIOD_PERIOD_PERIOD_QUESTION, |
| ), |
| ); |
| _writeNode(node.expression2); |
| } |
| |
| @override |
| void visitStaticQualifier(StaticQualifier node) { |
| _sink.writeEnum(AstNodeTag.StaticQualifier); |
| _writeOptionalNode(node.importPrefix); |
| _writeStringReference(node.name.lexeme); |
| _sink.writeElement(node.element); |
| } |
| |
| @override |
| void visitStringInterpolation(StringInterpolation node) { |
| _sink.writeEnum(AstNodeTag.StringInterpolation); |
| _writeNodeList(node.elements); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| _sink.writeEnum(AstNodeTag.SuperConstructorInvocation); |
| |
| _writeOptionalNode(node.constructorSelector); |
| _writeNode(node.argumentList); |
| |
| _sink.writeElement(node.element); |
| } |
| |
| @override |
| void visitSuperExpression(SuperExpression node) { |
| _sink.writeEnum(AstNodeTag.SuperExpression); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitSuperFormalParameter(covariant SuperFormalParameterImpl node) { |
| _sink.writeEnum(AstNodeTag.SuperFormalParameter); |
| |
| _withTypeParameters(node.functionTypedSuffix?.typeParameters, () { |
| _writeOptionalNode(node.functionTypedSuffix?.typeParameters); |
| _writeOptionalNode(node.type); |
| _writeOptionalNode(node.functionTypedSuffix?.formalParameters); |
| _storeRegularFormalParameter(node, node.constFinalOrVarKeyword); |
| }); |
| } |
| |
| @override |
| void visitSymbolLiteral(SymbolLiteral node) { |
| _sink.writeEnum(AstNodeTag.SymbolLiteral); |
| |
| var components = node.components; |
| _writeUint30(components.length); |
| for (var token in components) { |
| _writeStringReference(token.lexeme); |
| } |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitThisExpression(ThisExpression node) { |
| _sink.writeEnum(AstNodeTag.ThisExpression); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitThrowExpression(ThrowExpression node) { |
| _sink.writeEnum(AstNodeTag.ThrowExpression); |
| _writeNode(node.expression2); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitTypeArgumentList(TypeArgumentList node) { |
| _sink.writeEnum(AstNodeTag.TypeArgumentList); |
| _writeNodeList(node.arguments); |
| } |
| |
| @override |
| void visitTypeLiteral(TypeLiteral node) { |
| _sink.writeEnum(AstNodeTag.TypeLiteral); |
| _writeNode(node.type); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitTypeParameter(TypeParameter node) { |
| _sink.writeEnum(AstNodeTag.TypeParameter); |
| _writeDeclarationName(node.name); |
| _writeOptionalNode(node.bound); |
| _storeDeclaration(node); |
| } |
| |
| @override |
| void visitTypeParameterList(TypeParameterList node) { |
| _sink.writeEnum(AstNodeTag.TypeParameterList); |
| _writeNodeList(node.typeParameters); |
| } |
| |
| @override |
| void visitUnaryOperatorInvocation(UnaryOperatorInvocation node) { |
| _sink.writeEnum(AstNodeTag.UnaryOperatorInvocation); |
| |
| var binaryToken = TokensWriter.astToBinaryTokenType(node.operator.type); |
| _sink.writeEnum(binaryToken); |
| _writeNode(node.operand); |
| |
| _storeExpression(node); |
| _sink.writeElement(node.element); |
| } |
| |
| @override |
| void visitUnqualifiedFunctionInvocation( |
| covariant UnqualifiedFunctionInvocationImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.UnqualifiedFunctionInvocation); |
| _writeStringReference(node.name.lexeme); |
| _writeOptionalNode(node.typeArguments); |
| _writeNode(node.argumentList); |
| _sink.writeType(node.staticInvokeType); |
| _sink.writeOptionalTypeList(node.typeArgumentTypes); |
| _sink.writeOptionalObject(node.resolution, _writeInvocationResolution); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitUnqualifiedNameAssignmentTarget( |
| covariant UnqualifiedNameAssignmentTargetImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.UnqualifiedNameAssignmentTarget); |
| _writeStringReference(node.name.lexeme); |
| _sink.writeOptionalObject(node.read, _writeNamedReadResolution); |
| _sink.writeOptionalObject(node.write, _writeNamedWriteResolution); |
| } |
| |
| @override |
| void visitUnqualifiedNameExpression( |
| covariant UnqualifiedNameExpressionImpl node, |
| ) { |
| _sink.writeEnum(AstNodeTag.UnqualifiedNameExpression); |
| _writeStringReference(node.name.lexeme); |
| _sink.writeOptionalObject(node.resolution, _writeNamedReadResolution); |
| _storeExpression(node); |
| } |
| |
| @override |
| void visitVariableDeclarationList(VariableDeclarationList node) { |
| _sink.writeEnum(AstNodeTag.VariableDeclarationList); |
| _writeByte( |
| AstBinaryFlags.encode( |
| isConst: node.isConst, |
| isFinal: node.isFinal, |
| isLate: node.lateKeyword != null, |
| isVar: node.keyword?.keyword == Keyword.VAR, |
| ), |
| ); |
| _writeOptionalNode(node.type); |
| _writeNodeList(node.variables); |
| _storeAnnotatedNode(node); |
| } |
| |
| void _storeAnnotatedNode(AnnotatedNode node) { |
| _writeNodeList(node.metadata); |
| } |
| |
| void _storeDeclaration(Declaration node) { |
| _storeAnnotatedNode(node); |
| } |
| |
| void _storeExpression(Expression node) { |
| _sink.writeType(node.staticType); |
| } |
| |
| void _storeForEachParts(ForEachParts node) { |
| _writeNode(node.iterable2); |
| _storeForLoopParts(node); |
| } |
| |
| void _storeForLoopParts(ForLoopParts node) {} |
| |
| void _storeFormalParameter(FormalParameterImpl node) { |
| var fragment = node.declaredFragment!; |
| var element = fragment.element; |
| _writeActualType(_sink, element.type); |
| } |
| |
| void _storeFormalParameterListResolution(FormalParameterListImpl node) { |
| for (var formalParameter in node.allFormalParameters) { |
| var functionTypedSuffix = formalParameter.functionTypedSuffix; |
| _withTypeParameters(functionTypedSuffix?.typeParameters, () { |
| _storeFormalParameter(formalParameter); |
| if (functionTypedSuffix != null) { |
| _storeFormalParameterListResolution( |
| functionTypedSuffix.formalParameters, |
| ); |
| } |
| }); |
| } |
| } |
| |
| void _storeForParts(ForParts node) { |
| _writeOptionalNode(node.condition2); |
| _writeNodeList(node.updaters2); |
| _storeForLoopParts(node); |
| } |
| |
| void _storeInvocationExpression(InvocationExpression node) { |
| _writeOptionalNode(node.typeArguments); |
| _writeNode(node.argumentList); |
| _sink.writeType(node.staticInvokeType); |
| _sink.writeOptionalTypeList(node.typeArgumentTypes); |
| _storeExpression(node); |
| } |
| |
| void _storeRegularFormalParameter(FormalParameterImpl node, Token? keyword) { |
| _writeByte( |
| AstBinaryFlags.encodeFormalParameter( |
| hasInitializer: node.defaultClause != null, |
| hasName: node.name != null, |
| hasQuestion: node.functionTypedSuffix?.question != null, |
| isConst: keyword?.type == Keyword.CONST, |
| isCovariant: node.covariantKeyword != null, |
| isFinal: keyword?.type == Keyword.FINAL, |
| isPositional: node.isPositional, |
| isRequired: node.isRequired, |
| isVar: keyword?.type == Keyword.VAR, |
| ), |
| ); |
| |
| _writeNodeList(node.metadata); |
| if (node.name != null) { |
| _writeDeclarationName(node.name!); |
| } |
| if (node.defaultClause case var defaultClause?) { |
| _writeNode(defaultClause.value2); |
| } |
| } |
| |
| void _withTypeParameters(TypeParameterListImpl? node, void Function() f) { |
| if (node == null) { |
| f(); |
| } else { |
| var typeParameterElements = node.typeParameters |
| .map((typeParameter) => typeParameter.declaredFragment!.element) |
| .toList(); |
| _sink.localElements.withElements(typeParameterElements, () { |
| f(); |
| }); |
| } |
| } |
| |
| void _writeActualType(ResolutionSink resolutionSink, DartType type) { |
| resolutionSink.writeType(type); |
| } |
| |
| void _writeByte(int byte) { |
| assert((byte & 0xFF) == byte); |
| _sink.writeByte(byte); |
| } |
| |
| void _writeDeclarationName(Token token) { |
| _writeStringReference(token.lexeme); |
| } |
| |
| void _writeDotShorthandContextResolution( |
| DotShorthandContextResolutionImpl resolution, |
| ) { |
| switch (resolution) { |
| case ValidDotShorthandContextResolutionImpl(): |
| _sink.writeEnum(DotShorthandContextResolutionTag.valid); |
| _sink.writeType(resolution.contextType); |
| _sink.writeType(resolution.lookupType); |
| case InvalidDotShorthandContextResolutionImpl(): |
| _sink.writeEnum(DotShorthandContextResolutionTag.invalid); |
| _sink.writeType(resolution.contextType); |
| } |
| } |
| |
| void _writeDouble(double value) { |
| _sink.writeDouble(value); |
| } |
| |
| void _writeIndexReadResolution(IndexReadResolutionImpl resolution) { |
| switch (resolution) { |
| case DynamicIndexReadResolutionImpl(): |
| _sink.writeEnum(IndexReadResolutionTag.dynamic_); |
| case InvalidIndexReadResolutionImpl(:var recoveryElement): |
| _sink.writeEnum(IndexReadResolutionTag.invalid); |
| _sink.writeElement(recoveryElement); |
| case MethodIndexReadResolutionImpl(:var element, :var type): |
| _sink.writeEnum(IndexReadResolutionTag.method); |
| _sink.writeElement(element); |
| _sink.writeType(type); |
| } |
| } |
| |
| void _writeIndexWriteResolution(IndexWriteResolutionImpl resolution) { |
| switch (resolution) { |
| case DynamicIndexWriteResolutionImpl(): |
| _sink.writeEnum(IndexWriteResolutionTag.dynamic_); |
| case InvalidIndexWriteResolutionImpl(:var recoveryElement): |
| _sink.writeEnum(IndexWriteResolutionTag.invalid); |
| _sink.writeElement(recoveryElement); |
| case MethodIndexWriteResolutionImpl(:var element): |
| _sink.writeEnum(IndexWriteResolutionTag.method); |
| _sink.writeElement(element); |
| } |
| } |
| |
| void _writeInvocationResolution(InvocationResolutionImpl resolution) { |
| switch (resolution) { |
| case DynamicInvocationResolutionImpl(): |
| _sink.writeEnum(InvocationResolutionTag.dynamic_); |
| _sink.writeType(resolution.type); |
| case ExecutableInvocationResolutionImpl(): |
| _sink.writeEnum(InvocationResolutionTag.executable); |
| _sink.writeElement(resolution.element); |
| _sink.writeType(resolution.invokeType); |
| _sink.writeType(resolution.type); |
| case FunctionCallInvocationResolutionImpl(): |
| _sink.writeEnum(InvocationResolutionTag.functionCall); |
| _sink.writeType(resolution.invokeType); |
| _sink.writeType(resolution.type); |
| case FunctionInterfaceInvocationResolutionImpl(): |
| _sink.writeEnum(InvocationResolutionTag.functionInterface); |
| _sink.writeType(resolution.type); |
| case FunctionTypeInvocationResolutionImpl(): |
| _sink.writeEnum(InvocationResolutionTag.functionType); |
| _sink.writeType(resolution.invokeType); |
| _sink.writeType(resolution.type); |
| case InvalidInvocationResolutionImpl(): |
| _sink.writeEnum(InvocationResolutionTag.invalid); |
| _sink.writeType(resolution.type); |
| _sink.writeList(resolution.candidates, _sink.writeElement); |
| _sink.writeOptionalObject( |
| resolution.recovery, |
| _writeInvocationResolution, |
| ); |
| } |
| } |
| |
| void _writeNamedReadResolution(NamedReadResolutionImpl resolution) { |
| switch (resolution) { |
| case DynamicPropertyReadResolutionImpl(): |
| _sink.writeEnum(NamedReadResolutionTag.dynamicPropertyRead); |
| case ExecutableTearOffResolutionImpl(): |
| _sink.writeEnum(NamedReadResolutionTag.executableTearOff); |
| _sink.writeElement(resolution.element); |
| case FunctionCallTearOffResolutionImpl(): |
| _sink.writeEnum(NamedReadResolutionTag.functionCallTearOff); |
| _sink.writeType(resolution.type); |
| _sink.writeType(resolution.associatedFunctionType); |
| case FunctionInterfaceCallTearOffResolutionImpl(): |
| _sink.writeEnum(NamedReadResolutionTag.functionInterfaceCallTearOff); |
| _sink.writeType(resolution.type); |
| case GetterInvocationResolutionImpl(): |
| _sink.writeEnum(NamedReadResolutionTag.getterInvocation); |
| _sink.writeElement(resolution.element); |
| _sink.writeType(resolution.type); |
| case InvalidNamedReadResolutionImpl(): |
| _sink.writeEnum(NamedReadResolutionTag.invalid); |
| _sink.writeElement(resolution.recoveryElement); |
| case RecordFieldReadResolutionImpl(): |
| _sink.writeEnum(NamedReadResolutionTag.recordFieldRead); |
| _sink.writeType(resolution.type); |
| case VariableReadResolutionImpl(): |
| _sink.writeEnum(NamedReadResolutionTag.variableRead); |
| _sink.writeElement(resolution.element); |
| _sink.writeType(resolution.type); |
| } |
| } |
| |
| void _writeNamedWriteResolution(NamedWriteResolutionImpl resolution) { |
| switch (resolution) { |
| case InvalidNamedWriteResolutionImpl(): |
| _sink.writeEnum(NamedWriteResolutionTag.invalid); |
| _sink.writeElement(resolution.recoveryElement); |
| case SetterInvocationResolutionImpl(): |
| _sink.writeEnum(NamedWriteResolutionTag.setterInvocation); |
| _sink.writeElement(resolution.element); |
| case VariableWriteResolutionImpl(): |
| _sink.writeEnum(NamedWriteResolutionTag.variableWrite); |
| _sink.writeElement(resolution.element); |
| _sink.writeType(resolution.acceptedType); |
| case DynamicPropertyWriteResolutionImpl(): |
| _sink.writeEnum(NamedWriteResolutionTag.dynamicPropertyWrite); |
| } |
| } |
| |
| void _writeNode(AstNode node) { |
| node.accept2(this); |
| } |
| |
| void _writeNodeList(List<AstNode> nodeList) { |
| _writeUint30(nodeList.length); |
| for (var i = 0; i < nodeList.length; ++i) { |
| nodeList[i].accept2(this); |
| } |
| } |
| |
| void _writeOptionalNode(AstNode? node) { |
| _sink.writeOptionalObject(node, _writeNode); |
| } |
| |
| void _writeStringReference(String string) { |
| _sink.writeStringReference(string); |
| } |
| |
| @pragma("vm:prefer-inline") |
| void _writeUint30(int value) { |
| _sink.writeUint30(value); |
| } |
| |
| void _writeUint32(int value) { |
| _sink.writeUint32(value); |
| } |
| |
| /// Return `true` if the expression might be successfully serialized. |
| /// |
| /// This does not mean that the expression is constant, it just means that |
| /// we know that it might be serialized and deserialized. For example |
| /// function expressions are problematic, and are not necessary to |
| /// deserialize, so we choose not to do this. |
| static bool _isSerializableExpression(Expression? node) { |
| if (node == null) return false; |
| |
| var visitor = _IsSerializableExpressionVisitor(); |
| node.accept2(visitor); |
| return visitor.result; |
| } |
| } |
| |
| class _IsSerializableExpressionVisitor extends RecursiveAstVisitor2<void> { |
| bool result = true; |
| |
| @override |
| void visitFunctionExpression(FunctionExpression node) { |
| result = false; |
| } |
| } |