Rewritten a little.
diff --git a/tool/update_sdk.dart b/tool/update_sdk.dart
index 122127f..2ef23c8 100644
--- a/tool/update_sdk.dart
+++ b/tool/update_sdk.dart
@@ -20,34 +20,16 @@
 // - `-n` for dry-run.
 void main(List<String> args) {
   try {
-    var flagErrors = false;
-    // General use of verbosity levels:
-    // 0: No extra output.
-    // 1+: Say what is done
-    // 2+: Also say when no change is made.
-    var verbose = 0;
-    var dryRun = false;
-    var nonFlagArgs = <String>[];
-    for (var arg in args) {
-      if (arg.startsWith('-')) {
-        for (var i = 1; i < arg.length; i++) {
-          switch (arg[i]) {
-            case 'n':
-              dryRun = true;
-            case 'v':
-              verbose++;
-            case var char:
-              stderr.writeln('Invalid flag: "$char"');
-              flagErrors = true;
-          }
-        }
-      } else {
-        nonFlagArgs.add(arg);
-      }
-    }
-    if (flagErrors) {
-      stderr.writeln(usage);
-      exit(1);
+    var (
+      int verbose,
+      bool dryRun,
+      File? experimentsFile,
+      Version? targetVersion,
+    ) = _parseArguments(args);
+
+    var stylePackageDir = _findStylePackageDir();
+    if (verbose > 0) {
+      stdout.writeln('dart_style root: ${stylePackageDir.path}');
     }
     if (verbose > 1) {
       stdout.writeln('Verbosity: $verbose');
@@ -56,44 +38,42 @@
       if (dryRun || verbose > 1) stdout.writeln('Dry-run: $dryRun');
     }
 
-    var stylePackageDir = _findStylePackageDir();
-    if (verbose > 0) {
-      stdout.writeln('dart_style root: ${stylePackageDir.path}');
+    if (experimentsFile == null) {
+      experimentsFile = _findExperimentsFile();
+      if (experimentsFile == null) {
+        stderr
+          ..writeln('Cannot find experiments file or SDK directory,')
+          ..writeln('provide path to either on command line.')
+          ..writeln(usage);
+        exit(1);
+        return; // Unreachable, but `exit` has return type `void`.
+      }
+      if (verbose > 0) {
+        stdout.writeln('Experiments file found: ${experimentsFile.path}');
+      }
+    } else if (verbose > 0) {
+      stdout.writeln(
+        'Experiments file from command line: ${experimentsFile.path}',
+      );
     }
-    if (findExperimentsFile(nonFlagArgs) case var experimentsFile?) {
-      // A version number on the command line will be "current version",
-      // otherwise use the maximal version of released experiments in the
-      // experiments file.
-      Version? version;
-      var experiments = _parseExperiments(experimentsFile);
-      for (var arg in nonFlagArgs) {
-        if (Version.tryParse(arg) case var explicitVersion?) {
-          version = explicitVersion;
-          if (verbose > 0) {
-            stdout.writeln('SDK version from command line: $version');
-          }
-          break;
-        }
-      }
-      if (version == null) {
-        version = experiments.values.nonNulls.reduce(Version.max);
-        if (verbose > 0) {
-          stdout.writeln('SDK version from experiments: $version');
-        }
-      }
-
-      Updater(
-        stylePackageDir,
-        version,
-        experiments,
-        verbose: verbose,
-        dryRun: dryRun,
-      ).run();
-    } else {
-      stderr.writeln('Cannot find experiments file.');
-      stderr.writeln(usage);
+    var experiments = _parseExperiments(experimentsFile);
+    var latestReleasedExperiment = experiments.values.fold<Version?>(
+      null,
+      Version.maxOrNull,
+    );
+    if (latestReleasedExperiment == null) {
+      stderr.writeln('No released experiments in experiments file.');
       exit(1);
+      return;
     }
+
+    Updater(
+      stylePackageDir,
+      targetVersion ?? latestReleasedExperiment,
+      experiments,
+      verbose: verbose,
+      dryRun: dryRun,
+    ).run();
   } catch (e) {
     if (e case (:int exitCode)) {
       stdout.flush().then((_) {
@@ -105,6 +85,64 @@
   }
 }
 
+(int verbose, bool dryRun, File? experimentsFile, Version? version)
+_parseArguments(List<String> args) {
+  // Parse argument list.
+  var flagErrors = false;
+  // General use of verbosity levels:
+  // 0: No extra output.
+  // 1+: Say what is done.
+  // 2+: Also say when no change is made (what is *not* done).
+  var verbose = 0;
+  var dryRun = false;
+  var printHelp = false;
+  File? experimentsFile;
+  Version? targetVersion;
+  for (var arg in args) {
+    if (arg.startsWith('-')) {
+      for (var i = 1; i < arg.length; i++) {
+        switch (arg[i]) {
+          case 'n':
+            dryRun = true;
+          case 'v':
+            verbose++;
+          case 'h':
+            printHelp = true;
+          case var char:
+            stderr.writeln('Invalid flag: "$char"');
+            flagErrors = true;
+        }
+      }
+    } else if (Version.tryParse(arg) case var version?) {
+      if (targetVersion != null) {
+        stderr.writeln(
+          'More than one version argument: $targetVersion, $version',
+        );
+        flagErrors = true;
+      }
+      targetVersion = version;
+    } else if (_checkExperimentsFileOrSdk(arg) case var file?) {
+      if (experimentsFile != null) {
+        stderr.writeln('More than one experiments or SDK argument: $arg');
+        flagErrors = true;
+      }
+      experimentsFile = file;
+    } else {
+      stderr.writeln('Unrecognized argument: $arg');
+      flagErrors = true;
+    }
+  }
+  if (flagErrors) {
+    stderr.writeln(usage);
+    exit(1);
+  }
+  if (printHelp) {
+    stdout.writeln(usage);
+    exit(0);
+  }
+  return (verbose, dryRun, experimentsFile, targetVersion);
+}
+
 class Updater {
   final Directory root;
   final Version currentVersion;
@@ -118,6 +156,7 @@
     this.verbose = 0,
     bool dryRun = false,
   }) : files = FileCache(verbose: verbose, dryRun: dryRun);
+
   void run() {
     _updatePubspec();
     _updateTests();
@@ -174,7 +213,7 @@
   // Captures:
   // - name: The exp-name
   static final _experimentRE = RegExp(r' ?\(experiment (?<name>[\w\-]+)\)');
-  
+
   /// Matches a language version on a format test output line.
   static final _languageVersionRE = RegExp(r'(?<=^<<< )\d+\.\d+\b');
 
@@ -380,6 +419,7 @@
 
 bool _isStylePackageDir(Directory directory) {
   var pubspec = File(p.join(directory.path, 'pubspec.yaml'));
+  // Could read less, but is unlikely to matter.
   return pubspec.existsSync() &&
       LineSplitter.split(pubspec.readAsStringSync()).first ==
           'name: dart_style';
@@ -388,16 +428,19 @@
 // --------------------------------------------------------------------
 // Find version and experiments file in SDK.
 
-File? findExperimentsFile(List<String> args) {
-  // Check if argument is SDK directory.
-  if (args.isNotEmpty) {
-    for (var arg in args) {
-      var directory = Directory(p.absolute(arg));
-      if (directory.existsSync()) {
-        if (_experimentsInSdkDirectory(directory) case var file?) {
-          return file;
-        }
-      }
+/// Used on command line arguments to see if they point to SDK or experiments.
+File? _checkExperimentsFileOrSdk(String path) =>
+    _tryExperimentsFile(path) ?? _tryExperimentsFileInSdkPath(path);
+
+/// Used to find the experiments file if no command line path is given.
+///
+///
+/// Tries to locate an SDK that has a `tools/experimental_features.yaml` file.
+File? _findExperimentsFile() {
+  var envSdk = Platform.environment['DART_SDK'];
+  if (envSdk != null) {
+    if (_tryExperimentsFileInSdkPath(envSdk) case var file?) {
+      return file;
     }
   }
   // Try relative to `dart` executable.
@@ -408,7 +451,7 @@
       if (parent == cursor) break;
       cursor = parent;
       var directory = Directory(cursor);
-      if (_experimentsInSdkDirectory(directory) case var file?) {
+      if (_tryExperimentsFileInSdkDirectory(directory) case var file?) {
         return file;
       }
     }
@@ -416,7 +459,23 @@
   return null;
 }
 
-File? _experimentsInSdkDirectory(Directory directory) {
+File? _tryExperimentsFile(String path) {
+  if (p.basename(path) == 'experimental_features.yaml') {
+    var file = File(path);
+    if (file.existsSync()) return file;
+  }
+  return null;
+}
+
+File? _tryExperimentsFileInSdkPath(String path) {
+  var directory = Directory(p.normalize(path));
+  if (directory.existsSync()) {
+    return _tryExperimentsFileInSdkDirectory(directory);
+  }
+  return null;
+}
+
+File? _tryExperimentsFileInSdkDirectory(Directory directory) {
   var experimentsFile = File(
     p.join(directory.path, 'tools', 'experimental_features.yaml'),
   );
@@ -428,9 +487,13 @@
   final int major, minor;
   Version(this.major, this.minor);
 
-  static Version max(Version v1, Version v2) => v1.compareTo(v2) >= 0 ? v1 : v2;
+  static Version? maxOrNull(Version? v1, Version? v2) {
+    if (v1 == null) return v2;
+    if (v2 == null) return v1;
+    return max(v1, v2);
+  }
 
-  static Version min(Version v1, Version v2) => v1.compareTo(v2) <= 0 ? v1 : v2;
+  static Version max(Version v1, Version v2) => v1 >= v2 ? v1 : v2;
 
   static Version parse(String version) =>
       tryParse(version) ??
@@ -457,17 +520,24 @@
 
   @override
   int get hashCode => Object.hash(major, minor);
+
   @override
   bool operator ==(Object other) =>
       other is Version && major == other.major && minor == other.minor;
+
   @override
   String toString() => '$major.$minor';
 
+  // TODO: (https://dartbug.com/61891) - Remove ignores when issue is fixed.
+  // ignore: unreachable_from_main
   bool operator <(Version other) =>
       major < other.major || major == other.major && minor < other.minor;
+  // ignore: unreachable_from_main
   bool operator <=(Version other) =>
       major < other.major || major == other.major && minor <= other.minor;
+  // ignore: unreachable_from_main
   bool operator >(Version other) => other < this;
+  // ignore: unreachable_from_main
   bool operator >=(Version other) => other <= this;
 }
 
@@ -475,18 +545,21 @@
 String _plural(int number) => number == 1 ? '' : 's';
 
 final String usage = '''
-dart tool/update_sdk.dart [-v] [-n] [VERSION] [SDKDIR]
+dart tool/update_sdk.dart [-h] [-v] [-n] [VERSION] [PATH]
 
 Run from inside dart_style directory to be sure to be able to find it.
 Uses path to `dart` executable to look for SDK directory.
 
-VERSION  SemVer or `major.minor` version.
+VERSION  SemVer or 'major.minor' version.
          If provided, use that as SDK version in pubspec.yaml.
-SDKDIR   Path to SDK repository containing experimental_features.yaml file.
+         If not provided, uses most recent feature release version.
+PATH     Path to "experimental_features.yaml" or to an SDK repository containing
+         that file in "tools".
          Will be searched for if not provided.
 
 -v       Verbosity. Can be used multiple times.
--n       Dryrun. If set, does not write changed files back. 
+-n       Dryrun. If set, does not write changed files back.
+-h       Show usage.
 ''';
 
 void exit(int value) {