That falls apart the moment you need some non-basic feature like matching open/closed brackets/elements, etc.
Or references. Or refactoring ...
That said, it's not true that it needs to affect features like the ones you mentioned - all you need is to add a facade that gives your tools whatever interface to the buffer they need. As it is, my editor stores its buffer in a separate server process, because it was trivial to do so and gave me a bunch of benefits like multiple clients connecting to the same buffer, which also means I can trivially have out-of-process services augmenting the buffers with additional state lazily without needing to know anything about how the buffers are represented. The server process + a facade for the current buffer implementation + most of the basic editing operations the rest is built on is ~500 lines of code.
One of the things that strikes me is how much effort goes into making these editors work well with absurdly large files, rather than more editors punting on that and having people fall back on specific tools for huge files.
For my own editor I basically decided to ignore large files entirely and fall back on using emacs for the very rare case where I need to open an absurdly large file.
I know that's a luxury Jetbrains doesn't have, because we've come to expect all editors to handle ridiculous sized files well.
But the point being that for reasonably sized files - up to tens of thousands of lines - just an array of strings is more than fast enough.
Even with an editor like my personal one (not really usable for anyone else, though I've started packaging up parts of the code) written in Ruby (which introduces a substantial overhead per string).
I think if I ever decide to make my editor handle really huge files, I'll "just" split them in suitably large chunks and lazily do the necessary processing as needed