Repository: flutter
Issue: Code quality improvements for text input deltas
Labels: a: text input,framework,f: material design,c: proposal,P3,c: tech-debt,team-design,triaged-design

I'm creating an IME simulator in the flutter_test_robots package so that developers can simulate the kind of input that's used in document editing.

I found some code quality issues that made it difficult for me to get the simulator working. I recommend improving these details.

Please see:
 * Where Flutter handles delta JSON in the channel: https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/services/text_input.dart#L1803
 * Where Flutter deserializes the delta JSON: https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/services/text_editing_delta.dart#L65

Issues:
- **Provide a `toJSON()` for text editing deltas:** I'm sending deltas through the platform channel so that I get maximum correctness in the IME simulation. `TextEditingDelta` has a `fromJSON()` method, but no `toJSON()` method. Moreover, the `fromJSON()` method is very complicated. I found it impossible to read. So I made a guess about how I'm supposed to map values in the JSON blobs that I'm sending.
- **Clean up `TextEditingDelta.fromJSON()`:** As mentioned above, I couldn't visually trace what was happening in the `fromJSON()` method. It's doing a lot more than just de-serializing values and it's unclear what's happening. I recommend taking a look at some of Robert Martin's "clean code" guidelines to help improve the readability of that method.
- **Multiple areas fail silently:** I spent a while carefully tracing my fake JSON through the channel because any time something goes wrong in that channel, it fails silently. For example, I was passing some bad text bounds. This caused a "replace" call in `fromJSON()` to blow up, but I received no indication of this.
- **Conflicting terms for composing region:** In the JSON parsing there are references to the composing `start` and `end` values, and those are used interchangeably with `composingBase` and `composingExtent`. However, those are not the same concepts. As seen in `TextSelection`, `start` and `end` mean "upstream to downstream", but `base` and `extent` mean "a range in a user specified direction".
- **Use constants for message names and parameters:** All the message names are coded with inline strings. This *might* be appropriate for completely private details, but these names aren't private. These names are explicitly listed in the public docs for the channel. Thus, they should be public constants.
- **Offer message (de)serializers:** I mentioned individual delta serialization, but also in general there's no need to make other developers copy and paste the structure of messages. For example, the arguments for a delta message is a `List` that contains an `int`, followed by a `Map` that contains a `"deltas"` key, which then contains the `List` of deltas. Why not wrap that with a public object that others can use to access the data without worrying about the JSON structure?
- **Make it clear that the text input connection needs a special debug reset in tests:** I was hitting test failures with my simulator that I couldn't pin down. By luck, I found this line in the Flutter repo: `TextInputConnection.debugResetId();`. I'm still not sure why I need to call it. My widgets explicitly `close()` the input connection in their `dispose()` methods. Nonetheless, if I try to run more than 1 test at a time, the input connection holds on to the wrong connection ID and I can't connect the text fields in other tests.

You can see the simulator here: 
https://github.com/Flutter-Bounty-Hunters/flutter_test_robots/blob/main/lib/src/input_method_engine.dart

You can see how I'm testing the simulator here:
https://github.com/Flutter-Bounty-Hunters/flutter_test_robots/blob/main/test/flutter_test_robots_ime_test.dart