Merge branch 'master' of https://github.com/dart-lang/linter
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 299bd89..6c33d31 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -50,7 +50,7 @@
 #    - prefer_final_locals
 #    - prefer_is_empty # not recognized
     - prefer_is_not_empty
-#    - prefer_single_quotes
+    - prefer_single_quotes
 #    - public_member_api_docs
 #    - recursive_getter # not recognized
     - slash_for_doc_comments
diff --git a/bin/linter.dart b/bin/linter.dart
index 2e0b12e..52082ff 100644
--- a/bin/linter.dart
+++ b/bin/linter.dart
@@ -31,7 +31,7 @@
     code == unableToProcessExitCode || code == processFileFailedExitCode;
 
 void printUsage(ArgParser parser, IOSink out, [String error]) {
-  var message = "Lints Dart source files and pubspecs.";
+  var message = 'Lints Dart source files and pubspecs.';
   if (error != null) {
     message = error;
   }
@@ -51,11 +51,11 @@
   var parser = new ArgParser(allowTrailingOptions: true);
 
   parser
-    ..addFlag("help",
-        abbr: "h", negatable: false, help: "Show usage information.")
-    ..addFlag("stats",
-        abbr: "s", negatable: false, help: "Show lint statistics.")
-    ..addFlag("benchmark", negatable: false, help: "Show lint benchmarks.")
+    ..addFlag('help',
+        abbr: 'h', negatable: false, help: 'Show usage information.')
+    ..addFlag('stats',
+        abbr: 's', negatable: false, help: 'Show lint statistics.')
+    ..addFlag('benchmark', negatable: false, help: 'Show lint benchmarks.')
     ..addFlag('visit-transitive-closure',
         help: 'Visit the transitive closure of imported/exported libraries.')
     ..addFlag('quiet', abbr: 'q', help: "Don't show individual lint errors.")
@@ -86,21 +86,21 @@
     return;
   }
 
-  if (options["help"]) {
+  if (options['help']) {
     printUsage(parser, outSink);
     return;
   }
 
   if (options.rest.isEmpty) {
     printUsage(parser, errorSink,
-        "Please provide at least one file or directory to lint.");
+        'Please provide at least one file or directory to lint.');
     exitCode = unableToProcessExitCode;
     return;
   }
 
   var lintOptions = initialLintOptions;
 
