It’s been just over a year since
iCompleteMe’s inception. It’s a
hard fork of YouCompleteMe
, a powerful code completion system for Vim.
iCompleteMe
The iCompleteMe
project spawned as an attempt to implement Swift code completion via sourcekitd
into YouCompleteMe
.
The project started as an attempt to build a Swift code completion system ontop
of sourcekitd
for Vim. YouCompleteMe
’s stable and widely used codebase,
made it a good choice for a platform. But, it wasn’t possible to integrate
Swift code completion into YouCompleteMe
in an ad-hoc way: it needed to be
integrated directly into the core source code.
After code completion was working good, it seemed like a great fit to upstream
to YouCompleteMe
. Until it wasn’t. A hard fork ended up being the solution.
The YouCompleteMe team is absolutely a pleasure to work with - the fork
spawned for technical reasons..
YouCompleteMe
YouCompleteMe
consists of several features in addition to code completion
including diagnostics rendering, go to definition, and more. The system
vertically integrates several different backends like Jedi
for Python and
Racerd
for Rust.
Here’s a simplified summary of how YouCompleteMe
completion works:
- Vim
autocmds
and callbacks trigger completion inYouCompleteMe
’s VimScript - The VimScript calls into the completion system. ( Written in Python ).
- The Python code returns code completions to Vim via VimScript
- In the Vim Python process,
YouCompleteMe
gets code completions by delegating to a backend HTTP server,ycmd
. Some completions are computed in the Vim process directly. ycmd
delegates toCompleter
’s which all except the clang one, make HTTP requests to language level servers.- To get semantic completion, the actual language severs interface with program language tools ( like the Swift compiler )
One design advantage of YouCompleteMe
is that the semantic code completion
engines are run in isolated process. Since ycmd
is decoupled from Vim,
it is reusable in other contexts, like emacs. icmd
has recently been
integrated into emacs as well.
Now for the challenges.
Maintainability and Support
The system is a massive polygot project encompassing VimScript, Python 2 ( and 3 ), C++, Boost, and all of third party code: C#, Rust, Java, and more.
As all of these technologies evolve, the project needs to be updated to deal
with changes. iCompleteMe
succeeded in reducing the surface by focusing
exclusively on Swift.
A search of YouCompleteMe
’s Github issues ( and @jerrymarino
’s ), shows
a dedidicated and perpetual effort to hold it all together.
Installation
The standard installation process of YouCompleteMe
expects that the user’s
machine can compile the transitive dependency graph. Building a complex program
like this in arbitrary environments is not for the faint hearted. Installation
is one of the main challenges the project faces.
Namespacing
Since Vim plugins run in a shared process, there was a huge conflict with
YouCompleteMe
. Vim plugin code, global variables and import paths all
conflicted. Most of the YouCompleteMe
code running in Vim’s process had to be
namespaced to iCompleteMe
. This namespacing and literal source renaming
hardened the forking and renders most patches difficult to apply without
significant tooling.
Python
YouCompleteMe
supports both 2 and 3. Keeping python working is effort, even
for Vim its self. For example, using 3.7
pops warnings about deprecated
functionality used in Vim’s
core.
Argument placeholders
There was push back on having custom VimScript for Swift completion. For
function completions, it inserts placeholders where the arguments belong. As
the user tab
’s, argument placeholders are automatically deleted as the cursor
automatically jumps to the argument. For Xcode users, this behavior is
idiomatic. For YouCompleteMe
, this feature isn’t implemented. Clang’s
completion API has long exposed placeholders for methods
The philosophy of all encompassing YouCompleteMe
can’t support language
specific behaviors: the antithesis of a unified experience across all
languages.
Looking forward
iCompleteMe
inherited both the good parts and bad parts of YouCompleteMe
.
Swift brings a lot to the table for Vim plugin development, and SwiftForVim
makes it a reality.
Many problems of YouCompleteMe
could be solved by writing the core engine and
plugin in a single language and distributing it as statically compiled native
binary. This approach would make installation trivial and reduce maintenance
overhead.
The impending Swift rewrite of YouCompleteMe
could improve a lot more.
Here’s a few ideas:
- Leverage the safety and type system of Swift to make it stable.
- Build features in modules that can be reused in other plugins.
- Use a library based approach to reduce complexity, server abstractions, and processes.
- Writing it as functional as possible could make it easier to reason about.
- Strip out all features configuration options. Users instead create variants with permissibly licensed core libraries.
- Move away from an monolithic project and ownership model. A single monolithic code completion system is hard to support and evolve.
Starting up and progress
Things went into motion this early this summer.
1) Break the problem into small reasonable pieces and prototype.
2) SwiftPackageManager.vim is the test ground for prototyping starting with the diagnostics feature.
3) Implement Swift support ( Factor SwiftForVim ) out of SwiftPackageManager.vim
This is just the beginning.