Take analysis options into account when computing the severity of a strong mode "error".

This allows users to opt into the strong mode hints by turning them into warnings or errors in their analysis options files.

R=leafp@google.com, vsm@google.com
BUG=

Review-Url: https://codereview.chromium.org/2784473004 .
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 695e6dd..463a5c2 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/source/error_processor.dart' show ErrorProcessor;
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart' show StrongModeCode;
@@ -1038,7 +1039,14 @@
   }
 
   void _recordMessage(AstNode node, ErrorCode errorCode, List arguments) {
-    var severity = errorCode.errorSeverity;
+    // Compute the right severity taking the analysis options into account.
+    // We construct a dummy error to make the common case where we end up
+    // ignoring the strong mode message cheaper.
+    var processor = ErrorProcessor.getProcessor(_options,
+        new AnalysisError.forValues(null, -1, 0, errorCode, null, null));
+    var severity =
+        (processor != null) ? processor.severity : errorCode.errorSeverity;
+
     if (severity == ErrorSeverity.ERROR) _failure = true;
     if (severity != ErrorSeverity.INFO || _options.strongModeHints) {
       int begin = node is AnnotatedNode
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 41444a0..fd3bf9d 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/task/options.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -2498,6 +2499,61 @@
     verify([source]);
   }
 
+  test_strongMode_downCastCompositeNoHint() async {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.strongMode = true;
+    options.strongModeHints = false;
+    resetWith(options: options);
+    Source source = addSource(r'''
+main() {
+  List dynamicList = [ ];
+  List<int> list = dynamicList;
+  print(list);
+}''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  test_strongMode_downCastCompositeHint() async {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.strongMode = true;
+    options.strongModeHints = true;
+    resetWith(options: options);
+    Source source = addSource(r'''
+main() {
+  List dynamicList = [ ];
+  List<int> list = dynamicList;
+  print(list);
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [StrongModeCode.DOWN_CAST_COMPOSITE]);
+    verify([source]);
+  }
+
+  test_strongMode_downCastCompositeWarn() async {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    applyToAnalysisOptions(options, {
+      AnalyzerOptions.analyzer: {
+        AnalyzerOptions.errors: {
+          StrongModeCode.DOWN_CAST_COMPOSITE.name: 'warning'
+        },
+      }
+    });
+    options.strongMode = true;
+    options.strongModeHints = false;
+    resetWith(options: options);
+    Source source = addSource(r'''
+main() {
+  List dynamicList = [ ];
+  List<int> list = dynamicList;
+  print(list);
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [StrongModeCode.DOWN_CAST_COMPOSITE]);
+    verify([source]);
+  }
+
   test_typeCheck_type_is_Null() async {
     Source source = addSource(r'''
 m(i) {