Version 2.17.2

* Cherry-pick 2b0cd3c892cc414ae2d585de3f373bdcad446523 to stable
* Cherry-pick 85615ce2e8004a59c62ea6f552fa25e66f3c11bb to stable
* Cherry-pick 5a99a2e4db5560009aae49f8113d7c15ef145aa5 to stable
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ce4c26d..880028a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,13 @@
+## 2.17.2 - 2022-06-01
+
+This is a patch release that fixes:
+
+- a Dart VM compiler crash (issue [#100375][]).
+- code completion when writing method overrides (issue [#49086][]).
+
+[#100375]: https://github.com/flutter/flutter/issues/100375
+[#49086]: https://github.com/dart-lang/sdk/issues/49086
+
 ## 2.17.1 - 2022-05-18
 
 This is a patch release that fixes:
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart b/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
index 69e49fe..1fbda62 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
@@ -17,7 +17,7 @@
   var matcher = FuzzyMatcher(pattern, matchStyle: MatchStyle.SYMBOL);
 
   double score(CompletionSuggestionBuilder suggestion) {
-    var textToMatch = suggestion.completion;
+    var textToMatch = suggestion.textToMatch;
 
     if (suggestion.kind == CompletionSuggestionKind.KEYWORD ||
         suggestion.kind == CompletionSuggestionKind.NAMED_ARGUMENT) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index aeb07b2..a784e8a 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -41,6 +41,9 @@
   /// See [CompletionSuggestion.relevance].
   int get relevance;
 
+  /// Return the text that should be matched against the filter.
+  String get textToMatch;
+
   CompletionSuggestion build();
 }
 
@@ -82,6 +85,9 @@
   }
 
   @override
+  String get textToMatch => completion;
+
+  @override
   CompletionSuggestion build() {
     return CompletionSuggestion(
       kind,
@@ -967,7 +973,10 @@
         displayText: displayText);
     suggestion.element = protocol.convertElement(element,
         withNullability: _isNonNullableByDefault);
-    _addSuggestion(suggestion);
+    _addSuggestion(
+      suggestion,
+      textToMatchOverride: element.displayName,
+    );
   }
 
   /// Add a suggestion for a [parameter].
@@ -1182,9 +1191,15 @@
 
   /// Add the given [suggestion] if it isn't shadowed by a previously added
   /// suggestion.
-  void _addSuggestion(protocol.CompletionSuggestion suggestion) {
+  void _addSuggestion(
+    protocol.CompletionSuggestion suggestion, {
+    String? textToMatchOverride,
+  }) {
     _addBuilder(
-      ValueCompletionSuggestionBuilder(suggestion),
+      ValueCompletionSuggestionBuilder(
+        suggestion,
+        textToMatchOverride: textToMatchOverride,
+      ),
     );
   }
 
@@ -1528,8 +1543,12 @@
 /// [CompletionSuggestionBuilder] that is based on a [CompletionSuggestion].
 class ValueCompletionSuggestionBuilder implements CompletionSuggestionBuilder {
   final CompletionSuggestion _suggestion;
+  final String? _textToMatchOverride;
 
-  ValueCompletionSuggestionBuilder(this._suggestion);
+  ValueCompletionSuggestionBuilder(
+    this._suggestion, {
+    String? textToMatchOverride,
+  }) : _textToMatchOverride = textToMatchOverride;
 
   @override
   String get completion => _suggestion.completion;
@@ -1544,6 +1563,9 @@
   int get relevance => _suggestion.relevance;
 
   @override
+  String get textToMatch => _textToMatchOverride ?? completion;
+
+  @override
   CompletionSuggestion build() {
     return _suggestion;
   }
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_check.dart b/pkg/analysis_server/test/services/completion/dart/completion_check.dart
index a7094e8..ff98794 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_check.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_check.dart
@@ -154,6 +154,14 @@
   }
 
   @useResult
+  CheckTarget<String?> get displayText {
+    return nest(
+      value.suggestion.displayText,
+      (selected) => 'has displayText ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
   CheckTarget<String?> get docComplete {
     return nest(
       value.suggestion.docComplete,
@@ -402,6 +410,18 @@
   }
 
   @useResult
+  CheckTarget<Iterable<CompletionSuggestionForTesting>> get overrides {
+    var result = value
+        .where((suggestion) =>
+            suggestion.suggestion.kind == CompletionSuggestionKind.OVERRIDE)
+        .toList();
+    return nest(
+      result,
+      (selected) => 'overrides ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
   CheckTarget<Iterable<CompletionSuggestionForTesting>> get withElementClass {
     return nest(
       value.where((e) {
diff --git a/pkg/analysis_server/test/services/completion/dart/location/class_body_test.dart b/pkg/analysis_server/test/services/completion/dart/location/class_body_test.dart
index d473b9f..ca3535f 100644
--- a/pkg/analysis_server/test/services/completion/dart/location/class_body_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/location/class_body_test.dart
@@ -18,14 +18,14 @@
 
 @reflectiveTest
 class ClassBodyTest1 extends AbstractCompletionDriverTest
-    with ClassBodyTestCases {
+    with ClassBodyTestCases, OverrideTestCases {
   @override
   TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
 }
 
 @reflectiveTest
 class ClassBodyTest2 extends AbstractCompletionDriverTest
-    with ClassBodyTestCases {
+    with ClassBodyTestCases, OverrideTestCases {
   @override
   TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
 }
@@ -311,6 +311,79 @@
   }
 }
 
+mixin OverrideTestCases on AbstractCompletionDriverTest {
+  Future<void> test_class_method_fromExtends() async {
+    final response = await getTestCodeSuggestions('''
+class A {
+  void foo01() {}
+}
+
+class B extends A {
+  foo^
+}
+''');
+
+    check(response).suggestions.overrides.includesAll([
+      (suggestion) => suggestion
+        ..displayText.isEqualTo('foo01() { … }')
+        ..hasSelection(offset: 60, length: 14)
+        ..completion.isEqualTo(r'''
+@override
+  void foo01() {
+    // TODO: implement foo01
+    super.foo01();
+  }'''),
+    ]);
+  }
+
+  Future<void> test_class_method_fromImplements() async {
+    final response = await getTestCodeSuggestions('''
+class A {
+  void foo01() {}
+}
+
+class B implements A {
+  foo^
+}
+''');
+
+    check(response).suggestions.overrides.includesAll([
+      (suggestion) => suggestion
+        ..displayText.isEqualTo('foo01() { … }')
+        ..hasSelection(offset: 55)
+        ..completion.isEqualTo(r'''
+@override
+  void foo01() {
+    // TODO: implement foo01
+  }'''),
+    ]);
+  }
+
+  Future<void> test_class_method_fromWith() async {
+    final response = await getTestCodeSuggestions('''
+mixin M {
+  void foo01() {}
+}
+
+class A with M {
+  foo^
+}
+''');
+
+    check(response).suggestions.overrides.includesAll([
+      (suggestion) => suggestion
+        ..displayText.isEqualTo('foo01() { … }')
+        ..hasSelection(offset: 60, length: 14)
+        ..completion.isEqualTo(r'''
+@override
+  void foo01() {
+    // TODO: implement foo01
+    super.foo01();
+  }'''),
+    ]);
+  }
+}
+
 class _Context {
   final bool isClass;
   final bool isMixin;
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 2322191..c8069cd 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -995,6 +995,15 @@
 
       // We have a contributor that looks at the type, but it is syntactic.
       if (parent is VariableDeclaration && parent.name == node) {
+        final parent2 = parent.parent;
+        final parent3 = parent2?.parent;
+        // `class A { foo^ }` looks like `class A { <noType> foo; }`.
+        if (parent2 is VariableDeclarationList &&
+            parent2.type == null &&
+            parent3 is FieldDeclaration &&
+            parent3.semicolon.isSynthetic) {
+          return false;
+        }
         return true;
       }
     }
diff --git a/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart b/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart
index e9b7143..7d55077 100644
--- a/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart
@@ -130,6 +130,22 @@
     result.assertResolvedNodes([]);
   }
 
+  test_classDeclaration_body_identifier() async {
+    var result = await _resolveTestCode(r'''
+class A {}
+
+class B {
+  void foo() {}
+
+  bar^
+}
+''');
+
+    result.assertResolvedNodes([
+      'bar;',
+    ]);
+  }
+
   test_constructorDeclaration_body() async {
     var result = await _resolveTestCode(r'''
 class A {}
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 30f6bec..829f715 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -2389,21 +2389,21 @@
         return left()->definition();
       } else if (rhs == 0) {
         return right()->definition();
-      } else if (rhs == 2) {
-        const int64_t shift_1 = 1;
-        ConstantInstr* constant_1 =
-            flow_graph->GetConstant(Smi::Handle(Smi::New(shift_1)));
+      } else if ((rhs > 0) && Utils::IsPowerOfTwo(rhs)) {
+        const int64_t shift_amount = Utils::ShiftForPowerOfTwo(rhs);
+        ConstantInstr* constant_shift_amount = flow_graph->GetConstant(
+            Smi::Handle(Smi::New(shift_amount)), representation());
         BinaryIntegerOpInstr* shift = BinaryIntegerOpInstr::Make(
             representation(), Token::kSHL, left()->CopyWithType(),
-            new Value(constant_1), GetDeoptId(), can_overflow(),
+            new Value(constant_shift_amount), GetDeoptId(), can_overflow(),
             is_truncating(), range(), SpeculativeModeOfInputs());
         if (shift != nullptr) {
           // Assign a range to the shift factor, just in case range
           // analysis no longer runs after this rewriting.
           if (auto shift_with_range = shift->AsShiftIntegerOp()) {
             shift_with_range->set_shift_range(
-                new Range(RangeBoundary::FromConstant(shift_1),
-                          RangeBoundary::FromConstant(shift_1)));
+                new Range(RangeBoundary::FromConstant(shift_amount),
+                          RangeBoundary::FromConstant(shift_amount)));
           }
           flow_graph->InsertBefore(this, shift, env(), FlowGraph::kValue);
           return shift;
diff --git a/tools/VERSION b/tools/VERSION
index c67ab37..419566c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -26,6 +26,6 @@
 CHANNEL stable
 MAJOR 2
 MINOR 17
-PATCH 1
+PATCH 2
 PRERELEASE 0
 PRERELEASE_PATCH 0
\ No newline at end of file