Repository: akvelon/flutter-code-editor
Pull request #238 (2023-05-17 06:21:09)

Issue225 fix suggestion error


Patch:
diff --git a/lib/src/wip/autocomplete/popup.dart b/lib/src/wip/autocomplete/popup.dart
index 90e2894..5035d8f 100644
--- a/lib/src/wip/autocomplete/popup.dart
+++ b/lib/src/wip/autocomplete/popup.dart
@@ -47,6 +47,7 @@ class PopupState extends State<Popup> {
   final pageStorageBucket = PageStorageBucket();
   @override
   void initState() {
+    widget.controller.reset();
     widget.controller.addListener(rebuild);
     super.initState();
   }
diff --git a/lib/src/wip/autocomplete/popup_controller.dart b/lib/src/wip/autocomplete/popup_controller.dart
index bbbc388..cbfc05d 100644
--- a/lib/src/wip/autocomplete/popup_controller.dart
+++ b/lib/src/wip/autocomplete/popup_controller.dart
@@ -7,7 +7,7 @@ class PopupController extends ChangeNotifier {
   bool shouldShow = false;
   bool enabled = true;
 
-  final ItemScrollController itemScrollController = ItemScrollController();
+  ItemScrollController itemScrollController = ItemScrollController();
   final ItemPositionsListener itemPositionsListener =
       ItemPositionsListener.create();
 
@@ -23,6 +23,10 @@ class PopupController extends ChangeNotifier {
 
   int get selectedIndex => _selectedIndex;
 
+  void reset() {
+    itemScrollController = ItemScrollController();
+  }
+
   void show(List<String> suggestions) {
     if (enabled == false) {
       return;


Test patch:
diff --git a/test/src/code_modifiers/controller_insertion_test.dart b/test/src/code_modifiers/controller_insertion_test.dart
new file mode 100644
index 0000000..9019e70
--- /dev/null
+++ b/test/src/code_modifiers/controller_insertion_test.dart
@@ -0,0 +1,149 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_code_editor/flutter_code_editor.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+  test('Insertion modifier test', () {
+    const examples = [
+      //
+      _Example(
+        'Add backticks',
+        initialValue: TextEditingValue(
+          text: 'dict',
+          //     \ cursor
+          selection: TextSelection.collapsed(offset: 0),
+        ),
+        expected: TextEditingValue(
+          text: '``dict',
+          //      \ cursor
+          selection: TextSelection.collapsed(offset: 1),
+        ),
+        inputChar: '`',
+      ),
+
+      _Example(
+        'Add char at the start of the string (braces)',
+        initialValue: TextEditingValue(
+          text: 'dict',
+          //     \ cursor
+          selection: TextSelection.collapsed(offset: 0),
+        ),
+        expected: TextEditingValue(
+          text: '{}dict',
+          //      \ cursor
+          selection: TextSelection.collapsed(offset: 1),
+        ),
+        inputChar: '{',
+      ),
+
+      _Example(
+        'Add char in the middle of the string (parentheses)',
+        initialValue: TextEditingValue(
+          text: 'print',
+          //        \ cursor
+          selection: TextSelection.collapsed(offset: 3),
+        ),
+        expected: TextEditingValue(
+          text: 'pri()nt',
+          //         \ cursor
+          selection: TextSelection.collapsed(offset: 4),
+        ),
+        inputChar: '(',
+      ),
+
+      _Example(
+        'Add char at the end of the string (brackets)',
+        initialValue: TextEditingValue(
+          text: 'print',
+          //          \ cursor
+          selection: TextSelection.collapsed(offset: 5),
+        ),
+        expected: TextEditingValue(
+          text: 'print[]',
+          //           \ cursor
+          selection: TextSelection.collapsed(offset: 6),
+        ),
+        inputChar: '[',
+      ),
+
+      _Example(
+        'Add close char before same close char (double quotes)',
+        initialValue: TextEditingValue(
+          text: 'string"',
+          //           \ cursor
+          selection: TextSelection.collapsed(offset: 6),
+        ),
+        expected: TextEditingValue(
+          text: 'string"""',
+          //            \ cursor
+          selection: TextSelection.collapsed(offset: 7),
+        ),
+        inputChar: '"',
+      ),
+
+      _Example(
+        'Empty initial string (single quotes)',
+        initialValue: TextEditingValue(
+          // ignore: avoid_redundant_argument_values
+          text: '',
+          //     \ cursor
+          selection: TextSelection.collapsed(offset: 0),
+        ),
+        expected: TextEditingValue(
+          text: '\'\'',
+          //       \ cursor
+          selection: TextSelection.collapsed(offset: 1),
+        ),
+        inputChar: '\'',
+      ),
+    ];
+
+    for (final example in examples) {
+      final controller = CodeController();
+      controller.value = example.initialValue;
+      controller.value = _addCharToSelectedPosition(
+        controller.value,
+        example.inputChar,
+      );
+
+      expect(
+        controller.value,
+        example.expected,
+        reason: example.name,
+      );
+    }
+  });
+}
+
+TextEditingValue _addCharToSelectedPosition(
+  TextEditingValue value,
+  String char,
+) {
+  final selection = value.selection;
+  final text = value.text;
+
+  final newText = text.substring(0, selection.start) +
+      char +
+      text.substring(selection.start);
+
+  return TextEditingValue(
+    text: newText,
+    selection: TextSelection.collapsed(
+      offset: selection.start + char.length,
+    ),
+  );
+}
+
+class _Example {
+  final String name;
+  final TextEditingValue initialValue;
+  final TextEditingValue expected;
+  final String inputChar;
+
+  const _Example(
+    this.name, {
+    required this.initialValue,
+    required this.expected,
+    required this.inputChar,
+  });
+}
diff --git a/test/src/code_modifiers/insertion_test.dart b/test/src/code_modifiers/insertion_test.dart
index c4129e0..5b7b338 100644
--- a/test/src/code_modifiers/insertion_test.dart
+++ b/test/src/code_modifiers/insertion_test.dart
@@ -1,178 +1,75 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_code_editor/flutter_code_editor.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_code_editor/src/code_field/editor_params.dart';
 import 'package:flutter_code_editor/src/code_modifiers/insertion.dart';
 import 'package:flutter_test/flutter_test.dart';
 
 void main() {
-  test('Insertion modifier test', () {
-    const examples = [
-      //
-      _Example(
-        'Add close char at the start of the string',
-        initialValue: TextEditingValue(
-          text: 'dict',
-          //     \ cursor
-          selection: TextSelection.collapsed(offset: 0),
-        ),
-        expected: TextEditingValue(
-          text: '{}dict',
-          //      \ cursor
-          selection: TextSelection.collapsed(offset: 1),
-        ),
-        inputChar: '{',
-      ),
+  test('inserts at the start of string correctly', () {
+    const modifier = InsertionCodeModifier(openChar: '1', closeString: '23');
+    const text = 'Hello World';
+    final selection = TextSelection.fromPosition(const TextPosition(offset: 0));
+    const editorParams = EditorParams();
 
-      _Example(
-        'Add close char in the middle of the string',
-        initialValue: TextEditingValue(
-          text: 'print',
-          //        \ cursor
-          selection: TextSelection.collapsed(offset: 3),
-        ),
-        expected: TextEditingValue(
-          text: 'pri()nt',
-          //         \ cursor
-          selection: TextSelection.collapsed(offset: 4),
-        ),
-        inputChar: '(',
-      ),
+    final result = modifier.updateString(text, selection, editorParams);
 
-      _Example(
-        'Add close char at the end of the string',
-        initialValue: TextEditingValue(
-          text: 'print',
-          //          \ cursor
-          selection: TextSelection.collapsed(offset: 5),
-        ),
-        expected: TextEditingValue(
-          text: 'print[]',
-          //           \ cursor
-          selection: TextSelection.collapsed(offset: 6),
-        ),
-        inputChar: '[',
-      ),
-
-      _Example(
-        'Add close with several close chars',
-        initialValue: TextEditingValue(
-          text: 'string',
-          //           \ cursor
-          selection: TextSelection.collapsed(offset: 6),
-        ),
-        expected: TextEditingValue(
-          text: 'string123',
-          //            \ cursor
-          selection: TextSelection.collapsed(offset: 7),
-        ),
-        inputChar: '1',
-        insertedString: '23',
-      ),
+    expect(result!.text, '123Hello World');
+    expect(result.selection.baseOffset, 1);
+    expect(result.selection.extentOffset, 1);
+  });
 
-      _Example(
-        'Add close char before same close char',
-        initialValue: TextEditingValue(
-          text: 'string)',
-          //           \ cursor
-          selection: TextSelection.collapsed(offset: 6),
-        ),
-        expected: TextEditingValue(
-          text: 'string())',
-          //            \ cursor
-          selection: TextSelection.collapsed(offset: 7),
-        ),
-        inputChar: '(',
-      ),
+  test('inserts in the middle of string correctly', () {
+    const modifier = InsertionCodeModifier(openChar: '1', closeString: '23');
+    const text = 'Hello World';
+    final selection = TextSelection.fromPosition(const TextPosition(offset: 5));
+    const editorParams = EditorParams();
 
-      _Example(
-        'Empty initial string',
-        initialValue: TextEditingValue(
-          // ignore: avoid_redundant_argument_values
-          text: '',
-          //     \ cursor
-          selection: TextSelection.collapsed(offset: 0),
-        ),
-        expected: TextEditingValue(
-          text: '()',
-          //      \ cursor
-          selection: TextSelection.collapsed(offset: 1),
-        ),
-        inputChar: '(',
-      ),
-    ];
+    final result = modifier.updateString(text, selection, editorParams);
 
-    for (final example in examples) {
-      final additionalModifier = example.insertedString != null
-          ? InsertionCodeModifier(
-              openChar: example.inputChar,
-              closeString: example.insertedString!,
-            )
-          : null;
+    expect(result!.text, 'Hello123 World');
+    expect(result.selection.baseOffset, 6);
+    expect(result.selection.extentOffset, 6);
+  });
 
-      if (additionalModifier != null &&
-          CodeController.defaultCodeModifiers.any(
-            (e) =>
-                e is InsertionCodeModifier && e.openChar == example.inputChar,
-          )) {
-        fail('Modifier for ${example.inputChar} already exists');
-      }
+  test('inserts at the end of string correctly', () {
+    const modifier = InsertionCodeModifier(openChar: '1', closeString: '23');
+    const text = 'Hello World';
+    final selection =
+        TextSelection.fromPosition(const TextPosition(offset: text.length));
+    const editorParams = EditorParams();
 
-      late CodeController controller;
+    final result = modifier.updateString(text, selection, editorParams);
 
-      if (additionalModifier == null) {
-        controller = CodeController();
-      } else {
-        controller = CodeController(
-          modifiers: CodeController.defaultCodeModifiers + [additionalModifier],
-        );
-      }
+    expect(result!.text, 'Hello World123');
+    expect(result.selection.baseOffset, text.length + 1);
+    expect(result.selection.extentOffset, text.length + 1);
+  });
 
-      controller.value = example.initialValue;
+  test('inserts in the middle of string with selection correctly', () {
+    const modifier = InsertionCodeModifier(openChar: '1', closeString: '23');
+    const text = 'Hello World';
+    const selection = TextSelection(
+      baseOffset: 5,
+      extentOffset: 7,
+    );
+    const editorParams = EditorParams();
 
-      controller.value = _addCharToSelectedPosition(
-        controller.value,
-        example.inputChar,
-      );
+    final result = modifier.updateString(text, selection, editorParams);
 
-      expect(
-        controller.value,
-        example.expected,
-        reason: example.name,
-      );
-    }
+    expect(result!.text, 'Hello123orld');
+    expect(result.selection.baseOffset, 6);
+    expect(result.selection.extentOffset, 6);
   });
-}
-
-TextEditingValue _addCharToSelectedPosition(
-  TextEditingValue value,
-  String char,
-) {
-  final selection = value.selection;
-  final text = value.text;
 
-  final newText = text.substring(0, selection.start) +
-      char +
-      text.substring(selection.start);
-
-  return TextEditingValue(
-    text: newText,
-    selection: TextSelection.collapsed(
-      offset: selection.start + char.length,
-    ),
-  );
-}
+  test('inserts at empty string correctly', () {
+    const modifier = InsertionCodeModifier(openChar: '1', closeString: '23');
+    const text = '';
+    final selection = TextSelection.fromPosition(const TextPosition(offset: 0));
+    const editorParams = EditorParams();
 
-class _Example {
-  final String name;
-  final TextEditingValue initialValue;
-  final TextEditingValue expected;
-  final String inputChar;
-  final String? insertedString;
+    final result = modifier.updateString(text, selection, editorParams);
 
-  const _Example(
-    this.name, {
-    required this.initialValue,
-    required this.expected,
-    required this.inputChar,
-    this.insertedString,
+    expect(result!.text, '123');
+    expect(result.selection.baseOffset, 1);
+    expect(result.selection.extentOffset, 1);
   });
 }