private void TextBufferChangedOnBackground(object sender, TextContentChangedEventArgs e)
        {
            if (e.Changes.Count == 0)
            {
                return;
            }

            if (e.Changes[0].NewLength == 0)
            {
                state.Sb.Clear();
                return;
            }

            // Check if user is typing into what we're trying to suggest
            if (state.Sb.ToString().StartsWith(e.Changes[0].NewText))
            {
                state.Sb.Remove(0, e.Changes[0].NewLength);
                return;
            }

            // 2.If user is typing a completely different thing, check cache
            //   a. Synchronous cache check
            //   b. If nothing, async query (the function might not query, but whatever)
            var codeBeforeCaret = new SnapshotSpan(view.TextSnapshot,
                                                   0,
                                                   curCaretBufferPosition).GetText();
            var normalized = DocumentProcessor.NormalizeCode(codeBeforeCaret) + e.Changes[0].NewText;
            var completion = state.Cache.GetCompletion(normalized);

            state.Sb.Clear();
            state.Sb.Append(completion);
            if (completion.Length == 0)
            {
                // Used to grab the filename
                view.TextBuffer.Properties.TryGetProperty(typeof(ITextDocument),
                                                          out ITextDocument doc);
                _ = Task.Run(() => RequestServer(normalized, doc));
            }
            else
            {
                state.Sb.Remove(0, e.Changes[0].NewLength);
            }
        }