Store isAsynchronous and isGenerator in executables.

So, that we don't have to read bodies to know if these executables
are async / generators.

R=brianwilkerson@google.com

Change-Id: I1a88f896a9d1b0539a021b1f12b7b55ac44ca44a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/102100
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index d655c4c..617ad57 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -4747,6 +4747,7 @@
   LinkedNodeBuilder _variantField_10;
   idl.LinkedNodeFormalParameterKind _variantField_26;
   double _variantField_21;
+  bool _variantField_37;
   LinkedNodeTypeBuilder _variantField_25;
   String _variantField_30;
   LinkedNodeBuilder _variantField_14;
@@ -9440,6 +9441,14 @@
   }
 
   @override
+  bool get executable_isAsynchronous {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.functionExpression ||
+        kind == idl.LinkedNodeKind.methodDeclaration);
+    return _variantField_27 ??= false;
+  }
+
+  @override
   bool get inheritsCovariant {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -9477,6 +9486,13 @@
     _variantField_27 = value;
   }
 
+  set executable_isAsynchronous(bool value) {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.functionExpression ||
+        kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_27 = value;
+  }
+
   set inheritsCovariant(bool value) {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -9858,6 +9874,21 @@
   }
 
   @override
+  bool get executable_isGenerator {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.functionExpression ||
+        kind == idl.LinkedNodeKind.methodDeclaration);
+    return _variantField_37 ??= false;
+  }
+
+  set executable_isGenerator(bool value) {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.functionExpression ||
+        kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_37 = value;
+  }
+
+  @override
   LinkedNodeTypeBuilder get expression_type {
     assert(kind == idl.LinkedNodeKind.adjacentStrings ||
         kind == idl.LinkedNodeKind.assignmentExpression ||
@@ -10178,11 +10209,15 @@
     LinkedNodeBuilder functionExpression_body,
     LinkedNodeBuilder functionExpression_formalParameters,
     LinkedNodeBuilder functionExpression_typeParameters,
+    bool executable_isAsynchronous,
+    bool executable_isGenerator,
   })  : _kind = idl.LinkedNodeKind.functionExpression,
         _variantField_24 = actualReturnType,
         _variantField_6 = functionExpression_body,
         _variantField_7 = functionExpression_formalParameters,
-        _variantField_8 = functionExpression_typeParameters;
+        _variantField_8 = functionExpression_typeParameters,
+        _variantField_27 = executable_isAsynchronous,
+        _variantField_37 = executable_isGenerator;
 
   LinkedNodeBuilder.functionTypeAlias({
     LinkedNodeTypeBuilder actualReturnType,
@@ -10244,10 +10279,12 @@
     int methodDeclaration_modifierKeyword,
     int methodDeclaration_propertyKeyword,
     int methodDeclaration_actualProperty,
+    bool executable_isAsynchronous,
     LinkedNodeBuilder methodDeclaration_typeParameters,
     int codeLength,
     int codeOffset,
     LinkedNodeBuilder methodDeclaration_name,
+    bool executable_isGenerator,
   })  : _kind = idl.LinkedNodeKind.methodDeclaration,
         _variantField_24 = actualReturnType,
         _variantField_11 = annotatedNode_comment,
@@ -10260,10 +10297,12 @@
         _variantField_16 = methodDeclaration_modifierKeyword,
         _variantField_18 = methodDeclaration_propertyKeyword,
         _variantField_19 = methodDeclaration_actualProperty,
+        _variantField_27 = executable_isAsynchronous,
         _variantField_9 = methodDeclaration_typeParameters,
         _variantField_34 = codeLength,
         _variantField_33 = codeOffset,
-        _variantField_10 = methodDeclaration_name;
+        _variantField_10 = methodDeclaration_name,
+        _variantField_37 = executable_isGenerator;
 
   LinkedNodeBuilder.fieldFormalParameter({
     LinkedNodeTypeBuilder actualType,
@@ -10496,10 +10535,12 @@
     int constructorDeclaration_externalKeyword,
     int constructorDeclaration_period,
     int constructorDeclaration_separator,
+    bool executable_isAsynchronous,
     LinkedNodeBuilder constructorDeclaration_redirectedConstructor,
     int codeLength,
     int codeOffset,
     LinkedNodeBuilder constructorDeclaration_returnType,
+    bool executable_isGenerator,
   })  : _kind = idl.LinkedNodeKind.constructorDeclaration,
         _variantField_2 = constructorDeclaration_initializers,
         _variantField_11 = annotatedNode_comment,
