- File actions (
file-actions.wit, API 1.3): quick fixes and refactorings that create, rename or delete files, applied as one undoable workspace edit. - Project files (
workspace.wit): read, write, find and search files inside the open projects. - Other files (
fs.wit, API 1.3): files outside the projects, under explicit grants, and the plugin’s own private directory. - File templates: entries of the File › New… menu, no code needed.
File actions
A file action is a code action whose result is file operations plus text edits. Declare thecode-actions provider kind (the same kind as text-only quick fixes), implement
openidea_plugin::file_actions::FileActions, and register it together with providers:
⌥⏎ / Alt+Enter) and have the same 50 ms editor budget.
The FileAction record
Rules:
- Operations and edits are one workspace edit: if any step fails nothing is applied, and
one Undo reverses all of it. Undoing a
Deleterestores the file. Createfails when the file exists unlessoverwrite; missing parent directories are created.- Paths are absolute or relative to the project root and must stay inside it; a path outside disables the action.
Resolving on pick
Return an action withdata and empty operations and edits to defer the work. When the
user picks it, the host calls resolve_file_action(doc, action) under the 5-second command
budget instead of 50 ms. As with resolve_code_action, host::pick, pick_many, input
and confirm ask in the editor’s window and the wait doesn’t count. Return
Error::Cancelled or an action with nothing to apply to abandon it.
Project files
Inside the open projects, a plugin uses itsProject handle (ctx.project() in commands
and events, host::project_of(path) in providers, host::projects() for every open
project). All of these need project.read except write_file:
Paths are absolute or relative to the root.
.. and symlinks that leave the root are
refused. In a remote project these run on the server, next to the files.
Two related calls need no capability and work only from a command or event of a window:
host::pick_directory(title, initial) (API 1.3) opens the native folder chooser, and
host::open_project(path, new_window) (API 1.3) runs the normal File › Open… flow,
including the trust prompt. Paths belong to the UI machine.
Files outside the projects
host::fs (WIT fs.wit, API 1.3) reads and writes files outside the open projects: the
configuration of a tool the plugin integrates with, a licence file, a program installed
elsewhere. Every call is checked against a grant:
- Paths are absolute or start with
~/. A grant covers a directory (any depth) or one file. The path is resolved to its real location before comparing, so a symlink out of the granted directory is refused, and/opt/seedoesn’t cover/opt/seeyon. - Granting a whole file system (
/,C:\) is refused when the manifest is read. fs.writedoesn’t implyfs.read. Writes fail withError::Invalidwhen the directory is missing, the text can’t be encoded, or an editor holds unsaved changes for the file.- Both are high-risk capabilities: the install page tells the user so.
The private directory
host::fs::plugin_dir() returns a directory that belongs only to this plugin, separate
from its installed code and its key-value storage. Reading and writing inside it needs no
fs.* or project.read grant, even during activation or provider calls without a project.
It is created owner-only (0700 on Unix, an owner-only ACL on Windows), survives idle
reclaim, reloads, updates and restarts, and is removed on uninstall. Use it for generated
content or caches larger than storage. A path in it works with host::open_location and
as an argument to an approved process.
File templates
[[contributes.fileTemplates]] adds entries to the File › New… menu. They need no code and grant
no file access: files are created only when the user invokes a template, through the IDE’s
normal New File flow.
engines.openidea = "^1.3", fileName creates an exact file name (dotfiles too)
without a name prompt, and variables add required text fields to the new-file dialog,
inserted with $NAME$ or ${NAME}:
NAME,
PACKAGE, END, …). $PACKAGE$ follows the built-in rules for the extension (source roots
for Java and Kotlin, Composer PSR-4 for PHP, …).