Skip to content

Document-link detector includes surrounding punctuation in matched range, breaking navigation #666

@couimet

Description

@couimet

Summary

When a RangeLink appears inside surrounding punctuation in prose (e.g., wrapped in parentheses), the document-link detector includes the leading punctuation character in the matched range. The dirty character is carried through to parsed.path and parsed.quotedPath, so navigation fails with Cannot find file: (packages/... even though the "Open with RangeLink" tooltip indicates the link was recognized.

Repro

Place a RangeLink inside parentheses in any text document:

... self-paste-blocked branch (packages/rangelink-vscode-extension/src/feedback/OperationFeedbackProvider.ts#L154-L162): apply the prefix ...

Hover the link — the tooltip reads "Open with RangeLink". Cmd-click the link.

Expected: the editor opens OperationFeedbackProvider.ts and selects lines 154–162.

Actual: a warning toast appears: Cannot find file: (packages/rangelink-vscode-extension/src/feedback/OperationFeedbackProvider.ts. The leading ( was included in the matched path.

Logs

[DEBUG] {"fn":"RangeLinkDocumentProvider.handleLinkClick","linkText":"(packages/rangelink-vscode-extension/src/feedback/OperationFeedbackProvider.ts#L154-L162","parsed":{"path":"(packages/rangelink-vscode-extension/src/feedback/OperationFeedbackProvider.ts","quotedPath":"'(packages/rangelink-vscode-extension/src/feedback/OperationFeedbackProvider.ts'","start":{"line":154},"end":{"line":162},"linkType":"regular","selectionType":"Normal"}} Document link clicked - delegating to handler
[INFO]  {"fn":"RangeLinkNavigationHandler.navigateToLink", ...} Navigating to RangeLink
[WARN]  {"fn":"RangeLinkNavigationHandler.navigateToLink", ...} Failed to resolve workspace path
[DEBUG] {"fn":"VscodeAdapter.showWarningMessage","message":"Cannot find file: (packages/rangelink-vscode-extension/src/feedback/OperationFeedbackProvider.ts"} Showing warning message

Both parsed.path and parsed.quotedPath retain the leading (, confirming the dirty character originates in the matched range, not in any downstream code.

Root cause (proposed)

The document-link detector's regex/range computation does not strip leading surrounding punctuation from the match. Links embedded in normal English prose are routinely wrapped in or followed by punctuation, so the detector should treat surrounding bracket characters, quotes, and trailing sentence terminators as boundaries rather than path content.

Proposed fix

Trim the matched range in the document-link detector so the following characters are excluded from the start and end of the link, when present:

  • Brackets: (, ), [, ], {, }, <, >
  • Quotes: ', ", `
  • Trailing sentence terminators: ., ,, :, ;

Trimming should be symmetric where appropriate (e.g., an opening ( at the start pairs with a closing ) at the end) and conservative for trailing punctuation (only strip when it would otherwise leave the path invalid). Fixing at the detector ensures parsed.path and parsed.quotedPath are clean for every downstream consumer (navigation handler, hover, future features) and removes the visual glitch of an underlined paren.

Regression coverage

Add two cases:

  1. A minimal synthetic case for the parser/detector unit tests: link wrapped in each supported pair ((foo.ts#L1-L2), [foo.ts#L1-L2], "foo.ts#L1-L2", etc.) and trailing sentence terminators (foo.ts#L1-L2.).
  2. A prose-embedded integration case mirroring the real-world repro: a paragraph containing ... branch (path#Lx-Ly): ... to prove the detector handles surrounding text correctly.

Notes

The link was generated by Claude Code inside a planning note. The "(path#Lx-Ly):" pattern shows up naturally whenever a link is parenthesized in English prose, so this affects real workflows even when no user manually constructs a bad link.

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority:highHigh priorityscope:corerangelink-core-ts packagetype:bugBug or defect in existing functionality

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions