Cherry-pick 028ac521805dde0d71a1c97d1063b091fcddfe25 from analyzer to master.

This fixes "Evaluation of this constant expression throws an exception"
during Flutter analysis.

Initial CL: https://dart-review.googlesource.com/c/sdk/+/81750

R=brianwilkerson@google.com, paulberry@google.com

Title: Enum values are always computed, compute even implicit null values of default parameters.
Change-Id: If38dde0490f04bf39119087b5f15a36272e58cab
Reviewed-on: https://dart-review.googlesource.com/c/84041
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 76ee093..3cab468 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -183,15 +183,20 @@
   void computeConstantValue(ConstantEvaluationTarget constant) {
     validator.beforeComputeValue(constant);
     if (constant is ParameterElementImpl) {
-      Expression defaultValue = constant.constantInitializer;
-      if (defaultValue != null) {
-        RecordingErrorListener errorListener = new RecordingErrorListener();
-        ErrorReporter errorReporter =
-            new ErrorReporter(errorListener, constant.source);
-        DartObjectImpl dartObject =
-            defaultValue.accept(new ConstantVisitor(this, errorReporter));
-        constant.evaluationResult =
-            new EvaluationResultImpl(dartObject, errorListener.errors);
+      if (constant.isOptional) {
+        Expression defaultValue = constant.constantInitializer;
+        if (defaultValue != null) {
+          RecordingErrorListener errorListener = new RecordingErrorListener();
+          ErrorReporter errorReporter =
+              new ErrorReporter(errorListener, constant.source);
+          DartObjectImpl dartObject =
+              defaultValue.accept(new ConstantVisitor(this, errorReporter));
+          constant.evaluationResult =
+              new EvaluationResultImpl(dartObject, errorListener.errors);
+        } else {
+          constant.evaluationResult =
+              EvaluationResultImpl(typeProvider.nullObject);
+        }
       }
     } else if (constant is VariableElementImpl) {
       Expression constantInitializer = constant.constantInitializer;
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index e6cab4e..513799f 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1784,6 +1784,9 @@
   }
 
   @override
+  bool get isConstantEvaluated => true;
+
+  @override
   void set isFinal(bool isFinal) {
     assert(false);
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/constant_test.dart b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
new file mode 100644
index 0000000..53a5c74
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2018, 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/src/dart/element/element.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+import 'resolution.dart';
+import 'task_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConstantDriverTest);
+    defineReflectiveTests(ConstantTaskTest);
+  });
+}
+
+@reflectiveTest
+class ConstantDriverTest extends DriverResolutionTest with ConstantMixin {}
+
+abstract class ConstantMixin implements ResolutionTest {
+  test_constantValue_defaultParameter_noDefaultValue() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {
+  const A({int p});
+}
+''');
+    addTestFile(r'''
+import 'a.dart';
+const a = const A();
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    var aLib = findElement.import('package:test/a.dart').importedLibrary;
+    var aConstructor = aLib.getType('A').constructors.single;
+    DefaultParameterElementImpl p = aConstructor.parameters.single;
+
+    // To evaluate `const A()` we have to evaluate `{int p}`.
+    // Even if its value is `null`.
+    expect(p.isConstantEvaluated, isTrue);
+    expect(p.constantValue.isNull, isTrue);
+  }
+
+  test_constFactoryRedirection_super() async {
+    addTestFile(r'''
+class I {
+  const factory I(int f) = B;
+}
+
+class A implements I {
+  final int f;
+
+  const A(this.f);
+}
+
+class B extends A {
+  const B(int f) : super(f);
+}
+
+@I(42)
+main() {}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    var node = findNode.annotation('@I');
+    var value = node.elementAnnotation.constantValue;
+    expect(value.getField('(super)').getField('f').toIntValue(), 42);
+  }
+}
+
+@reflectiveTest
+class ConstantTaskTest extends TaskResolutionTest with ConstantMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/enum_test.dart b/pkg/analyzer/test/src/dart/resolution/enum_test.dart
index d30bf67..930ab7c 100644
--- a/pkg/analyzer/test/src/dart/resolution/enum_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/enum_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/error/codes.dart';
+import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
@@ -44,6 +45,20 @@
     var v = findElement.topVar('v');
     assertElementTypeString(v.type, 'List<Object>');
   }
+
+  test_isConstantEvaluated() async {
+    addTestFile(r'''
+enum E {
+  aaa, bbb
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    expect(findElement.field('aaa').isConstantEvaluated, isTrue);
+    expect(findElement.field('bbb').isConstantEvaluated, isTrue);
+    expect(findElement.field('values').isConstantEvaluated, isTrue);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/resolution/find_element.dart b/pkg/analyzer/test/src/dart/resolution/find_element.dart
index dff0500..4eadf43 100644
--- a/pkg/analyzer/test/src/dart/resolution/find_element.dart
+++ b/pkg/analyzer/test/src/dart/resolution/find_element.dart
@@ -73,21 +73,28 @@
   }
 
   FieldElement field(String name) {
-    for (var type in unitElement.mixins) {
-      for (var field in type.fields) {
+    for (var enum_ in unitElement.enums) {
+      for (var field in enum_.fields) {
         if (field.name == name) {
           return field;
         }
       }
     }
-    for (var type in unitElement.types) {
-      for (var field in type.fields) {
+    for (var mixin in unitElement.mixins) {
+      for (var field in mixin.fields) {
         if (field.name == name) {
           return field;
         }
       }
     }
-    fail('Not found class field: $name');
+    for (var class_ in unitElement.types) {
+      for (var field in class_.fields) {
+        if (field.name == name) {
+          return field;
+        }
+      }
+    }
+    fail('Not found field: $name');
   }
 
   FunctionElement function(String name) {