-  var configFile = options["config"];
+  var configFile = options['config'];
   if (configFile != null) {
     var config = new LintConfig.parse(readFile(configFile));
     lintOptions.configure(config);
@@ -137,7 +137,7 @@
   var packageConfigFile = options['packages'];
 
   if (customPackageRoot != null && packageConfigFile != null) {
-    errorSink.write("Cannot specify both '--package-root' and '--packages.");
+    errorSink.write("Cannot specify both '--package-root' and '--packages'.");
     exitCode = unableToProcessExitCode;
     return;
   }
diff --git a/lib/src/rules/always_put_required_named_parameters_first.dart b/lib/src/rules/always_put_required_named_parameters_first.dart
index a98d97f..e05d493 100644
--- a/lib/src/rules/always_put_required_named_parameters_first.dart
+++ b/lib/src/rules/always_put_required_named_parameters_first.dart
@@ -25,10 +25,10 @@
 ''';
 
 /// The name of `meta` library, used to define analysis annotations.
-String _META_LIB_NAME = "meta";
+String _META_LIB_NAME = 'meta';
 
 /// The name of the top-level variable used to mark a required named parameter.
-String _REQUIRED_VAR_NAME = "required";
+String _REQUIRED_VAR_NAME = 'required';
 
 bool _isRequired(Element element) =>
     element is PropertyAccessorElement &&
diff --git a/lib/src/rules/always_require_non_null_named_parameters.dart b/lib/src/rules/always_require_non_null_named_parameters.dart
index 0ab3fca..eccb65f 100644
--- a/lib/src/rules/always_require_non_null_named_parameters.dart
+++ b/lib/src/rules/always_require_non_null_named_parameters.dart
@@ -38,10 +38,10 @@
 ''';
 
 /// The name of `meta` library, used to define analysis annotations.
-String _META_LIB_NAME = "meta";
+String _META_LIB_NAME = 'meta';
 
 /// The name of the top-level variable used to mark a required named parameter.
-String _REQUIRED_VAR_NAME = "required";
+String _REQUIRED_VAR_NAME = 'required';
 
 bool _isRequired(Element element) =>
     element is PropertyAccessorElement &&
diff --git a/lib/src/rules/always_specify_types.dart b/lib/src/rules/always_specify_types.dart
index b5838cc..6c811b9 100644
--- a/lib/src/rules/always_specify_types.dart
+++ b/lib/src/rules/always_specify_types.dart
@@ -66,11 +66,11 @@
 ''';
 
 /// The name of `meta` library, used to define analysis annotations.
-String _META_LIB_NAME = "meta";
+String _META_LIB_NAME = 'meta';
 
 /// The name of the top-level variable used to mark a Class as having optional
 /// type args.
-String _OPTIONAL_TYPE_ARGS_VAR_NAME = "optionalTypeArgs";
+String _OPTIONAL_TYPE_ARGS_VAR_NAME = 'optionalTypeArgs';
 
 bool _isOptionallyParameterized(ParameterizedType type) {
   List<ElementAnnotation> metadata = type.element?.metadata;
diff --git a/lib/src/rules/non_constant_identifier_names.dart b/lib/src/rules/non_constant_identifier_names.dart
index 6441c1e..abc6bf4 100644
--- a/lib/src/rules/non_constant_identifier_names.dart
+++ b/lib/src/rules/non_constant_identifier_names.dart
@@ -55,9 +55,16 @@
   }
 
   @override
+  visitConstructorDeclaration(ConstructorDeclaration node) {
+    if (node.name != null) {
+      checkIdentifier(node.name);
+    }
+  }
+
+  @override
   visitFormalParameterList(FormalParameterList node) {
     node.parameters.forEach((FormalParameter p) {
-      if (p is! FieldFormalParameter) {
+      if (p is! FieldFormalParameter && p.identifier != null) {
         checkIdentifier(p.identifier, underscoresOk: true);
       }
     });
@@ -83,11 +90,4 @@
       }
     });
   }
-
-  @override
-  visitConstructorDeclaration(ConstructorDeclaration node) {
-    if (node.name != null) {
-      checkIdentifier(node.name);
-    }
-  }
 }
diff --git a/lib/src/rules/prefer_const_constructors_in_immutables.dart b/lib/src/rules/prefer_const_constructors_in_immutables.dart
index a03d849..64b6d82 100644
--- a/lib/src/rules/prefer_const_constructors_in_immutables.dart
+++ b/lib/src/rules/prefer_const_constructors_in_immutables.dart
@@ -36,10 +36,10 @@
 ''';
 
 /// The name of `meta` library, used to define analysis annotations.
-String _META_LIB_NAME = "meta";
+String _META_LIB_NAME = 'meta';
 
 /// The name of the top-level variable used to mark a immutable class.
-String _IMMUTABLE_VAR_NAME = "immutable";
+String _IMMUTABLE_VAR_NAME = 'immutable';
 
 bool _isImmutable(Element element) =>
     element is PropertyAccessorElement &&
diff --git a/lib/src/rules/prefer_contains.dart b/lib/src/rules/prefer_contains.dart
index a728d57..2c7d2f9 100644
--- a/lib/src/rules/prefer_contains.dart
+++ b/lib/src/rules/prefer_contains.dart
@@ -123,7 +123,7 @@
 
     final DartObjectImpl rightValue =
         binaryExpression.rightOperand.accept(visitor);
-    if (rightValue?.type?.name == "int") {
+    if (rightValue?.type?.name == 'int') {
       // Constant is on right side of comparison operator
       _checkConstant(binaryExpression, rightValue.toIntValue(), operator.type);
       return;
@@ -131,7 +131,7 @@
 
     final DartObjectImpl leftValue =
         binaryExpression.leftOperand.accept(visitor);
-    if (leftValue?.type?.name == "int") {
+    if (leftValue?.type?.name == 'int') {
       // Constants is on left side of comparison operator
       _checkConstant(binaryExpression, leftValue.toIntValue(),
           _invertedTokenType(operator.type));
diff --git a/lib/src/rules/prefer_is_empty.dart b/lib/src/rules/prefer_is_empty.dart
index 429c6d6..51bd1f1 100644
--- a/lib/src/rules/prefer_is_empty.dart
+++ b/lib/src/rules/prefer_is_empty.dart
@@ -139,7 +139,7 @@
 
     DartObjectImpl rightValue = binaryExpression.rightOperand.accept(visitor);
 
-    if (rightValue?.type?.name == "int") {
+    if (rightValue?.type?.name == 'int') {
       // Constants is on right side of comparison operator
       int value = rightValue.toIntValue();
       if (value == 0) {
@@ -179,7 +179,7 @@
 
     DartObjectImpl leftValue = binaryExpression.leftOperand.accept(visitor);
 
-    if (leftValue?.type?.name == "int") {
+    if (leftValue?.type?.name == 'int') {
       // Constants is on left side of comparison operator
       int value = leftValue.toIntValue();
 
diff --git a/lib/src/rules/use_to_and_as_if_applicable.dart b/lib/src/rules/use_to_and_as_if_applicable.dart
index b41cf92..5b61f94 100644
--- a/lib/src/rules/use_to_and_as_if_applicable.dart
+++ b/lib/src/rules/use_to_and_as_if_applicable.dart
@@ -46,7 +46,7 @@
 ''';
 
 bool _beginsWithAsOrTo(String name) {
-  final regExp = new RegExp(r"(to|as|_to|_as)[A-Z]", caseSensitive: true);
+  final regExp = new RegExp(r'(to|as|_to|_as)[A-Z]', caseSensitive: true);
   return regExp.matchAsPrefix(name) != null;
 }
 
diff --git a/test/integration_test.dart b/test/integration_test.dart
index 130c066..10dce29 100644
--- a/test/integration_test.dart
+++ b/test/integration_test.dart
@@ -296,9 +296,9 @@
         expect(
             collectingOut.trim(),
             stringContainsInOrder([
-              "Specify exports in a separate section after all imports.",
+              'Specify exports in a separate section after all imports.',
               "export 'dummy.dart';  // LINT",
-              "Specify exports in a separate section after all imports.",
+              'Specify exports in a separate section after all imports.',
               "export 'dummy2.dart';  // LINT",
               '5 files analyzed, 2 issues found, in'
             ]));
@@ -316,29 +316,29 @@
         expect(
             collectingOut.trim(),
             stringContainsInOrder([
-              "Sort directive sections alphabetically.",
+              'Sort directive sections alphabetically.',
               "import 'dart:convert'; // LINT",
-              "Sort directive sections alphabetically.",
+              'Sort directive sections alphabetically.',
               "import 'package:charcode/ascii.dart'; // LINT",
-              "Sort directive sections alphabetically.",
+              'Sort directive sections alphabetically.',
               "import 'package:ansicolor/ansicolor.dart'; // LINT",
-              "Sort directive sections alphabetically.",
+              'Sort directive sections alphabetically.',
               "import 'package:linter/src/formatter.dart'; // LINT",
-              "Sort directive sections alphabetically.",
+              'Sort directive sections alphabetically.',
               "import 'dummy3.dart'; // LINT",
-              "Sort directive sections alphabetically.",
+              'Sort directive sections alphabetically.',
               "import 'dummy2.dart'; // LINT",
-              "Sort directive sections alphabetically.",
+              'Sort directive sections alphabetically.',
               "import 'dummy1.dart'; // LINT",
-              "Sort directive sections alphabetically.",
+              'Sort directive sections alphabetically.',
               "export 'dart:convert'; // LINT",
-              "Sort directive sections alphabetically.",
+              'Sort directive sections alphabetically.',
               "export 'package:charcode/ascii.dart'; // LINT",
-              "Sort directive sections alphabetically.",
+              'Sort directive sections alphabetically.',
               "export 'package:ansicolor/ansicolor.dart'; // LINT",
-              "Sort directive sections alphabetically.",
+              'Sort directive sections alphabetically.',
               "export 'package:linter/src/formatter.dart'; // LINT",
-              "Sort directive sections alphabetically.",
+              'Sort directive sections alphabetically.',
               "export 'dummy1.dart'; // LINT",
               '5 files analyzed, 12 issues found, in'
             ]));
diff --git a/test/mock_sdk.dart b/test/mock_sdk.dart
index d6b6791..4b2e61e 100644
--- a/test/mock_sdk.dart
+++ b/test/mock_sdk.dart
@@ -322,7 +322,7 @@
   Source fromFileUri(Uri uri) {
     String filePath = uri.path;
     String libPath = '/lib';
-    if (!filePath.startsWith("$libPath/")) {
+    if (!filePath.startsWith('$libPath/')) {
       return null;
     }
     for (SdkLibrary library in LIBRARIES) {
@@ -336,7 +336,7 @@
           return null;
         }
       }
-      if (filePath.startsWith("$libraryPath/")) {
+      if (filePath.startsWith('$libraryPath/')) {
         String pathInLibrary = filePath.substring(libraryPath.length + 1);
         String path = '${library.shortName}/$pathInLibrary';
         try {
@@ -365,14 +365,14 @@
   @override
   Source mapDartUri(String dartUri) {
     const Map<String, String> uriToPath = const {
-      "dart:core": "/lib/core/core.dart",
-      "dart:html": "/lib/html/dartium/html_dartium.dart",
-      "dart:async": "/lib/async/async.dart",
-      "dart:async/stream.dart": "/lib/async/stream.dart",
-      "dart:collection": "/lib/collection/collection.dart",
-      "dart:convert": "/lib/convert/convert.dart",
-      "dart:io": "/lib/io/io.dart",
-      "dart:math": "/lib/math/math.dart"
+      'dart:core': '/lib/core/core.dart',
+      'dart:html': '/lib/html/dartium/html_dartium.dart',
+      'dart:async': '/lib/async/async.dart',
+      'dart:async/stream.dart': '/lib/async/stream.dart',
+      'dart:collection': '/lib/collection/collection.dart',
+      'dart:convert': '/lib/convert/convert.dart',
+      'dart:io': '/lib/io/io.dart',
+      'dart:math': '/lib/math/math.dart'
     };
 
     String path = uriToPath[dartUri];
diff --git a/test/mocks.dart b/test/mocks.dart
index 3272085..3d06483 100644
--- a/test/mocks.dart
+++ b/test/mocks.dart
@@ -24,7 +24,7 @@
   }
 
   @override
-  writeln([Object obj = ""]) {
+  writeln([Object obj = '']) {
     buffer.writeln(obj);
   }
 }
diff --git a/tool/rule.dart b/tool/rule.dart
index 5d0781c..328612c 100644
--- a/tool/rule.dart
+++ b/tool/rule.dart
@@ -87,10 +87,10 @@
 
 void updateRuleRegistry(String ruleName) {
   print("Don't forget to update lib/rules.dart with a line like:");
-  print("  ..register(new ${toClassName(ruleName)}())");
-  print("and add your rule to `example/all.yaml`.");
-  print("Then run your test like so:");
-  print("  pub run test -N $ruleName");
+  print('  ..register(new ${toClassName(ruleName)}())');
+  print('and add your rule to `example/all.yaml`.');
+  print('Then run your test like so:');
+  print('  pub run test -N $ruleName');
 }
 
 String _generateClass(String ruleName, String className) => """