Skip to content

feat: hover-to-open navigation for RPC and function references - #369

Open
Kateřina Beňová (KatBen-Make) wants to merge 6 commits into
masterfrom
feat/app-component-navigation
Open

feat: hover-to-open navigation for RPC and function references#369
Kateřina Beňová (KatBen-Make) wants to merge 6 commits into
masterfrom
feat/app-component-navigation

Conversation

@KatBen-Make

@KatBen-Make Kateřina Beňová (KatBen-Make) commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Jira task

https://make.atlassian.net/browse/IEN-15822

Summary

  • Adds hover-to-open navigation for component references found in app code: hovering over an
    pc://Name reference or a custom IML function call (e.g. {{getTimeActivityBody(parameters)}}) shows an Open link that opens the referenced component's code and reveals it in the sidebar / file explorer.
  • Works in both online mode (cloud temp files — fetches the app's component summary via the API, opens through �pps-sdk.load-source, and reveals the node in the Custom apps tree) and local-development mode (resolves the reference via makecomapp.json + idMapping, opens the on-disk file, and reveals it in the file explorer).
  • Reference detection and online-path parsing live in a pure, unit-tested helper (src/libs/component-reference.ts); imljson files only match function calls inside {{ }} template regions.
  • Second commit applies self-review fixes based on conventions distilled from prior PR reviews (feat: add per-app component search #361/feat(endpoints): add support for SDK endpoint type #362/chore: remove legacy Integromat support #366): typed command target, parallelized+progress-wrapped app/component fetch, non-fatal reveal failures, cache-eviction-on-rejection, and negative-result caching for the local makecomapp.json filesystem walk.

Test plan

  • sc --noEmit passes
  • eslint passes on touched files (only pre-existing, unrelated
    equire()-import warnings remain in extension.ts)
  • Unit tests updated/passing for component-reference.ts (detection scope, half-open ranges, online path parsing)
  • Manually tested via a built VSIX: hovering over
    pc://Name and a custom function call in both online and local-development mode shows the popup and Open correctly navigates and reveals the component
  • Await GitHub bot / reviewer feedback

Add a hover popup over RPC references (rpc://Name) and custom IML
function calls in app code. Clicking the popup link opens the referenced
component's code file and reveals it in the sidebar.

Works in both online mode (cloud temp files, opened via apps-sdk.load-source
and revealed in the apps tree) and local-development mode (resolved via
makecomapp.json + idMapping, opened from disk and revealed in the explorer).

Built on the shared app-component-search helper (fetchAppComponentsSummary,
buildComponentTreeItem). Token detection and online-path parsing live in a
pure, unit-tested module (src/libs/component-reference.ts).

Co-authored-by: Cursor <cursoragent@cursor.com>
Apply the dev-conventions distilled from prior PR reviews (#361/#362/#366):
- Type the open-referenced-component command target instead of using an
  untyped parameter.
- Fetch the live app tree node and component summary in parallel, wrapped
  in a progress notification, instead of a sequential synthetic-node path.
- Make reveal failures non-fatal and log them instead of throwing after the
  file has already opened successfully.
- Restrict imljson function-reference detection to {{ }} template regions
  and use half-open ranges so trailing characters are not matched.
- Fix the online-cache to evict on rejection instead of replaying a failed
  fetch, and cache negative local makecomapp.json lookups per directory.
- Update unit tests to cover the new detection and caching behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copilot AI lite review requested due to automatic review settings August 19, 2026 19:10
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown
Messages
Your PR title & description are valid

Generated 25. 8. 2026 0:55:16 GMT+2 for d5622a6

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds editor hover support to navigate from in-code component references (e.g. rpc://Name and custom IML function calls) to the referenced component’s source, integrating with both online (temp-file + tree reveal) and local-development (disk file + explorer reveal) workflows in the Make Apps VS Code extension.

Changes:

  • Introduces ComponentReferenceHoverProvider to detect references on hover, resolve them against the app’s known components, and offer an Open link.
  • Adds a pure helper library (src/libs/component-reference.ts) with unit tests for reference detection and online temp-path parsing.
  • Registers a hidden command (apps-sdk.open-referenced-component) and wires it up to open/reveal the referenced code in online and local modes.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/providers/ComponentReferenceHoverProvider.ts New hover provider that resolves references (online via API summary; local via makecomapp.json) and renders an “Open” hover link.
src/libs/component-reference.ts New pure helper for syntactic reference detection + online temp-path context parsing.
src/libs/component-reference.test.ts Unit tests for detection scopes/ranges and online path parsing.
src/extension.ts Registers the hover provider and the apps-sdk.open-referenced-component command implementation.
package.json Contributes the new command and hides it from the command palette.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/extension.ts
Comment thread src/providers/ComponentReferenceHoverProvider.ts
Comment thread src/libs/component-reference.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/providers/ComponentReferenceHoverProvider.ts:243

  • markdown.isTrusted = true trusts any command URI that might end up in this MarkdownString. Since this hover only needs a single command, it’s safer to restrict trust to that command via enabledCommands.
		markdown.isTrusted = true;

src/providers/ComponentReferenceHoverProvider.ts:132

  • Local reference resolution can repeatedly throw and be re-tried when the opened file is outside the current workspace (or when the cached root is outside the workspace). Since getMakecomappRootDir enforces “file must be in workspace”, consider short-circuiting early and then reusing the already-found root appRootFsPath when loading makecomapp.json to avoid an extra upward walk on every hover.
		const appRootFsPath = this.findLocalAppRoot(documentUri.fsPath);
		if (!appRootFsPath) {
			return undefined;
		}

- Tolerate an apps-list fetch failure in open-referenced-component: log and
  fall back to an empty list instead of failing the whole command, since the
  file can still be opened from target.appName/appVersion alone.
- Restrict MarkdownString.isTrusted to the single command the hover link
  actually invokes, instead of trusting every command URI.
- Grammar: "That allow-list" -> "This allow-list".

Co-authored-by: Cursor <cursoragent@cursor.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/providers/ComponentReferenceHoverProvider.ts:126

  • In local-development resolution, findLocalAppRoot() already walked/cached the makecomapp.json root, but the subsequent getMakecomappRootDir(documentUri) and getMakecomappJson(documentUri) will re-walk the filesystem (and getMakecomappJson calls getMakecomappRootDir again). This largely defeats the negative-result caching and adds avoidable synchronous FS work on every hover. Use the cached appRootFsPath as the anchor when resolving the root and reading makecomapp.json so the follow-up checks are O(1).
		let root: vscode.Uri;
		let makecomappJson: Awaited<ReturnType<typeof getMakecomappJson>>;
		try {
			root = getMakecomappRootDir(documentUri);
			makecomappJson = await getMakecomappJson(documentUri);

let makecomappJson: Awaited<ReturnType<typeof getMakecomappJson>>;
try {
root = getMakecomappRootDir(documentUri);
makecomappJson = await getMakecomappJson(documentUri);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This call also writes - it migrates and saves. So a mouse hover mutates a file tracked by git. migrateMakecomappJsonFile will update manifest after hover over rpc://example

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch - fixed in d5622a6. Added an opt-in { readOnly: true } option to getMakecomappJson() that skips the migrate-and-save write-back, and the hover resolver now passes it. All other (write-intent) call sites are unaffected since the option defaults to off.


constructor(private readonly authorization: string, private readonly environment: Environment) {}

async provideHover(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

provideHover drops the CancellationToken, so we keep doing network work after VS Code has cancelled the hover (i.e. after the user moved the mouse away).

Low impact because the per-app promise is cached, but it's free to bail on token.isCancellationRequested

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in d5622a6: provideHover now takes the CancellationToken and both resolveOnline/resolveLocal check token.isCancellationRequested after their awaits, bailing out early instead of continuing.

* Walks from the file's directory upward looking for `makecomapp.json`, caching hits and misses
* per directory so unrelated workspace `.js` hovers do not repeat the walk.
*/
private findLocalAppRoot(fileFsPath: string): string | null {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we reuse getMakecomappRootDir?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in d5622a6: findLocalAppRoot now delegates to getMakecomappRootDir() instead of a hand-rolled fs.existsSync walk, so it also correctly respects the workspace boundary (which the old walk did not).

Comment thread src/extension.ts Outdated
Comment on lines +344 to +345
const codeName = target.supertype === 'rpc' ? 'api' : 'code';
const language = target.supertype === 'rpc' ? 'imljson' : 'js';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rpc -> api/imljson and function -> code/js is already encoded in AppsProvider.js and in component-code-def.ts. Any future component type means remembering to update three places. Can we have a centralized place for this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in d5622a6, scoped to this feature: added REFERENCE_CODE_DEF in component-reference.ts so extension.ts and ComponentReferenceHoverProvider now share one rpc/function -> code-file mapping instead of each hardcoding it. I did not attempt to also unify this with AppsProvider.js / component-code-def.ts, since those cover every component type (module/webhook/connection/endpoint) and touching them would be a materially larger, unrelated refactor - happy to file that separately if useful.

* path upward from a failed resolve) is not under a `makecomapp.json`. Avoids re-walking the
* filesystem on every hover over `foo(` in unrelated `.js` files.
*/
private readonly localAppRootCache = new Map<string, string | null>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cache stores negative results and never invalidates. So if someone hovers in a folder before cloning an app there, that directory is remembered as "not a Make project" and after they clone, hover stays dead until they reload the window. They'd have no idea why.

Worth clearing the cache on a makecomapp.json create

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in d5622a6: added a **/makecomapp.json FileSystemWatcher in extension.ts that clears the local-app-root cache on create/delete, via a new clearLocalAppRootCache() method.

- Critical: getMakecomappJson() migrates-and-saves makecomapp.json when
  needed, so a plain hover could silently dirty a git-tracked file. Add an
  opt-in readOnly option and use it from the hover resolver; all other
  (write-intent) call sites are unaffected.
- Respect the CancellationToken VS Code passes into provideHover, bailing
  out after each await instead of continuing network/FS work once the user
  has moved the mouse away.
- Reuse getMakecomappRootDir() instead of re-implementing the upward
  makecomapp.json walk with raw fs.existsSync, which also makes the local
  resolution correctly respect the workspace boundary.
- Centralize the rpc/function -> code-file mapping (REFERENCE_CODE_DEF in
  component-reference.ts) so extension.ts and ComponentReferenceHoverProvider
  share one source instead of each hardcoding it.
- Clear the local-app-root cache when a makecomapp.json is created or
  deleted anywhere in the workspace (FileSystemWatcher in extension.ts), so
  hover does not stay dead in a directory after an app is cloned into it.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants