Conversation
…rce line
pine_check printed TradingView's raw message templates, so a real compile error
came back as:
Undeclared identifier "{identifier}"
pine-facade does not interpolate its messages — it sends the values separately
in a `ctx` map alongside the template, and `check()` was dropping that field:
{"code": "CE10272",
"ctx": {"identifier": "risk"},
"message": "Undeclared identifier \"{identifier}\"",
"start": {"line": 139, "column": 5}}
Fill the placeholders from `ctx`, pass the error `code` through, and add an
`annotated` view that shows the offending line with a caret under the reported
column:
139 | risk := atrVal * slMult
| ^-- Undeclared identifier "risk"
Placeholders with no matching `ctx` key are left alone rather than blanked, so
a template this code has not seen degrades to today's behaviour instead of
losing text. Warnings get the same treatment.
This matters most on builds where the Pine editor has no React fiber and every
pine_* editor tool fails: pine_check is then the only compile path left, and
its output is the entire error report.
Adds tests/pine_annotate.test.js — 8 tests, fetch stubbed, no network or
TradingView needed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DsdBoQLyPJihjuyYbPkda6
There was a problem hiding this comment.
🟡 Changes recommended
annotate() should defensively handle CRLF input and clamp untrusted column values to avoid misrendered output and potential large-string allocations.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Improves pine_check output by interpolating pine-facade error/warning message templates using the provided ctx map, and by adding an annotated string that shows the offending source line with a caret at the reported column to make compiler feedback actionable without opening TradingView.
Changes:
- Add
{placeholder}interpolation (and pass throughcode) for errors and warnings returned by pine-facade. - Add
annotatedoutput via a newannotate()helper, included only when there are warnings/errors. - Add unit tests and update documentation/tool descriptions to reflect the enhanced
pine_checkoutput.
File summaries
| File | Description |
|---|---|
| tests/pine_annotate.test.js | Adds unit coverage for interpolation and annotated caret rendering. |
| src/tools/pine.js | Updates pine_check tool description to mention annotated. |
| src/core/pine.js | Implements message interpolation, surfaces code, and adds annotated generation. |
| README.md | Documents pine_check’s new annotated output with an example. |
| package.json | Ensures the new unit test runs under test:unit / test:all. |
| CLAUDE.md | Updates the Pine workflow docs to recommend starting with pine_check and describes annotated. |
Review details
- Files reviewed: 6/6 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| // Render the offending source lines with the compiler's complaint attached, so | ||
| // the caller can fix an error without counting columns by hand. | ||
| export function annotate(source, issues) { | ||
| const lines = source.split('\n'); |
| const src = lines[ln - 1]; | ||
| const gutter = String(ln).padStart(4, ' '); | ||
| const pad = ' '.repeat(5) + '|' + ' '.repeat(1 + Math.max(0, (issue.column ?? 1) - 1)); |
Both from Copilot's review: - split on /\r?\n/ so a CRLF script doesn't leave a stray CR in the rendered line, which pushed the caret out of alignment with the text above it - clamp the column into [1, line length + 1] and require an integer, so a malformed column can't allocate a huge pad string The upper bound is length + 1, not length: "Syntax error at input 'end of line without line continuation'" legitimately points one past the last character, and clamping to the text would have moved that caret onto it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DsdBoQLyPJihjuyYbPkda6
|
Both Copilot points addressed in
One nuance on the clamp: the upper bound is Three tests added for it — CRLF alignment, a |
The bug
pine_checkreturns TradingView's message templates verbatim, so a real compile error reads:pine-facade doesn't interpolate its own messages. It sends the values separately in a
ctxmap next to the template, andcheck()insrc/core/pine.jswas readinge.messagewhile droppinge.ctx:{"code": "CE10272", "ctx": {"identifier": "risk"}, "message": "Undeclared identifier \"{identifier}\"", "start": {"line": 139, "column": 5}}So the one field the caller actually needs — which identifier — was being thrown away on every error.
The fix
Fill the placeholders from
ctx, pass the errorcodethrough, and add anannotatedview showing the offending line with a caret under the reported column:A placeholder with no matching
ctxkey is left as-is rather than blanked, so an unrecognised template degrades to today's behaviour instead of losing text. Warnings get the same treatment.annotatedis omitted entirely when the script is clean, so nothing changes for a passing check.This matters most on builds where the Pine editor has no React fiber —
pine_set_source/pine_smart_compile/pine_get_errorsall fail there (several open PRs are chasing variants of this), andpine_checkbecomes the only compile path left. Its output is then the entire error report.What I ran
Against the live pine-facade endpoint, 15 real third-party Pine scripts (v5 and v6, 2.5KB–20KB) were checked end to end: 13 compiled clean, 2 had genuine errors. Both error cases printed raw
{identifier}/{funId}templates before this change and read correctly after:The second one is the case that convinced me this was worth filing — untouched, it names neither the function nor the argument.
npm run test:e2ewas not run: no TradingView Desktop on this machine, and this path never opens a CDP connection.check()posts to pine-facade from the server process, so there is nothing browser-side for the change to affect.Tests
tests/pine_annotate.test.js, 8 tests, fetch stubbed — no network, no TradingView. Covers caret column alignment, out-of-range and missing-column input, multiple issues,ctxinterpolation for errors and warnings, an unknown placeholder, andannotatedbeing absent on a clean compile.🤖 Generated with Claude Code
https://claude.ai/code/session_01DsdBoQLyPJihjuyYbPkda6