@@ -10512,10 +10553,12 @@
         _variantField_16 = constructorDeclaration_externalKeyword,
         _variantField_18 = constructorDeclaration_period,
         _variantField_19 = constructorDeclaration_separator,
+        _variantField_27 = executable_isAsynchronous,
         _variantField_9 = constructorDeclaration_redirectedConstructor,
         _variantField_34 = codeLength,
         _variantField_33 = codeOffset,
-        _variantField_10 = constructorDeclaration_returnType;
+        _variantField_10 = constructorDeclaration_returnType,
+        _variantField_37 = executable_isGenerator;
 
   LinkedNodeBuilder.dottedName({
     List<LinkedNodeBuilder> dottedName_components,
@@ -11868,6 +11911,7 @@
         signature.addString(x);
       }
     }
+    signature.addBool(this._variantField_37 == true);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -12050,6 +12094,9 @@
     if (_variantField_21 != null && _variantField_21 != 0.0) {
       fbBuilder.addFloat64(21, _variantField_21);
     }
+    if (_variantField_37 == true) {
+      fbBuilder.addBool(37, true);
+    }
     if (offset_variantField_25 != null) {
       fbBuilder.addOffset(25, offset_variantField_25);
     }
@@ -12129,6 +12176,7 @@
   idl.LinkedNode _variantField_10;
   idl.LinkedNodeFormalParameterKind _variantField_26;
   double _variantField_21;
+  bool _variantField_37;
   idl.LinkedNodeType _variantField_25;
   String _variantField_30;
   idl.LinkedNode _variantField_14;
@@ -15394,6 +15442,16 @@
   }
 
   @override
+  bool get executable_isAsynchronous {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.functionExpression ||
+        kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_27 ??=
+        const fb.BoolReader().vTableGet(_bc, _bcOffset, 27, false);
+    return _variantField_27;
+  }
+
+  @override
   bool get inheritsCovariant {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -15673,6 +15731,16 @@
   }
 
   @override
