forcedotcom / forcedotcom/apex-language-support

Use Org Metadata Catalog for find-missing-artifact org lookups - W-23971749

Open
#664 1 comment 0 reactions 0 assignees View on GitHub
USER STORY
Dominant language
TypeScript
Stars
11
Forks
3
Avg merge
1d 13h
Merged PRs (30d)
36

Description

## Summary

Canonical work item: [W-23971749](https://gus.lightning.force.com/a07EE00002ifA17YAE)

Migrate org-related `findMissingArtifact` lookups in `packages/apex-lsp-vscode-extension` to the production Org Metadata Catalog exposed by `@salesforce/vscode-services`.

The immediate goal is to stop the Apex language-server client from owning duplicate org discovery, Tooling queries, and remote Apex source storage where the released catalog can provide those responsibilities. The migration must preserve the existing parser-owned candidate selection, missing-artifact wire protocol, workspace-first behavior, org-switch isolation, and graceful degradation.

## Production API baseline

- `@salesforce/vscode-services@67.13.3` is the first production release whose `SalesforceVSCodeServicesApi.services` exposes `OrgMetadataCatalog`, its dependency in `prebuiltServicesDependencies`, `OrgMetadataCatalogChangePubSub`, and `ORG_METADATA_SCHEME`.
- The released catalog surface is currently:
- `getChildren(reference?, options?)`
- `getEntries(references, options?)`
- `resolveComponents(references)`
- The proposed `findComponents(...)` and `describeSObjects(...)` operations are **not** present in `67.13.3`.
- Upstream implementation: https://github.com/forcedotcom/salesforcedx-vscode/pull/7918
- Production release: https://github.com/forcedotcom/salesforcedx-vscode/releases/tag/v67.13.3
- Upstream design for the missing finder/describe APIs: https://github.com/forcedotcom/salesforcedx-vscode/blob/v67.13.3/docs/superpowers/plans/2026-08-14-org-metadata-catalog-finder-api.md

## Current Apex LS client behavior

`handleFindMissingArtifact` is workspace-first and currently composes multiple Salesforce Services APIs:

| Artifact | Workspace lookup | Org lookup | Result |
| --- | --- | --- | --- |
| Apex class | `ComponentSetService` | Direct Tooling SOQL through `ConnectionService` | Client-owned `apex-org-artifact:` document |
| Apex trigger | `ComponentSetService` | Direct Tooling SOQL through `ConnectionService` | Client-owned `apex-org-artifact:` document |
| sObject | `ComponentSetService` plus local metadata adaptation | `MetadataDescribeService.describeCustomObject` | Structured missing-artifact payload |

Relevant implementation:

- `src/missing-artifact-handler.ts`
- `src/services/org-artifact-adapter.ts`
- `src/services/org-artifact-fs.ts`
- `src/services/workspace-component-set-adapter.ts`
- `src/sobjects/org-sobject-adapter.ts`

## Recommended delivery approach

Use a phased hybrid migration.

### Phase 1: released catalog path for Apex classes and triggers

1. Upgrade the development API dependency and establish the minimum compatible Salesforce Services extension version containing the catalog.
2. Add a narrow client adapter over `api.services.OrgMetadataCatalog` and provide effects with `prebuiltServicesDependencies`.
3. Translate parser-derived exact candidates to `{ type: 'ApexClass' | 'ApexTrigger', fullName }` references.
4. Batch exact candidates through `OrgMetadataCatalog.getEntries(...)`.
5. Preserve candidate order and select the first matching component. Prefer `workspaceUri` when the entry is in the workspace; otherwise open its catalog `documentUri`.
6. Synchronize `sf-org-metadata:` Apex class and trigger documents with the language server.
7. On the catalog path, remove direct client Tooling queries and stop materializing Apex class/trigger source in `OrgArtifactFileSystem`.
8. Retain an explicitly transitional capability/version fallback for older Salesforce Services releases. Record whether catalog or legacy resolution handled the request.

### Phase 2: catalog-owned sObject descriptions

Continue using `MetadataDescribeService.describeCustomObject` until Salesforce Services exposes a catalog-owned, batch-oriented description operation such as `describeSObjects(names)`.

When available:

1. Switch org sObject lookup to the catalog operation.
2. Keep Apex-specific adaptation, definition targets, and wire-size enforcement in this repository.
3. Remove the direct public `MetadataDescribeService` dependency from the supported path.

## Options considered

### A. Use only the released `67.13.3` catalog now

- Use `getEntries` and catalog documents for Apex classes/triggers.
- Keep direct describe for sObjects.
- Fastest way to remove duplicate source discovery/storage, but it is intentionally partial.
- `getEntries` may acquire a complete metadata-type inventory and does not encapsulate workspace-first document selection as a dedicated finder contract would.

### B. Wait for `findComponents` and `describeSObjects`

- Produces the cleanest one-step migration and clearer miss/error semantics.
- Delays consuming a production catalog that already handles Apex source inventory, workspace correlation, stable documents, caching, persistence, and org isolation.

### C. Phased hybrid migration — recommended

- Delivers value from the production API now.
- Keeps the compatibility boundary narrow.
- Avoids inventing a client-side sObject catalog API that Services does not yet expose.
- Leaves a direct path to the upstream finder/describe contracts when they are published.

## Acceptance criteria

- [ ] The client detects catalog capability and uses it when available.
- [ ] Exact Apex class and trigger candidates come only from parser/symbol-derived missing-artifact data; no raw-source semantic heuristics are introduced.
- [ ] Workspace-only, org-only, and both-present Apex classes and triggers resolve with deterministic workspace-first behavior.
- [ ] Org-only source opens through `sf-org-metadata:` and synchronizes with the language server.
- [ ] Namespaced and unqualified Apex class/trigger candidates retain existing semantic ordering.
- [ ] Missing, protected, authorization-failed, no-active-org, and request-failed outcomes preserve current suppression/degradation behavior.
- [ ] Active-org changes cannot commit stale results or leak documents from the previous org.
- [ ] Concurrent and duplicate requests remain coalesced/bounded.
- [ ] Direct Tooling SOQL and client-owned Apex/trigger VFS storage are not used on the catalog path.
- [ ] Existing sObject semantic payloads and definition navigation remain unchanged while the temporary describe path remains.
- [ ] Telemetry distinguishes catalog versus legacy resolution without recording org, namespace, component, object, or field names.
- [ ] Unit/integration coverage includes catalog capability fallback and the existing missing-artifact scenarios.
- [ ] The minimum supported `salesforcedx-vscode-services` version and fallback removal condition are documented.

## Upstream/package prerequisite to verify

The published `@salesforce/vscode-services@67.13.3` tarball contains only 11 files, and `out/index.d.ts` re-exports `SalesforceVSCodeServicesApi` from `../../salesforcedx-vscode-services/out/src/index`, which is not included in that tarball. Before implementation, verify that a clean external consumer can resolve the catalog types. If not, open/fix the upstream packaging issue or temporarily maintain the existing narrow local interface without importing unpublished internals.

## Non-goals

- Changing the language-server missing-artifact wire protocol.
- Moving Apex-specific candidate ordering or semantic adaptation into Salesforce Services.
- Writing automatically resolved org source into the user workspace.
- Permanently maintaining two discovery/storage implementations.

Contributor guide

Open the contributing guide

Research direction

Start at handleFindMissingArtifact in src/missing-artifact-handler.ts, then read the org and workspace adapters listed in the issue. First verify that @salesforce/vscode-services@67.13.3 exposes usable catalog types to an external consumer. Done means catalog-backed Apex class and trigger resolution preserves workspace-first behavior, fallback and degradation semantics, org isolation, telemetry, and existing sObject behavior, with unit and integration coverage.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend-api-design, devtools
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.