Compare commits
6 Commits
a5c219024e
...
22887b56cd
| Author | SHA1 | Date | |
|---|---|---|---|
| 22887b56cd | |||
| 0342df1d4e | |||
| db8c5147db | |||
| eab763fd21 | |||
| 4e00584af7 | |||
| 1ed7a8e193 |
@ -1,5 +1,5 @@
|
||||
{"type":"meta","next_id":{"DSC":38,"AGD":41,"DEC":36,"PLN":78,"LSN":52,"CLSN":1}}
|
||||
{"type":"discussion","id":"DSC-0037","status":"open","ticket":"pbs-autocomplete-parameter-names","title":"PBS autocomplete parameter names for stdlib and method calls","created_at":"2026-05-08","updated_at":"2026-05-08","tags":["compiler-pbs","studio","lsp","autocomplete","signature-help","stdlib"],"agendas":[{"id":"AGD-0040","file":"AGD-0040-pbs-autocomplete-parameter-names-for-stdlib-and-method-calls.md","status":"open","created_at":"2026-05-08","updated_at":"2026-05-08"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"meta","next_id":{"DSC":38,"AGD":41,"DEC":37,"PLN":81,"LSN":53,"CLSN":1}}
|
||||
{"type":"discussion","id":"DSC-0037","status":"done","ticket":"pbs-autocomplete-parameter-names","title":"PBS autocomplete parameter names for stdlib and method calls","created_at":"2026-05-08","updated_at":"2026-05-14","tags":["compiler-pbs","studio","lsp","autocomplete","signature-help","stdlib"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0052","file":"discussion/lessons/DSC-0037-pbs-autocomplete-parameter-names/LSN-0052-canonical-callable-parameter-names-through-pbs-editor-assistance.md","status":"done","created_at":"2026-05-14","updated_at":"2026-05-14"}]}
|
||||
{"type":"discussion","id":"DSC-0036","status":"open","ticket":"pbs-symbol-documentation-and-hover-markdown","title":"Modelo de documentacao de simbolos em PBS e consumo markdown no hover","created_at":"2026-05-08","updated_at":"2026-05-08","tags":["compiler","compiler-pbs","studio","lsp","vscode","editor","hover","documentation","markdown"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-pbs-symbol-documentation-and-hover-markdown.md","status":"open","created_at":"2026-05-08","updated_at":"2026-05-08"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0035","status":"done","ticket":"pbs-lsp-editor-assistance-wave-1","title":"Wave 1 de assistencia editorial via LSP para PBS no VS Code","created_at":"2026-05-08","updated_at":"2026-05-08","tags":["studio","lsp","vscode","compiler","compiler-pbs","editor","completion","hover","signature-help"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0051","file":"discussion/lessons/DSC-0035-pbs-lsp-editor-assistance-wave-1/LSN-0051-compiler-backed-editor-assistance-for-pbs.md","status":"done","created_at":"2026-05-08","updated_at":"2026-05-08"}]}
|
||||
{"type":"discussion","id":"DSC-0034","status":"done","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-07","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0034-frontend-semantic-host-projection-flexibility/LSN-0048-frontend-owned-semantic-vocabularies-with-declarative-host-projection.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]}
|
||||
|
||||
@ -0,0 +1,77 @@
|
||||
---
|
||||
id: LSN-0052
|
||||
ticket: pbs-autocomplete-parameter-names
|
||||
title: Canonical callable parameter names through PBS editor assistance
|
||||
created: 2026-05-14
|
||||
tags: [compiler-pbs, studio, lsp, autocomplete, signature-help, stdlib]
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
PBS editor assistance is compiler-backed. Completion, hover, and signature help should therefore expose the same callable shape that the compiler understands, not a parallel UI-only interpretation.
|
||||
|
||||
Before this discussion, some callable surfaces could reach editor assistance with synthesized labels such as `arg0` and `arg1`. Those labels made stdlib and method calls harder to use because they erased the public meaning of each argument exactly where the editor is meant to help.
|
||||
|
||||
`DEC-0036` made callable parameter names normative semantic metadata. `PLN-0078`, `PLN-0079`, and `PLN-0080` implemented that rule in specs, compiler semantics, and LSP regression coverage.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
### Compiler semantics own parameter identity
|
||||
|
||||
**What:** Every user-visible PBS callable must expose a semantic parameter list with canonical name, zero-based order, type when known, and origin/source metadata.
|
||||
|
||||
**Why:** Completion, hover, signature help, diagnostics, and later documentation surfaces need one source of truth for callable shape. If each editor adapter invents labels independently, stdlib and host-backed API names drift from compiler truth.
|
||||
|
||||
**Trade-offs:** This makes stdlib and host-backed parameter names part of public API shape. Renaming them becomes compatibility-sensitive, but that cost is appropriate because these names are visible to users and tooling.
|
||||
|
||||
### Generated ordinal names stay internal
|
||||
|
||||
**What:** `arg0`, `arg1`, and equivalent ordinal placeholders must not appear in user-facing editor or LSP output.
|
||||
|
||||
**Why:** A generated ordinal name is not a public API name. Publishing it trains users and tests to rely on a placeholder that carries no semantic meaning.
|
||||
|
||||
**Trade-offs:** If a callable genuinely lacks a canonical parameter name, the boundary should represent the metadata as incomplete instead of fabricating a plausible-looking name. That can make missing metadata more visible, but it prevents false API contracts.
|
||||
|
||||
## Patterns and Algorithms
|
||||
|
||||
The compiler-side pattern is to keep parameter identity attached to callable symbols, not only to AST declarations used by direct hover paths.
|
||||
|
||||
The PBS semantic support model now carries `CallableParameter` records beside callable input types. This preserves:
|
||||
|
||||
- authored parameter name;
|
||||
- parameter order;
|
||||
- resolved type view;
|
||||
- source span as origin metadata.
|
||||
|
||||
Editor-facing formatting should then render signatures from those semantic parameters. Direct AST formatting and model-backed callable formatting should produce the same names for user-authored methods, stdlib services, host-backed declarations, and visible builtin/intrinsic method surfaces.
|
||||
|
||||
The LSP bridge should stay thin. It should map compiler editorial signatures into baseline completion, hover, and signature-help payloads without inventing names. The LSP4J mapper should preserve labels and parameter lists exactly as received from the baseline protocol model.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- Do not fix missing parameter names with an editor-side rename table. That creates a second source of callable truth.
|
||||
- Do not treat stdlib parameter names as incidental implementation details. They are public API surface once completion and signature help expose them.
|
||||
- Do not use `argN` as a harmless fallback in tests. A passing test that expects `arg0` is a regression against the semantic contract.
|
||||
- Be careful when testing stdlib signatures that reference imported types. A test for parameter identity should not accidentally become a test for transitive type rendering unless that is the intended scope.
|
||||
|
||||
## Final Result
|
||||
|
||||
The implemented slice updated:
|
||||
|
||||
- PBS and compiler specs to define callable parameter identity and `argN` leak prevention;
|
||||
- PBS compiler semantic callable symbols to preserve structured parameter metadata;
|
||||
- PBS editorial formatting to render semantic names instead of synthesized ordinals;
|
||||
- LSP bridge and mapper tests to prove completion, hover, and signature help preserve semantic names.
|
||||
|
||||
The validating commits were:
|
||||
|
||||
- `4e00584` implements `PLN-0078`;
|
||||
- `eab763f` implements `PLN-0079`;
|
||||
- `db8c514` implements `PLN-0080`.
|
||||
|
||||
## Takeaways
|
||||
|
||||
- Parameter names are structural callable metadata, not documentation prose.
|
||||
- Editor assistance should consume compiler semantics rather than patching over missing names locally.
|
||||
- Public stdlib and host-backed parameter renames need compatibility review.
|
||||
- Missing semantic metadata is better exposed as incomplete than disguised as `arg0`.
|
||||
@ -1,153 +0,0 @@
|
||||
---
|
||||
id: AGD-0040
|
||||
ticket: pbs-autocomplete-parameter-names
|
||||
title: PBS autocomplete parameter names for stdlib and method calls
|
||||
status: open
|
||||
created: 2026-05-08
|
||||
resolved:
|
||||
decision:
|
||||
tags: [compiler-pbs, studio, lsp, autocomplete, signature-help, stdlib]
|
||||
---
|
||||
|
||||
## Pain
|
||||
|
||||
Domain owner: `compiler/pbs`
|
||||
|
||||
Autocomplete and signature help currently show method/function parameters as arg0, arg1, etc., especially for stdlib APIs, making calls hard to understand at the point of use.
|
||||
|
||||
The immediate user-facing problem is not just cosmetic. When a completion inserts or previews something like:
|
||||
|
||||
- `draw(arg0, arg1, arg2)`
|
||||
- `setTile(arg0, arg1, arg2)`
|
||||
- `loadSprite(arg0)`
|
||||
|
||||
the editor fails at the exact moment it should reduce lookup cost. The user has to leave the call site, inspect docs/source, or guess what each argument means.
|
||||
|
||||
For PBS, this is especially damaging because stdlib and host-backed APIs are likely to be the most frequently discovered through autocomplete.
|
||||
|
||||
## Context
|
||||
|
||||
The compiler-backed LSP wave can surface completions, hover, and signature help, but the parameter identity exposed to editor consumers is not yet reliable or authored enough for ergonomic API use.
|
||||
|
||||
Subdomains touched:
|
||||
|
||||
- `compiler/general`
|
||||
- `studio/lsp`
|
||||
- `tools/vscode-extension`
|
||||
|
||||
Related discussions:
|
||||
|
||||
- `DSC-0035` established the compiler-backed editor assistance wave.
|
||||
- `DSC-0036` is discussing authored symbol documentation and markdown hover.
|
||||
|
||||
This agenda is narrower than `DSC-0036`.
|
||||
|
||||
`DSC-0036` asks how symbol documentation should be authored and transported. This agenda asks where canonical parameter names come from and how completion/signature surfaces should consume them. Parameter names may later connect to documentation, but they need their own canonical identity even without full prose documentation.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- [ ] Where should canonical parameter names for stdlib and builtins live?
|
||||
- [ ] Should parameter names be part of the compiler semantic model, external stdlib metadata, authored documentation, or derived from declarations?
|
||||
- [ ] How should completion snippets, signature help, and hover consume the same parameter identity?
|
||||
- [ ] Should generated fallback names like `arg0` be allowed to reach user-facing editor UI at all?
|
||||
- [ ] Do user-authored PBS functions already preserve parameter names well enough, or is the problem shared by all callable symbols?
|
||||
- [ ] Are stdlib APIs represented as PBS declarations, Java/Kotlin host descriptors, compiler intrinsics, generated metadata, or a mix?
|
||||
- [ ] Should parameter names be normative API surface, meaning renames require compatibility/release discipline?
|
||||
- [ ] How should optional/default/rest parameters be represented if PBS supports or later adds them?
|
||||
- [ ] Should completion snippets include placeholders named from canonical parameters, or should names appear only in detail/signature help?
|
||||
|
||||
## Options
|
||||
|
||||
### Option A - Canonical parameter names live in the compiler semantic callable model
|
||||
|
||||
- **Approach:** every callable symbol resolved by the compiler has an explicit parameter list with stable names, types, order, and origin. LSP completion, signature help, and hover all read from that same semantic shape.
|
||||
- **Pro:** one authoritative contract; works for user code, stdlib, builtins, and host-backed APIs if they are projected into the semantic model.
|
||||
- **Con:** requires stdlib/builtin surfaces to provide or be lowered into real parameter metadata instead of ad hoc editor-only labels.
|
||||
- **Maintainability:** strong. It makes `arg0` a compiler/model quality issue rather than a UI formatting problem.
|
||||
|
||||
### Option B - Parameter names live in stdlib/API metadata consumed by the LSP adapter
|
||||
|
||||
- **Approach:** stdlib and host-backed APIs carry external metadata for names and docs; LSP consumes that metadata when building completion items and signatures.
|
||||
- **Pro:** fast path for the worst current pain if the main offender is stdlib; avoids forcing every host descriptor into a richer compiler model immediately.
|
||||
- **Con:** risks splitting callable truth between compiler semantics and editor metadata. User-authored and stdlib callables may drift.
|
||||
- **Maintainability:** medium. Acceptable as a migration step, but weak as the final owner if the compiler and editor can disagree.
|
||||
|
||||
### Option C - Derive display names in the editor/LSP when semantic names are missing
|
||||
|
||||
- **Approach:** keep existing compiler output and have LSP/VS Code replace `arg0`, `arg1` with guessed names from docs, method names, types, or curated maps.
|
||||
- **Pro:** minimal compiler change; can improve a handful of visible APIs quickly.
|
||||
- **Con:** guessing parameter names is fragile and can mislead users. It treats presentation as truth.
|
||||
- **Maintainability:** weak. This should be reserved only as a temporary compatibility shim with clear diagnostics.
|
||||
|
||||
### Option D - Bind parameter names to the documentation model from `DSC-0036`
|
||||
|
||||
- **Approach:** parameter names and descriptions are authored together in the symbol documentation surface, then completion/signature help extract display names from docs.
|
||||
- **Pro:** ties names and descriptions together; can produce rich signature help.
|
||||
- **Con:** parameter identity becomes dependent on documentation authoring. A callable without docs could still degrade to `arg0`.
|
||||
- **Maintainability:** medium-to-weak as a canonical source. Good for prose descriptions, poor for structural identity.
|
||||
|
||||
### Option E - Allow `arg0`/`arg1` internally but ban them from user-facing LSP output
|
||||
|
||||
- **Approach:** define a conformance rule: generated fallback parameter names may exist internally, but completion/signature/hover must either show canonical names or omit placeholder names instead of exposing `argN`.
|
||||
- **Pro:** creates a clear UX quality gate and prevents the worst editor output.
|
||||
- **Con:** does not by itself solve where real names come from.
|
||||
- **Maintainability:** strong as a guardrail, incomplete as the main design.
|
||||
|
||||
## Tradeoffs
|
||||
|
||||
The central tradeoff is speed versus ownership.
|
||||
|
||||
An editor-only fix can make the UI look better quickly, but it creates a second source of truth for API shape. That is exactly the kind of split that becomes expensive once hover, snippets, signature help, diagnostics, docs, and future refactors all need the same callable metadata.
|
||||
|
||||
Putting names into the compiler semantic model is heavier, but it matches the long-term direction implied by compiler-backed editor assistance. The editor should not need to know why a callable is user-authored, stdlib, host-backed, or intrinsic in order to display a usable signature.
|
||||
|
||||
There is still room for a staged path:
|
||||
|
||||
- immediately block or reduce `argN` in user-facing output;
|
||||
- add canonical names for stdlib APIs through the nearest existing stdlib descriptor;
|
||||
- converge those descriptors into the compiler's callable semantic model;
|
||||
- let documentation add descriptions, examples, and prose later without owning structural names.
|
||||
|
||||
`DSC-0036` should remain complementary. Documentation can describe what a parameter means, but the parameter name itself should be structural metadata.
|
||||
|
||||
## Recommendation
|
||||
|
||||
Use **Option A** as the target design and **Option E** as a non-negotiable editor quality guardrail.
|
||||
|
||||
Recommended direction:
|
||||
|
||||
1. Treat canonical parameter names as part of the resolved callable symbol model.
|
||||
2. Require stdlib, builtin, host-backed, and user-authored callables to expose the same parameter shape to editor assistance.
|
||||
3. Define `arg0`, `arg1`, etc. as internal fallback names only; they should not appear in completion labels, snippets, signature help, or hover unless explicitly authored as real API names.
|
||||
4. Let the documentation model from `DSC-0036` attach parameter descriptions later, but not replace structural parameter identity.
|
||||
|
||||
If implementation needs to be staged, the first slice should target the stdlib because that is where the current UX pain is most visible.
|
||||
|
||||
## Discussion
|
||||
|
||||
This agenda should avoid reducing the problem to "prettier snippets".
|
||||
|
||||
The real question is ownership:
|
||||
|
||||
- who owns a callable's parameter names?
|
||||
- does the compiler know them?
|
||||
- does the editor receive them as structured data?
|
||||
- can tests assert that stdlib APIs do not leak fallback names?
|
||||
|
||||
The minimum acceptable outcome is that a user can discover a stdlib call from autocomplete and understand what each argument is supposed to represent without leaving the call site.
|
||||
|
||||
Potential acceptance examples for a later decision/plan:
|
||||
|
||||
- completion insert text uses named placeholders where snippets are enabled;
|
||||
- signature help displays stable parameter names and types;
|
||||
- hover can show a callable signature using the same names;
|
||||
- conformance tests fail if public stdlib callables expose `argN` placeholders;
|
||||
- fallback behavior is explicit when a callable genuinely lacks parameter names.
|
||||
|
||||
## Resolution
|
||||
|
||||
Ainda em aberto.
|
||||
|
||||
## Next Step
|
||||
|
||||
Discutir se a equipe aceita `compiler/pbs` como owner dos nomes canonicos de parametros e se `argN` deve ser banido de qualquer surface LSP user-facing.
|
||||
@ -462,6 +462,8 @@ Campos:
|
||||
* `sortText`: prefixado para impor bucket (ex.: `"1_"`, `"2_"`)
|
||||
* `filterText`: label
|
||||
|
||||
Callable completion details and snippets must consume parameter names from the compiler semantic callable model. LSP/editor code must not invent display names such as `arg0` or `arg1`; missing semantic names should remain visibly incomplete rather than being presented as API names.
|
||||
|
||||
---
|
||||
|
||||
## Tarefas de implementação
|
||||
|
||||
@ -65,6 +65,8 @@ Habilitar `references`, `prepareRename`, `rename` com regras de segurança.
|
||||
|
||||
* Type facts básicos: `NodeId -> TypeId`
|
||||
* Modelo de assinatura: para functions (params, retorno)
|
||||
* Parameter names for signatureHelp and hover come from the compiler semantic callable model, including stdlib, host-backed, builtin, and intrinsic callables.
|
||||
* Generated placeholders such as `arg0` must not appear in LSP completion, signatureHelp, or hover output.
|
||||
|
||||
### Testes
|
||||
|
||||
|
||||
@ -167,6 +167,8 @@ The following constructs are callable in v1 core:
|
||||
Rules:
|
||||
|
||||
- All callable categories use the same input/output tuple model.
|
||||
- Every user-visible callable category MUST expose a semantic parameter list for editor and tooling consumers.
|
||||
- Each semantic parameter record MUST carry its canonical source/API name, zero-based order, type when known, and origin/source sufficient for implementation and diagnostics.
|
||||
- A struct method is identified by `(struct type, method name, input tuple shape excluding the receiver slot, output tuple shape)`.
|
||||
- A contract value is identified at the type level by its contract type and at runtime by an underlying concrete struct instance or service singleton value plus its selected implementation.
|
||||
- A callback declaration defines a nominal callable type with exactly one input/output tuple shape.
|
||||
@ -177,6 +179,9 @@ Rules:
|
||||
- A callback value is identified at the type level by its declared callback type and signature.
|
||||
- Contract signatures and barrel signatures must preserve the same callable shape.
|
||||
- Canonical host primitive identity and binding are governed by the Host ABI Binding specification rather than by ordinary v1 core declaration identity alone.
|
||||
- The compiler semantic model is the canonical owner of callable parameter names for completion, signature help, hover, diagnostics, and other editor-facing surfaces.
|
||||
- Generated ordinal placeholders such as `arg0`, `arg1`, or equivalent names are internal implementation fallbacks only and MUST NOT be exposed as public parameter names.
|
||||
- If a user-visible callable lacks a real canonical parameter name, semantic metadata MUST represent that name as missing or unresolved rather than fabricating an ordinal placeholder.
|
||||
|
||||
### 3.3 Declaration validity
|
||||
|
||||
|
||||
@ -343,6 +343,18 @@ This list fixes the currently required declarative role of interface modules, bu
|
||||
|
||||
An interface module is not runtime code.
|
||||
|
||||
### 9.2.1 Callable parameter identity
|
||||
|
||||
Stdlib and SDK interface modules define public callable surfaces. Their method and function signatures MUST preserve stable canonical parameter names in the compiler semantic callable model.
|
||||
|
||||
Rules:
|
||||
|
||||
- Stdlib and SDK-hosted callable definitions MUST carry parameter names, zero-based order, type when known, and source/origin metadata.
|
||||
- Stdlib and host-backed parameter names are part of the public API surface.
|
||||
- Renaming a public stdlib or host-backed parameter is API compatibility-sensitive and MUST be reviewed with the same discipline as other public callable-shape changes.
|
||||
- Interface-module loaders MUST NOT replace missing or unavailable public parameter names with generated ordinal placeholders such as `arg0` or `arg1`.
|
||||
- Missing canonical parameter identity MUST be represented as incomplete semantic metadata, not as a fabricated public name.
|
||||
|
||||
### 9.3 Interface-module restrictions
|
||||
|
||||
At minimum, an interface module MUST remain declarative.
|
||||
|
||||
@ -82,6 +82,8 @@ This document depends on, at minimum:
|
||||
|
||||
PBS distinguishes three ownership categories for callable behavior.
|
||||
|
||||
All categories share the callable parameter identity contract from the Static Semantics Specification. A PBS-visible callable MUST project canonical parameter names, order, type when known, and origin into the semantic callable model regardless of whether the behavior is program-owned, VM-owned, or host-backed.
|
||||
|
||||
### 5.1 Program-owned function
|
||||
|
||||
A program-owned function is authored by the program and compiled from a PBS body.
|
||||
@ -129,6 +131,8 @@ Properties:
|
||||
Host-backed operations are the domain of `declare host`, PBX `SYSC`, loader
|
||||
resolution, and final `SYSCALL`.
|
||||
|
||||
Host-backed ownership changes runtime authority and lowering, but it does not remove source/API parameter identity. Host-backed callable parameter names remain public semantic metadata and MUST NOT be replaced with generated ordinal placeholders in editor-facing surfaces.
|
||||
|
||||
## 6. The Boundary Question
|
||||
|
||||
The normative classification question is:
|
||||
|
||||
@ -106,6 +106,8 @@ reserved top-level `declare const` shell carrying builtin metadata.
|
||||
An intrinsic operation is a VM-owned callable behavior with canonical
|
||||
definition in the VM contract.
|
||||
|
||||
Visible intrinsic operations and builtin method surfaces MUST be projected into the same semantic callable parameter shape used by ordinary PBS callables. Each visible intrinsic parameter MUST expose a canonical name, order, type when known, and VM/intrinsic origin metadata. If an intrinsic registry entry or builtin descriptor lacks a real public parameter name, compiler/editor metadata MUST represent the name as missing or unresolved rather than publishing `arg0`, `arg1`, or another generated ordinal placeholder.
|
||||
|
||||
### 5.5 Canonical intrinsic registry artifact
|
||||
|
||||
Final intrinsic ids are owned by one canonical ISA-scoped registry artifact.
|
||||
|
||||
@ -110,6 +110,9 @@ Rules:
|
||||
- `declare host` exists to define compile-time interface shape, not executable PBS bodies.
|
||||
- The compiler is responsible for mapping each host-backed member to its canonical host identity.
|
||||
- The PBX must not depend on source spellings such as `Gfx` for runtime resolution.
|
||||
- Host-backed source/API signatures MUST preserve their canonical parameter names in compiler semantic callable metadata.
|
||||
- Host-backed parameter names are public API surface and are compatibility-sensitive.
|
||||
- Loader-facing slot counts and canonical host identity do not license compiler or editor surfaces to publish generated parameter names such as `arg0` or `arg1`.
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
@ -98,6 +98,18 @@ At minimum, each language corpus must retain:
|
||||
|
||||
Regression grouping by language is expected; one shared monolithic corpus is not required.
|
||||
|
||||
### 6.1 Callable parameter identity regressions
|
||||
|
||||
PBS conformance tests MUST protect user-visible callable parameter identity.
|
||||
|
||||
At minimum, tests MUST prove that:
|
||||
|
||||
1. user-authored callable parameters preserve canonical names, order, type when known, and origin in semantic metadata,
|
||||
2. stdlib, builtins, host-backed APIs, and visible intrinsics project parameter identity through the same semantic callable model,
|
||||
3. editor-facing compiler outputs for completion, signature help, hover, and parameter documentation do not leak generated ordinal placeholders such as `arg0` or `arg1`,
|
||||
4. missing canonical parameter names are represented as incomplete metadata rather than fabricated public names,
|
||||
5. and stdlib or host-backed parameter renames are treated as public API compatibility changes.
|
||||
|
||||
## 7. Claims and Evidence
|
||||
|
||||
For PBS quality claims at this stage:
|
||||
|
||||
@ -741,9 +741,13 @@ public final class PbsEditorialSupportService {
|
||||
}
|
||||
final ArrayList<PbsEditorialSignature> signatures = new ArrayList<>(callables.size());
|
||||
for (final var callable : callables) {
|
||||
final ArrayList<String> parameterLabels = new ArrayList<>(callable.inputTypes().size());
|
||||
for (int index = 0; index < callable.inputTypes().size(); index += 1) {
|
||||
parameterLabels.add("arg" + index + ": " + formatType(callable.inputTypes().get(index)));
|
||||
final ArrayList<String> parameterLabels = new ArrayList<>(callable.parameters().size());
|
||||
for (final var parameter : callable.parameters()) {
|
||||
if (parameter.name() == null || parameter.name().isBlank()) {
|
||||
parameterLabels.add(formatType(parameter.type()));
|
||||
} else {
|
||||
parameterLabels.add(parameter.name() + ": " + formatType(parameter.type()));
|
||||
}
|
||||
}
|
||||
final String label = callable.name() + "(" + String.join(", ", parameterLabels) + ") -> " + formatType(callable.outputType());
|
||||
signatures.add(new PbsEditorialSignature(callable.name(), label, parameterLabels, formatType(callable.outputType())));
|
||||
|
||||
@ -143,10 +143,18 @@ final class PbsFlowSemanticSupport {
|
||||
|
||||
record CallableSymbol(
|
||||
String name,
|
||||
List<CallableParameter> parameters,
|
||||
List<TypeView> inputTypes,
|
||||
TypeView outputType,
|
||||
Span span) {
|
||||
}
|
||||
|
||||
record CallableParameter(
|
||||
String name,
|
||||
int order,
|
||||
TypeView type,
|
||||
Span span) {
|
||||
}
|
||||
|
||||
record CallbackSignature(
|
||||
List<TypeView> inputTypes,
|
||||
@ -469,10 +477,18 @@ final class PbsFlowSemanticSupport {
|
||||
final PbsAst.TypeRef resultErrorType,
|
||||
final Span span) {
|
||||
final var input = new ArrayList<TypeView>(parameters.size());
|
||||
for (final var parameter : parameters) {
|
||||
input.add(typeFrom(parameter.typeRef()));
|
||||
final var semanticParameters = new ArrayList<CallableParameter>(parameters.size());
|
||||
for (int index = 0; index < parameters.size(); index += 1) {
|
||||
final var parameter = parameters.get(index);
|
||||
final var type = typeFrom(parameter.typeRef());
|
||||
input.add(type);
|
||||
semanticParameters.add(new CallableParameter(
|
||||
parameter.name(),
|
||||
index,
|
||||
type,
|
||||
parameter.span()));
|
||||
}
|
||||
return new CallableSymbol(name, input, callableReturn(returnKind, returnType, resultErrorType), span);
|
||||
return new CallableSymbol(name, semanticParameters, input, callableReturn(returnKind, returnType, resultErrorType), span);
|
||||
}
|
||||
|
||||
private TypeView callableReturn(
|
||||
|
||||
@ -155,7 +155,7 @@ final class PbsEditorialSupportServiceTest {
|
||||
ReadOnlyList.empty(),
|
||||
source.lastIndexOf("2);"));
|
||||
assertTrue(methodHelp.isPresent());
|
||||
assertEquals("blend(arg0: int, arg1: int) -> int", methodHelp.orElseThrow().signatures().getFirst().label());
|
||||
assertEquals("blend(dx: int, dy: int) -> int", methodHelp.orElseThrow().signatures().getFirst().label());
|
||||
assertEquals(1, methodHelp.orElseThrow().activeParameter());
|
||||
|
||||
final var constructorHelp = service.signatureHelp(
|
||||
@ -171,6 +171,57 @@ final class PbsEditorialSupportServiceTest {
|
||||
assertEquals("Vec()", constructorHover.signatures().getFirst().label());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPreserveSemanticParameterNamesForHostAndBuiltinCallables() {
|
||||
final var source = """
|
||||
import { Gfx, Sprite } from @sdk:gfx;
|
||||
|
||||
fn main(sprite: Sprite) -> void {
|
||||
Gfx.draw_pixel(1, 2, 3);
|
||||
sprite.blit(4, 5);
|
||||
}
|
||||
""";
|
||||
final var ast = parseOrdinary(source);
|
||||
final var supplementalTopDecls = supplementalTopDecls("""
|
||||
declare host Gfx {
|
||||
fn draw_pixel(x: int, y: int, color: int) -> void;
|
||||
}
|
||||
|
||||
declare builtin type Sprite(
|
||||
pub id: int
|
||||
) {
|
||||
fn blit(x: int, y: int) -> void;
|
||||
}
|
||||
""");
|
||||
|
||||
final var hostHelp = service.signatureHelp(
|
||||
source,
|
||||
ast,
|
||||
supplementalTopDecls,
|
||||
source.indexOf("2, 3"));
|
||||
assertTrue(hostHelp.isPresent());
|
||||
assertEquals("draw_pixel(x: int, y: int, color: int) -> void", hostHelp.orElseThrow().signatures().getFirst().label());
|
||||
assertFalse(hostHelp.orElseThrow().signatures().getFirst().label().contains("arg"));
|
||||
|
||||
final var builtinHelp = service.signatureHelp(
|
||||
source,
|
||||
ast,
|
||||
supplementalTopDecls,
|
||||
source.indexOf("5);"));
|
||||
assertTrue(builtinHelp.isPresent());
|
||||
assertEquals("blit(x: int, y: int) -> void", builtinHelp.orElseThrow().signatures().getFirst().label());
|
||||
assertFalse(builtinHelp.orElseThrow().signatures().getFirst().label().contains("arg"));
|
||||
|
||||
final var hostCompletion = service.completion(
|
||||
source,
|
||||
ast,
|
||||
supplementalTopDecls,
|
||||
source.indexOf("draw_pixel"));
|
||||
assertTrue(hostCompletion.stream().anyMatch(candidate ->
|
||||
candidate.label().equals("draw_pixel")
|
||||
&& candidate.detail().equals("draw_pixel(x: int, y: int, color: int) -> void")));
|
||||
}
|
||||
|
||||
private PbsEditorialResolvedSymbol requireHover(
|
||||
final String source,
|
||||
final PbsAst.File ast,
|
||||
|
||||
@ -6,6 +6,7 @@ import p.studio.lsp.messages.LspProjectContext;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@ -142,8 +143,9 @@ class CompilerLanguageServiceBridgeTest {
|
||||
overlay,
|
||||
hoverPosition.line(),
|
||||
hoverPosition.character());
|
||||
assertTrue(hover.markdown().contains("blend(arg0: int, arg1: int) -> int"));
|
||||
assertTrue(hover.markdown().contains("blend(dx: int, dy: int) -> int"));
|
||||
assertTrue(hover.markdown().contains("**method**"));
|
||||
assertFalse(hover.markdown().contains("arg0"));
|
||||
|
||||
final var functionSignatureHelp = bridge.signatureHelp(
|
||||
context,
|
||||
@ -163,6 +165,60 @@ class CompilerLanguageServiceBridgeTest {
|
||||
assertEquals("Vec()", constructorSignatureHelp.signatures().getFirst().label());
|
||||
}
|
||||
|
||||
@Test
|
||||
void completionHoverAndSignatureHelpUseStdlibSemanticParameterNames() {
|
||||
final Path projectRoot = findRepoRoot(Path.of("").toAbsolutePath().normalize())
|
||||
.resolve("test-projects")
|
||||
.resolve("main")
|
||||
.toAbsolutePath()
|
||||
.normalize();
|
||||
final Path documentPath = projectRoot.resolve("src").resolve("main.pbs");
|
||||
final String overlay = """
|
||||
import { Gfx } from @sdk:gfx;
|
||||
|
||||
fn frame() -> void {
|
||||
Gfx.clear_565(5);
|
||||
}
|
||||
""";
|
||||
final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge();
|
||||
final LspProjectContext context = new LspProjectContext("main", "pbs", projectRoot);
|
||||
final DocumentPositionMapper mapper = new DocumentPositionMapper(overlay);
|
||||
final var memberPosition = mapper.positionOf(overlay.indexOf("clear_565"));
|
||||
final var signaturePosition = mapper.positionOf(overlay.indexOf("5);"));
|
||||
|
||||
final var completion = bridge.completion(
|
||||
context,
|
||||
documentPath.toUri().toString(),
|
||||
overlay,
|
||||
memberPosition.line(),
|
||||
memberPosition.character());
|
||||
final var clear565Completion = completion.items().stream()
|
||||
.filter(item -> item.label().equals("clear_565"))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
assertEquals("clear_565(color_565: int) -> void", clear565Completion.detail());
|
||||
assertFalse(clear565Completion.detail().contains("arg0"));
|
||||
|
||||
final var hover = bridge.hover(
|
||||
context,
|
||||
documentPath.toUri().toString(),
|
||||
overlay,
|
||||
memberPosition.line(),
|
||||
memberPosition.character());
|
||||
assertTrue(hover.markdown().contains("clear_565(color_565: int) -> void"));
|
||||
assertFalse(hover.markdown().contains("arg0"));
|
||||
|
||||
final var signatureHelp = bridge.signatureHelp(
|
||||
context,
|
||||
documentPath.toUri().toString(),
|
||||
overlay,
|
||||
signaturePosition.line(),
|
||||
signaturePosition.character());
|
||||
assertEquals("clear_565(color_565: int) -> void", signatureHelp.signatures().getFirst().label());
|
||||
assertEquals(List.of("color_565: int"), signatureHelp.signatures().getFirst().parameters());
|
||||
assertFalse(signatureHelp.signatures().getFirst().label().contains("arg0"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void describeServerPublishesFrontendVisualThemes() {
|
||||
final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge();
|
||||
|
||||
@ -19,6 +19,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@ -86,6 +87,7 @@ final class Lsp4jProtocolMessageMapperTest {
|
||||
assertEquals(1, completion.getItems().size());
|
||||
assertEquals("blend", completion.getItems().getFirst().getLabel());
|
||||
assertEquals("blend(dx: int, dy: int) -> int", completion.getItems().getFirst().getDetail());
|
||||
assertFalse(completion.getItems().getFirst().getDetail().contains("arg0"));
|
||||
final var documentation = assertInstanceOf(Either.class, completion.getItems().getFirst().getDocumentation());
|
||||
assertTrue(documentation.isRight());
|
||||
|
||||
@ -98,6 +100,8 @@ final class Lsp4jProtocolMessageMapperTest {
|
||||
1));
|
||||
assertEquals(1, signatureHelp.getSignatures().size());
|
||||
assertEquals("mix(left: int, right: int) -> int", signatureHelp.getSignatures().getFirst().getLabel());
|
||||
assertFalse(signatureHelp.getSignatures().getFirst().getLabel().contains("arg0"));
|
||||
assertEquals("left: int", signatureHelp.getSignatures().getFirst().getParameters().getFirst().getLabel().getLeft());
|
||||
assertEquals(1, signatureHelp.getActiveParameter());
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user