+  bool get executable_isGenerator {
+    assert(kind == idl.LinkedNodeKind.constructorDeclaration ||
+        kind == idl.LinkedNodeKind.functionExpression ||
+        kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_37 ??=
+        const fb.BoolReader().vTableGet(_bc, _bcOffset, 37, false);
+    return _variantField_37;
+  }
+
+  @override
   idl.LinkedNodeType get expression_type {
     assert(kind == idl.LinkedNodeKind.adjacentStrings ||
         kind == idl.LinkedNodeKind.assignmentExpression ||
@@ -15909,6 +15977,10 @@
       if (functionExpression_typeParameters != null)
         _result["functionExpression_typeParameters"] =
             functionExpression_typeParameters.toJson();
+      if (executable_isAsynchronous != false)
+        _result["executable_isAsynchronous"] = executable_isAsynchronous;
+      if (executable_isGenerator != false)
+        _result["executable_isGenerator"] = executable_isGenerator;
     }
     if (kind == idl.LinkedNodeKind.functionTypeAlias) {
       if (actualReturnType != null)
@@ -15995,6 +16067,8 @@
       if (methodDeclaration_actualProperty != 0)
         _result["methodDeclaration_actualProperty"] =
             methodDeclaration_actualProperty;
+      if (executable_isAsynchronous != false)
+        _result["executable_isAsynchronous"] = executable_isAsynchronous;
       if (methodDeclaration_typeParameters != null)
         _result["methodDeclaration_typeParameters"] =
             methodDeclaration_typeParameters.toJson();
@@ -16002,6 +16076,8 @@
       if (codeOffset != 0) _result["codeOffset"] = codeOffset;
       if (methodDeclaration_name != null)
         _result["methodDeclaration_name"] = methodDeclaration_name.toJson();
+      if (executable_isGenerator != false)
+        _result["executable_isGenerator"] = executable_isGenerator;
     }
     if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
       if (actualType != null) _result["actualType"] = actualType.toJson();
@@ -16288,6 +16364,8 @@
       if (constructorDeclaration_separator != 0)
         _result["constructorDeclaration_separator"] =
             constructorDeclaration_separator;
+      if (executable_isAsynchronous != false)
+        _result["executable_isAsynchronous"] = executable_isAsynchronous;
       if (constructorDeclaration_redirectedConstructor != null)
         _result["constructorDeclaration_redirectedConstructor"] =
             constructorDeclaration_redirectedConstructor.toJson();
@@ -16296,6 +16374,8 @@
       if (constructorDeclaration_returnType != null)
         _result["constructorDeclaration_returnType"] =
             constructorDeclaration_returnType.toJson();
+      if (executable_isGenerator != false)
+        _result["executable_isGenerator"] = executable_isGenerator;
     }
     if (kind == idl.LinkedNodeKind.dottedName) {
       if (dottedName_components.isNotEmpty)
@@ -17672,6 +17752,8 @@
         "functionExpression_formalParameters":
             functionExpression_formalParameters,
         "functionExpression_typeParameters": functionExpression_typeParameters,
+        "executable_isAsynchronous": executable_isAsynchronous,
+        "executable_isGenerator": executable_isGenerator,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -17727,10 +17809,12 @@
         "methodDeclaration_modifierKeyword": methodDeclaration_modifierKeyword,
         "methodDeclaration_propertyKeyword": methodDeclaration_propertyKeyword,
         "methodDeclaration_actualProperty": methodDeclaration_actualProperty,
+        "executable_isAsynchronous": executable_isAsynchronous,
         "methodDeclaration_typeParameters": methodDeclaration_typeParameters,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
         "methodDeclaration_name": methodDeclaration_name,
+        "executable_isGenerator": executable_isGenerator,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -17934,11 +18018,13 @@
             constructorDeclaration_externalKeyword,
         "constructorDeclaration_period": constructorDeclaration_period,
         "constructorDeclaration_separator": constructorDeclaration_separator,
+        "executable_isAsynchronous": executable_isAsynchronous,
         "constructorDeclaration_redirectedConstructor":
             constructorDeclaration_redirectedConstructor,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
         "constructorDeclaration_returnType": constructorDeclaration_returnType,
+        "executable_isGenerator": executable_isGenerator,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index b7053cb..47e6bb9 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1936,6 +1936,8 @@
 
   variantField_21:double (id: 21);
 
+  variantField_37:bool (id: 37);
+
   variantField_25:LinkedNodeType (id: 25);
 
   variantField_30:string (id: 30);
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index d0e04f4..b9bac17 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -1395,6 +1395,20 @@
   @VariantId(17, variant: LinkedNodeKind.enumDeclaration)
   int get enumDeclaration_rightBracket;
 
+  @VariantId(27, variantList: [
+    LinkedNodeKind.constructorDeclaration,
+    LinkedNodeKind.functionExpression,
+    LinkedNodeKind.methodDeclaration,
+  ])
+  bool get executable_isAsynchronous;
+
+  @VariantId(37, variantList: [
+    LinkedNodeKind.constructorDeclaration,
+    LinkedNodeKind.functionExpression,
+    LinkedNodeKind.methodDeclaration,
+  ])
+  bool get executable_isGenerator;
+
   @VariantId(25, variantList: [
     LinkedNodeKind.adjacentStrings,
     LinkedNodeKind.assignmentExpression,
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 2cc58d4..b1f46b5 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -600,6 +600,8 @@
   @override
   LinkedNodeBuilder visitFunctionExpression(FunctionExpression node) {
     return LinkedNodeBuilder.functionExpression(
+      executable_isAsynchronous: node.body?.isAsynchronous ?? false,
+      executable_isGenerator: node.body?.isGenerator ?? false,
       functionExpression_body: node.body?.accept(this),
       functionExpression_formalParameters: node.parameters?.accept(this),
       functionExpression_typeParameters: node.typeParameters?.accept(this),
@@ -854,6 +856,8 @@
   @override
   LinkedNodeBuilder visitMethodDeclaration(MethodDeclaration node) {
     var builder = LinkedNodeBuilder.methodDeclaration(
+      executable_isAsynchronous: node.body?.isAsynchronous ?? false,
+      executable_isGenerator: node.body?.isGenerator ?? false,
       methodDeclaration_body: node.body?.accept(this),
       methodDeclaration_externalKeyword: _getToken(node.externalKeyword),
       methodDeclaration_formalParameters: node.parameters?.accept(this),
diff --git a/pkg/analyzer/lib/src/summary2/lazy_ast.dart b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
index 14aab50..5b10d20 100644
--- a/pkg/analyzer/lib/src/summary2/lazy_ast.dart
+++ b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
@@ -990,6 +990,24 @@
     return node.getProperty(_key);
   }
 
+  static bool isAsynchronous(FunctionExpression node) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return lazy.data.executable_isAsynchronous;
+    } else {
+      return node.body.isAsynchronous;
+    }
+  }
+
+  static bool isGenerator(FunctionExpression node) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return lazy.data.executable_isGenerator;
+    } else {
+      return node.body.isGenerator;
+    }
+  }
+
   static void readBody(
     AstBinaryReader reader,
     FunctionExpression node,
@@ -1363,6 +1381,24 @@
     }
   }
 
+  static bool isAsynchronous(MethodDeclaration node) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return lazy.data.executable_isAsynchronous;
+    } else {
+      return node.body.isAsynchronous;
+    }
+  }
+
+  static bool isGenerator(MethodDeclaration node) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return lazy.data.executable_isGenerator;
+    } else {
+      return node.body.isGenerator;
+    }
+  }
+
   static void readBody(
     AstBinaryReader reader,
     MethodDeclaration node,
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index d37d6bd..fa3f72c 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -760,8 +760,18 @@
   }
 
   bool isAsynchronous(AstNode node) {
-    var body = _getFunctionBody(node);
-    return body.isAsynchronous;
+    if (node is ConstructorDeclaration) {
+      return false;
+    } else if (node is FunctionDeclaration) {
+      LazyFunctionDeclaration.readFunctionExpression(_astReader, node);
+      return isAsynchronous(node.functionExpression);
+    } else if (node is FunctionExpression) {
+      return LazyFunctionExpression.isAsynchronous(node);
+    } else if (node is MethodDeclaration) {
+      return LazyMethodDeclaration.isAsynchronous(node);
+    } else {
+      throw UnimplementedError('${node.runtimeType}');
+    }
   }
 
   bool isAsyncKeyword(int token) {
@@ -836,8 +846,18 @@
   }
 
   bool isGenerator(AstNode node) {
-    var body = _getFunctionBody(node);
-    return body.isGenerator;
+    if (node is ConstructorDeclaration) {
+      return false;
+    } else if (node is FunctionDeclaration) {
+      LazyFunctionDeclaration.readFunctionExpression(_astReader, node);
+      return isGenerator(node.functionExpression);
+    } else if (node is FunctionExpression) {
+      return LazyFunctionExpression.isGenerator(node);
+    } else if (node is MethodDeclaration) {
+      return LazyMethodDeclaration.isGenerator(node);
+    } else {
+      throw UnimplementedError('${node.runtimeType}');
+    }
   }
 
   bool isGetter(AstNode node) {
@@ -1096,24 +1116,6 @@
     return node.members;
   }
 
-  FunctionBody _getFunctionBody(AstNode node) {
-    if (node is ConstructorDeclaration) {
-      LazyConstructorDeclaration.readBody(_astReader, node);
-      return node.body;
-    } else if (node is FunctionDeclaration) {
-      LazyFunctionDeclaration.readFunctionExpression(_astReader, node);
-      return _getFunctionBody(node.functionExpression);
-    } else if (node is FunctionExpression) {
-      LazyFunctionExpression.readBody(_astReader, node);
-      return node.body;
-    } else if (node is MethodDeclaration) {
-      LazyMethodDeclaration.readBody(_astReader, node);
-      return node.body;
-    } else {
-      throw UnimplementedError('${node.runtimeType}');
-    }
-  }
-
   NodeList<Annotation> _getPartDirectiveAnnotation() {
     var definingContext = libraryContext.definingUnit;
     var unit = definingContext.unit;