PSA: Custom Autocomplete and Navigation in IntelliJ Using PSI Context
The PSA plugin empowers developers to implement project-specific autocomplete, navigation, and code templates directly within IntelliJ IDEA. A script written in any language analyzes the current PSI tree and returns suggestions. This solves the challenge of supporting custom frameworks without installing separate plugins.
How PSI Context Works
The plugin activates when you specify the path to an executable script in settings. When autocomplete (Ctrl+Space) or GoTo is triggered, a PSA Context — a simplified PSI tree of the focused element — is generated. It’s JSON-encoded into a temporary file (due to command-line argument limits) and passed to the script via the PSA_CONTEXT environment variable.
Example for PHP:
<?php
function myFunc() {
$l = '';
// ^ cursor here
}
The generated JSON includes a hierarchical structure of elements:
{
"elementType": "right single quote",
"elementName": null,
"elementFqn": null,
"text": "'",
"parent": {
"elementType": "String",
"text": "''",
// ... nested structure up to file level
}
}
Each PSI node includes elementType, elementName, elementFqn, text, textRange (startOffset/endOffset), parent/prev/next, and options.
Environment Variables for the Script
The script receives:
PSA_CONTEXT: Path to the JSON file containing the PSI tree.PSA_TYPE: EitherCompletionorGoTo.PSA_LANGUAGE: The programming language (PHP, JS, etc.).PSA_DEBUG: Set to1when debugging is enabled.PSA_OFFSET: Cursor position within the element.
The script parses the tree, analyzes context (element + parents), and determines suggestions. For Completion, it returns an array of options; for GoTo, one with a link.
Script Response Format
JSON response:
{
"completions": [
{
"text": "insertion text",
"link": "FileName.php:42:5", // only for GoTo
"bold": true,
"priority": 10
}
],
"notifications": ["debug message"],
"gotoElementTypes": ["FUNCTION", "CLASS"] // performance filter
}
priority sorts results; bold highlights entries. gotoElementTypes restricts GoTo scope for faster performance.
Documentation and Swagger
The plugin generates Swagger UI from its API models for clarity. Methods are 'fake' but describe call structures. Use OpenAPI Generator to create DTO classes for your script.
PSI element structure:
elementType: Type (STRING, FUNCTION).elementName/Fqn: Name or FQCN.options: Dictionary of parameters.text: Original source text.textRange: Offsets.- Relationships: parent/prev/next.
Setup and Performance
Enable the plugin and point it to your script. Turn on PSA_DEBUG for troubleshooting. Use gotoElementTypes filters to reduce GoTo overhead.
Advantages over framework-specific plugins:
- Project-level dependency, not global.
- Supports custom APIs and templates.
- Language-agnostic script support.
Example script (pseudocode):
#!/bin/bash
context=$(cat $PSA_CONTEXT | jq .)
if [[ $PSA_TYPE == "Completion" ]]; then
# analysis logic
echo '{"completions": [{"text": "customFunc()"}]}'
fi
Key Points
- PSA passes the full PSI tree for precise contextual analysis.
- Scripts return completions with
priorityandboldfor custom ranking. - GoTo supports
file:line:poslinks andelementTypefiltering. - Swagger documentation speeds up DTO development.
- Works with any project language (PHP, JS/TS, etc.).
— Editorial Team
No comments yet.