Repository navigation
Render the verifier's line tags as subscripts and name every part of an error alike - #196
Merged
Merged
Conversation
Collaborator
Author
|
Codex review (
|
Collaborator
Author
|
Clean-code audit (SOLID / DRY / KISS) of the diff
Nothing left to change. |
…rror alike Verifier 0.0.38 writes variables by their name and, only when an error has several values of one, tags the others with the line their value comes from (x@12, numbered x@12#2 when they share a line). The message and the context already used those names, but the server sent the expected, the Found steps, the counterexample and the translation table with the default formatter, so the steps of one error wrote three different values as `preview` and numbered clashes per line (`preview#1`). - Server: the refinement and state refinement DTOs format the expected, each step's binder and predicate, the counterexample and the translation-table keys with the error's DisplayNames. - Webview: a tag is drawn as a subscript, preview with l51 below, titled "value of preview at line 51", in highlighted expressions, binders and the code of messages; the step diff keeps a tagged name as one token; the Unicode superscript digits are no longer matched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g steps Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CatarinaGamboa
force-pushed
the
feat/175-line-tags
branch
from
November 11, 2026 19:14
53107c5 to
5993529
Compare
…, in words x@12 reads "x at line 12", x@25#2 "the 2nd value x gets at line 25", and x#2 "the 2nd value of x (line unknown)". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CatarinaGamboa
added a commit
that referenced
this pull request
Nov 11, 2026
… as markdown, and code in the view as in the hover (#198) Closes #197 ## What changes The editor hover shows a LiquidJava error as one markdown card: VS Code's own problem part holds only the **title** (it renders that message as plain text), and the extension's markdown part under it holds the **headline**, the **origin notes**, the **counterexample** and the **hints**: - **code** the verifier marks with backticks is inline code (editor font), without the backticks; - each **line reference** (`line 134`) is a link that opens that file at that line, from the structured `references` (`SourceReferenceDTO`), not a text search; - hints get a **Hint** / **Hints** heading, as in the panel, and several call sequences are listed under "Any one of these:"; - everything else is escaped, so `*`, `_`, `<`, `|`, `#` in expressions stay literal. In the **LiquidJava view**, the code in the Origin line and in the hints gets the look of inline code in a markdown hover (`textCodeBlock.background`, inherited colour) instead of the preformatted-text colours, which drew grey boxes around it in light themes. Before this PR, the hints were not in the editor hover at all, and the notes and counterexample were plain text with raw backticks. **Server:** the diagnostic message is the title alone (`LJDiagnosticsHandler.diagnosticMessage`). This is what the Problems tab, F8 and the squiggle show; the headline, the notes and the counterexample are in the hover's card and in the view. **Shared parsing.** The code-span and reference parsing that #193 wrote for the panel moves from `webview/message-text.ts` to `utils/message-text.ts` (`splitMessageText`, no `vscode` import, so both bundles use it). The panel renders the segments as HTML, the hover as markdown (`utils/message-markdown.ts`, `formatDiagnosticMarkdown`). The grouping of call sequences into options (`groupHints`) moves there too. **Trust.** The links are `file:` URIs with an `#L<line>,<col>` fragment, which VS Code opens without a command, so the markdown part is **not trusted** (no `isTrusted`, no command links). The existing refinement hover keeps its own trusted `MarkdownString`; the diagnostic card is a separate part of the hover. ## Design choice VS Code's diagnostic hover is always plain text, and the same string is the Problems tab entry. Rendering the headline in markdown without showing it twice means the diagnostic itself carries only the title, so the **Problems tab and the problem view (F8) show the error type**, not the headline (screenshot below). The PM chose the card over the Problems tab text (2026-11-11); putting `Title: headline` back in the diagnostic is a one-line change in `diagnosticMessage` if that is ever wanted. ## Screenshots Headless VS Code (openvscode 1.109), verifier 0.0.38, study task A1_38, cursor on the error. Before = `main` + the first version of this PR (hints only); after = this PR. | | Before | After | |---|---|---| | Hover, dark | <img src="https://raw.githubusercontent.com/liquid-java/vscode-liquidjava/pr-screenshots/197/A1_38-hover-before-dark.png" width="430"> | <img src="https://raw.githubusercontent.com/liquid-java/vscode-liquidjava/pr-screenshots/197/A1_38-hover-card-dark.png" width="430"> | | Hover, light | <img src="https://raw.githubusercontent.com/liquid-java/vscode-liquidjava/pr-screenshots/197/A1_38-hover-before-light.png" width="430"> | <img src="https://raw.githubusercontent.com/liquid-java/vscode-liquidjava/pr-screenshots/197/A1_38-hover-card-light.png" width="430"> | | Problems tab, dark | (headline + notes + counterexample as plain text) | <img src="https://raw.githubusercontent.com/liquid-java/vscode-liquidjava/pr-screenshots/197/A1_38-problems-card-dark.png" width="430"> | | View, dark | <img src="https://raw.githubusercontent.com/liquid-java/vscode-liquidjava/pr-screenshots/197/A1_38-panel-before-dark.png" width="300"> | <img src="https://raw.githubusercontent.com/liquid-java/vscode-liquidjava/pr-screenshots/197/A1_38-panel-after-dark.png" width="300"> | | View, light | <img src="https://raw.githubusercontent.com/liquid-java/vscode-liquidjava/pr-screenshots/197/A1_38-panel-before-light.png" width="300"> | <img src="https://raw.githubusercontent.com/liquid-java/vscode-liquidjava/pr-screenshots/197/A1_38-panel-after-light.png" width="300"> | The first version's screenshots (hints only, E_A3_07 with a clickable `line 51`, A1_09 with two call sequences) are in the PR's history under `pr-screenshots/197/*-after.png` and `*-link.png`. ## Not in this PR - The squiggle's range ends one character before the LiquidJava position (`getRangeFromPosition` uses `endColumn - 1`), so on the last character of the error our part shows without the problem part. Pre-existing; left alone. - Line tags (`x@51`) in the hover's code are shown as the verifier writes them; #196 renders them as subscripts in the panel only. ## Tests - `utils/message-markdown.spec.ts`: code spans incl. a multi-backtick and a padded span, the link at the reference's `start`, escaping of `* < _ | #`; call sequences as options; a diagnostic's headline, then notes, then counterexample, then hints; the headline alone when it has nothing else. - `LJDiagnosticsHandlerTest`: the diagnostic's message is the title alone. - Client: `npm run test:unit` (140 passed), `npm run test:typecheck`, `npm run lint`, `npx tsc --noEmit`. Server: `mvn -B test -Dtest=LJDiagnosticsHandlerTest`. - Rebased on `main` (after #196); the conflict in `webview/message-text.ts` resolved as described in the overlap note of the first version. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
CatarinaGamboa
added a commit
that referenced
this pull request
Nov 11, 2026
…r lines (#199) Closes #195 Names the verifier gives values of the code, such as `#if_condition`, `#getUndoManager_result` or `#case_condition@74`, now explain themselves on hover in plain words. When their source line is known, the hover gives it and a click goes there. ## What the verifier already sends **No verifier change is needed.** Since 0.0.38 (#196), the error's translation table is keyed by the name as shown, and it holds a position for every generated name in the error: - `#if_condition` → the condition, `#getUndoManager_result` → the call, `#case_condition@74` → its `case`, and so on. - Several values of one kind get distinct names (`#case_condition@71` … `@74`), so they no longer share one entry. The issue's note about this is out of date. - In A1_56, all 11 generated names in the 19 steps are in the table. The Context tab has no translation table. There, the server leaves out generated variables. This PR adds one field, `generatedPlaces` (name as shown → place). The server code is in this repo, so this is still a vscode-only change. ## What the hover says The text is the title of the name, with "at line N" when the line is known and "Click to go to it." when the name is a link. Every title ends with "LiquidJava gives it the name #…". | Name | Hover | |---|---| | `#if_condition` | The condition of the if at line N | | `#loop_condition` | The condition of the loop at line N | | `#ternary_condition` | The condition of the ? : at line N | | `#switch_selector` | The value the switch at line N checks | | `#case_condition` | Whether the case at line N matches | | `#try_branch` | Whether the try block at line N runs to its end, rather than a catch block | | `#catch_branch` | Whether this catch block of the try at line N runs, rather than a later one | | `#array_length` | The length of the array created at line N | | `#new_File` | The new File object created at line N | | `#size_result` | The value returned by the call to size() at line N | | `#count_value` | The value of the field count read at line N | | `#operation_result` | The result of the operation at line N | | `#expression_value` | The value of the expression at line N | **Where the line comes from:** - First, the error's translation table (the Context tab uses `generatedPlaces`). The name is then a link. - Otherwise, the name's line tag (`@74`). The line is shown, but the name is not a link. - Otherwise, the line is left out. **`extended#1`** is not a generated name. It is a line tag with no line, on a program variable, and #196 already explains it ("the 1st value of extended (line unknown)"). ## Where - **Expected.** - **Found steps:** - the binder column: the title of `∀#if_condition` was "Go to source (boolean)"; it is now the explanation, and the click still highlights the source; - the predicates. - **The step diff:** both the changed fragments and the unchanged tokens. - **The counterexample.** - **The Context tab's refinements.** The names have a dotted underline, like the binders, and a pointer cursor when they are links. A link uses the same `location-link` click as the message references from #193. ## Screenshots A1_56 EditCommand, Found at step 7/20, in headless VS Code (openvscode-server) with verifier 0.0.38. **Headless screenshots do not capture native tooltips.** The box under the name is drawn by the screenshot script from the element's real `title` attribute. On main, the same box shows "(no tooltip)" for the predicate and "Go to source (boolean)" for the binder. | | before (main) | after | |---|---|---| | `#getUndoManager_result` in a predicate, dark |  |  | | `∀#if_condition` binder, dark |  |  | | `#getUndoManager_result`, light |  |  | | `∀#if_condition` binder, light |  |  | There is no Context tab screenshot. In A1_56, the Context tab replaces each generated value by its expression or drops it, so no generated name is left to show. The unit test covers the Context tab. ## Changes - `client/src/webview/generated-names.ts` (new): the kinds and their wording, the hover text, and the rendered name. - `highlighting.ts`: the highlighter takes an optional `places` table (name → place). A generated name, together with its line tag, is rendered by `renderGeneratedName`. - `vc-changes.ts`, `errors.ts`, `counterexample.ts`, `context/*.ts`: pass the table through. `renderBinder` uses the explanation as its title. - Server: `ContextHistoryDTO.generatedPlaces`, filled by `ContextHistoryConverter`. ## Tests - `vc-changes.spec`: one test, which fails on main. It checks: - a binder linked through the table; - a predicate name that is linked, one with no place, and one with only a tag line; - `#ret`, which is left alone; - a binder with only a tag; - the diff path. - `context.spec`: one test, which fails on main: a refinement's name linked through `generatedPlaces`. - `ContextHistoryConverterTest`: `#array_length` of the Door fixture has its place. - Local runs: - `npm run test:unit` (142), `test:typecheck`, `lint`; - `mvn -B package` (45); - `VSCODE_TEST_VERSION=minimum xvfb-run -a npm test` (9 + 1 passing). ## Not in this PR - The headline message (`found … #getUndoManager_result …`) and the editor hover are markdown or plain text with no translation table, so their names are not explained. - `#ret` (a method's return value) is not one of the verifier's generated kinds and is left as is. - A method named `operation` or a field named `expression` would be described as an operation result or expression value, because the verifier names them alike. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #175
Verifier 0.0.38 (liquid-java/liquidjava#493, already the dependency on main) names variables as in code and, only when an error has several values of one name, tags the others with the line their value comes from:
preview@51. The message and the Context tab already used those names. The rest of the panel did not: the server formatted the Expected, the Found steps, the counterexample and the translation table with the verifier's default formatter. That formatter numbers clashes within each expression, so the Found of A3_07 showed three different values ofpreviewall as∀preview, andpreview#1meant a different value on each line.What 0.0.38 sends
x@51. When tagged values share a line,x@25#1,x@25#2; with no line,x#2. A call argument can carry one too:failures.size()@84. No Unicode superscripts any more.ContextDisplay, merged in Show the Context tab's refinements as the error messages show them #186) already use the names.LJError.getDisplayNames()gives the error's names for refinement and state refinement errors; nothing else is pre-formatted for the IDE.What changes
Server (
server/src/main/java/dtos)RefinementErrorDTOandStateRefinementErrorDTOformat the expected, each step's binder and predicate (VCImplicationDTO), and the counterexample witherror.getDisplayNames().TranslationTableDTOkeys each entry by the error's name for it (preview@51), so a tagged binder still opens its source. Errors without names keep the plain key.Webview
previewwith a smalll51below, titled "value of preview at line 51" (x@25#2→l25#2, "value 2 of x at line 25"). This applies in every highlighted expression (Expected, Found, steps, counterexample, Context), in the binders, and in the code of messages, notes and hints. Copy, the hover and the Problems panel keep the ASCIIpreview@51.preview@51as one token, so a changed tag highlights its whole variable."a@1"is not read as a tag.⁰-⁹.Against the issue's to-do
∀preview@51) through the re-keyed translation table. A tag inside a predicate shows only the tooltip, because the highlighter has no translation table. The line number is in the tag itself.ContextDisplaywithDisplayNamesandContextHistory.lineOf). This PR only renders its tags the same way.Screenshots (headless VS Code, light theme, verifier 0.0.38)
A3_07 ScannerOutputStage, the study exercise with several values of
preview.A2_08 LogWindow, plain names (no change, as for every other study exercise):
Not in this PR
#if_condition(Explain the verifier's generated names (#if_condition, call results, …) on hover #195).preview@54in the Context tab andpreviewin the error, as in the A3_07 screenshots. Making them agree would mean a verifier change.Expected conflicts
study-found-box): merges cleanly with its current head. It changesvc-implications.tsandstyles.ts; this PR adds one rule tostyles.tsand changesTOKEN_PATTERNandrenderBinderinvc-changes.ts. Any conflict would be instyles.ts(adjacent rules).message-text.ts.Tests
DiagnosticConverterTest: verifies ab = -bfixture and checks that the message, every Found step (∀b@6 b@6 == 8,∀b@7 b@7 == b@6 && b@7 > 0,∀b b == -b@7), the expected, the counterexample and the translation-table keys use the same names. On main the steps read∀b b == b#1 && b > 0.vc-changes.spec: tags render as subscripts with their tooltip (also after a call and with a number). A changed tag is diffed with its variable. A literal is left alone.diagnostics.spec: a tag in a message's code, next to a literal.context.specwas updated to the rendered tag.npm run test:unit(134),test:typecheck,lint,mvn -B package(44),VSCODE_TEST_VERSION=minimum xvfb-run -a npm test(9 + 1 passing).🤖 Generated with Claude Code