Skip to content

JS/TS: line-continuation string inside template hole (${"foo\\\nbar"}) breaks hole scanner state #433

Description

@Widthdom

Summary

StructuralLineMasker の JS/TS template-hole scanner が、`${...}` の hole 内で登場する文字列リテラルを SkipJsSingleLineString() で「その行の中だけ」スキップしています。このため、hole 内の文字列が "foo\ → 改行 → bar" のような JS で legal な line-continuation string になっていると、次行ではまだ文字列の途中なのに通常の hole 走査へ戻ってしまいます。

Impact

  • 継続行内の } で hole を早閉じしてしまい、backtick 内テキストが hole-outside と誤認される
  • 継続行内の識別子風テキストが phantom reference として reference graph に混入する
  • 逆に hole 内に含まれるべき本物の call site が落ちる可能性がある

発生条件は狭いですが、実ソースで見かける legal JS 構文であり、reference graph の信用性に影響するため blocking defect と整理します。

Where

  • src/CodeIndex/Indexer/StructuralLineMasker.cs:1504 — JS template-hole scanner が SkipJsSingleLineString(line, pos) を呼ぶ分岐
  • src/CodeIndex/Indexer/StructuralLineMasker.cs:1875SkipJsSingleLineString 実装が line 境界で止まり、mid-string state を caller に返さない

Suggested fix

Hole scanner 側で single/double quote の state と escape state を JsLexState (または hole frame) に持たせて行跨ぎで保持する。あるいは、hole 内部専用にも LexJavaScriptLine 相当の stateful lexer を再利用し、line-continuation string が close するまで hole-scan を中断する。

Regression test

ReferenceExtractorTests に以下相当のケースを追加すれば lock できます:

  • const t = `before ${"line1\\`
  • line2" + Helper.Foo()} after`;
  • 期待: Helper.Foo は 1 件だけ(phantom 無し、落ちなし)

Discovered via

Adversarial review by Codex during PR work on issue #264 (fix/issue-264-string-interpolation). Unrelated to #264's C# scope — filed as a separate issue per project policy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions