Skip to content

codemirror blob: Integrate with Sourcegraph extensions

Administrator requested to merge fkling/cm-file-sg-extensions into main

Created by: fkling

Note: This is a big PR, I don't expect a detailed review, but please ask if something is unclear. Disclaimer: I'm using CodeMirror to the best of my abilities. I still don't quite know when using a field would be better than a facet for example. So a lot of how the extensions are setup/configured is still in flux.

This commit introduces a way to interface with Sourcegraph extensions so that we can support hovercards and document highlights. I believe all extension points are supported:

  • Hovers (albeit incomplete; will complete in another PR)
  • Document highlights
  • Text decorations (including column view)
  • Status bar
  • Selection updates

This is big PR so let me provide a high level overview:

codemirror/sourcegraph-extensions.ts contains the extensions that communicate directly with the Sourcegraph extensions API. Where possible (and reasonable) I separated CodeMirror specific logic into separate modules and let the Sourcegraph extensions integrations interface with those via facets. In same cases it didn't make sense to introduce additional extension points and the Sourcegraph extensions integrations directly listen to CodeMirror events.

codemirror/decorations.ts implements the logic to convert TextDocumentDecorations into CodeMirror decorations. Inputs are provided via a facet, which is used for the Sourcegraph extensions integration as well as the git blame data coming from BlobPage (under the new core workflow integration). Note that decorations are only created/rendered for the lines that are currently visible.

codemirror/document-highlights.ts contains CodeMirror extensions that

  • listen to, debounce and filer CodeMirror events to determine the current mouse position
  • query one or more data sources for document highlights data
  • convert document highlights to CodeMirror extensions

Currently the only data source is provided by the Sourcegraph extensions integration.

codemirror/hovercard.ts contains logic to render hovercard data as CodeMirror hover tooltips. The hovercards implementation isn't complete yet, I will finish this in a future PR.

codemirror/index.ts contains logic that I didn't know where else to put.

codemirror/utils.ts contains, as the name implies, a couple of helper functions used by various extensions.

Also note that I switched from using EditorView.editable to EditorState.readOnly. This allows us to focus the editor and have a proper selection. That selection is sent to the extensions host when it changes. This is currently not synced with selected lines and I don't know what exactly we want to do in that area.

Note: The current blob view contains a lot of logic to clean up decorations and other state when switching documents. We avoid that with CodeMirror by completely resetting the editor's state when loading a new document so we get most of the cleanup for free.


I also made some changes to existing components to avoid code duplication or to fix things:

  • Blob.tsx: Exported the function to group text decorations
  • CodeMirrorQueryInput.tsx, input/extensions/index.tsx: Moved the createUpdatableField helper function to CodeMirrorEditor.ts to make it sharable.
  • ColumnDecorator.tsx: Extracted inner component.
  • LineDecorator.tsx: Extracted inner component.
  • BlobStatusBarContainer.module.scss needed to remove isolate otherwise hovercards would be rendered underneath the extensions sidebar. isolate doesn't seem necessary here but I don't know for sure.

Note on React integration

I'm currently creating a new root via createRoot and it seems to work but I feel like it's not optimal. (you might notice in the video that the line decorations seem to be rendered one after each other).


https://user-images.githubusercontent.com/179026/181710762-f85830c3-b557-4c3b-b2a3-267d62d04dfc.mp4

Test plan

  • Enable CodeMirror with enableCodeMirrorFileView
  • Enable extensions (e.g. git extras and codecov)
  • Navigate to a file, text decorations (if any) are rendered at the end of the line
  • With git-extras, enable enableExtensionsDecorationsColumnView and see blame data being rendered in a column.
  • With git-extras, enable extensionsAsCoreFeatures and see blame data being rendered in a column (might want to disable enableExtensionsDecorationsColumnView to see that it really works).
  • Toggle light/dark theme, decorations should update accordingly
  • Hover over tokens, hovecards and document highlights should appear

App preview:

Check out the client app preview documentation to learn more.

Merge request reports

Loading