From 953651d8082e722d4673232edd1d701a821ebfb7 Mon Sep 17 00:00:00 2001 From: Widthdom Date: Wed, 12 Aug 2026 02:36:42 +0900 Subject: [PATCH 01/45] Refactor markup symbol extractors by language --- .../Indexer/Symbols/SymbolExtractor.Html.cs | 943 +++++ .../Symbols/SymbolExtractor.Markdown.cs | 509 +++ .../Indexer/Symbols/SymbolExtractor.Markup.cs | 3289 ----------------- .../Indexer/Symbols/SymbolExtractor.Xaml.cs | 1589 ++++++++ .../Indexer/Symbols/SymbolExtractor.Xml.cs | 282 ++ 5 files changed, 3323 insertions(+), 3289 deletions(-) create mode 100644 src/CodeIndex/Indexer/Symbols/SymbolExtractor.Html.cs create mode 100644 src/CodeIndex/Indexer/Symbols/SymbolExtractor.Markdown.cs delete mode 100644 src/CodeIndex/Indexer/Symbols/SymbolExtractor.Markup.cs create mode 100644 src/CodeIndex/Indexer/Symbols/SymbolExtractor.Xaml.cs create mode 100644 src/CodeIndex/Indexer/Symbols/SymbolExtractor.Xml.cs diff --git a/src/CodeIndex/Indexer/Symbols/SymbolExtractor.Html.cs b/src/CodeIndex/Indexer/Symbols/SymbolExtractor.Html.cs new file mode 100644 index 000000000..48eba1a7b --- /dev/null +++ b/src/CodeIndex/Indexer/Symbols/SymbolExtractor.Html.cs @@ -0,0 +1,943 @@ +using System.Text; +using System.Text.RegularExpressions; +using Regex = CodeIndex.Indexer.BoundedRegex; +using System.Runtime.CompilerServices; +using CodeIndex.Models; + +namespace CodeIndex.Indexer; + +public static partial class SymbolExtractor +{ + + private static List ExtractHtmlSymbols(long fileId, string rawText, string[] lines) + { + const string defaultSlotSymbolName = "(default)"; + + if (!LinesContain(lines, '<')) + return []; + + // HTML needs proper tag-structure awareness so attribute lookalikes inside + // other attributes' quoted values (e.g. ``) + // don't leak phantom imports AND real attributes on the same tag aren't + // skipped. Regex alone can't do this — the outer tag context is lost once + // an attribute inside it is rejected — so walk the masked text with a + // character state machine that enumerates each tag's attributes in order. + // HTML は同一タグ内で別属性の引用符付き値に書かれた attribute 名の文字列(例: + // ``)から phantom な import を + // 漏らさず、かつ本物の属性を飛ばさないために、タグ構造を理解した走査が必要。 + // regex だけでは、タグ内のある属性を mask で落とした瞬間に外側タグのコンテキスト + // を失うため不可能。マスク済みテキストを文字単位の state machine で走査し、タグ + // ごとに属性を列挙していく。 + var maskedText = MayNeedHtmlRawTextMask(rawText) + ? MaskHtmlRawTextRegions(rawText) + : rawText; + + // Build per-line absolute offsets only once a symbol needs O(log n) + // offset-to-line lookup. Plain markup with no emitted symbols can skip it. + // シンボルが offset-to-line lookup を必要とする時だけ行ごとの絶対 offset を作る。 + // emit 対象のない plain markup では確保を避ける。 + int[]? lineStarts = null; + + List? symbols = null; + var pos = 0; + while (pos < maskedText.Length) + { + if (maskedText[pos] != '<') + { + pos++; + continue; + } + + // Skip closing tags, comments/doctypes/CDATA, and processing instructions. + // Raw-text bodies (