Skip to main content
Editor providers answer questions about one document while the user types. Some features need the whole project: a MyBatis mapper method and its XML statement, a route and its controller. For those, a plugin can publish data once per document and let the host answer from memory:
  • Document indexers (indexing.wit, API 1.2): definitions, references, aliases and gutter markers keyed by strings the plugin chooses. The host resolves Go to Declaration, gutter markers and, since API 1.3, Find Usages and Rename from them, without calling the plugin again.
  • Endpoint providers (endpoints.wit, API 1.3): a project’s HTTP routes for Search Everywhere and the HTTP client.
For a quick lookup in the host’s existing symbol index, Project::symbols(query, limit) (API 1.3) is enough; see File actions.

Declare a document indexer

Implement openidea_plugin::indexing::DocumentIndexer and register indexing (register_plugin!(MyPlugin, providers, indexing) when the plugin also has interactive providers). Components built with other tools target the plugin-indexing world. Indexers need project.read and run only in trusted projects.

Publish edges

index(doc) receives the document’s text (the editor’s while it is open) and the symbols the host’s syntax support found in it, and returns its Edges: A key is any string the plugin chooses (com.example.UserMapper#findById); keys are compared as is. Ranges are UTF-16. The edges of a document replace its previous ones. From the indexer fixture, a line-oriented test language where def key defines, ref key refers and alias prefix# target# aliases:
doc.symbols lists the host’s symbols (name, kind, container, range), so a plugin can anchor keys to declarations without parsing the language itself.

Resolution rules

  • When a key has definitions in the same detected module, other modules’ definitions are left out. Several targets open a chooser.
  • Alias chains are followed with bounded depth and candidates.
  • A marker’s tooltip lists its targets.

Branded markers (API 1.3)

A [[contributes.markerIcons]] entry with markers gives markers whose key starts with one of its prefixes a package icon and an optional tooltip; the longest matching prefix wins, then declaration order. Other markers keep the navigation glyph.
A marker published as Anchor { key: "usages#User".into(), range } then shows that icon. IDEs older than API 1.3 refuse a manifest with markers or tooltip.

Find Usages and Rename (API 1.3)

With no extra export, the graph also answers:
  • Find Usages on a published definition or reference lists every definition and reference of its key alongside the language server’s results.
  • Rename replaces every such anchor with the new name, merged with the language server’s edits into one workspace edit. It always shows a preview, even for one file; cancelling changes nothing, and applying it is one undoable change.
For this to work, anchors must cover exactly the name: no quotes, delimiters or surrounding syntax, in UTF-16 columns (an astral character is two columns). Markers are excluded, since their ranges may cover an annotation or a whole line.
  • Alias-linked keys follow the same targets and module preference as navigation.
  • Queries flush queued indexing work but don’t rescan the project; external changes must reach the file watcher and be indexed first. If a document changed, wait for indexing and rename again.
  • When no language server can rename at the position, an anchor on a code identifier (per the file’s syntax tree) is not renamed, because the declaration, imports and file name would be missed. Anchors in strings, comments, attribute values and files without a grammar are still renamed from the index.

How indexing runs

  • Initial discovery reuses the host’s project index. The editor schedules cancellable batches of at most 16 files; edits and file changes invalidate the affected entries before they are indexed again.
  • Reloading, disabling or a failing plugin drops its graph. Nothing is answered from a document version older than the editor’s.
Limits: 2 MiB per document, 20,000 files per graph, 4,096 definitions and references and 4,096 markers per document, 256 aliases, 200,000 entries per graph, 16 project/window graphs and 256 candidates per lookup. A document over a limit is not indexed; editing is never blocked. To try the fixture, build it with plugins/build.sh crates/ide-plugin/tests/fixtures/indexer and load the folder as a development plugin in a trusted project with .idx files; its README lists the steps. cargo test -p ide-host --test plugin_indexing runs the real component contract checks.

Project HTTP endpoints (API 1.3)

A plugin that knows a framework’s routes can share them with the IDE: Search Everywhere’s Endpoints section, URL completion in .http files, and an Open in HTTP Client gutter action on each declaration.
  • endpoints(ctx) runs the first time the IDE needs the project’s routes, and again after a file matching files is created, changed or removed; in between the host answers from its cache. Return the complete list (an empty list clears it).
  • It runs in the background and can’t prompt. Each endpoint’s location must be inside the project.
  • Open in HTTP Client opens the generated-requests scratch file; requests start at http://localhost:8080, path parameters become HTTP client variables, and any-method routes use GET.
  • The host validates the whole batch before replacing the last valid result: up to 10,000 endpoints, 4 MiB of route metadata, 16 MiB of declaration documents.
  • Disabling, uninstalling, reloading or crashing withdraws the routes; idle reclaim keeps them cached. This API adds no Endpoints tool window.