Summary
The Lisp extractor at SymbolExtractor.Lisp.cs detects quoted forms like 'symbol, `symbol, ,symbol as bareword symbols because IsQuotedLispForm (line 94) checks only for a quote character at the opening paren, not quote prefixes on individual datums. When code contains 'defun, `let-binding, or ,unquoted-var, the extractor calls TryCreateLispSymbol on the name after the prefix (e.g. defun from 'defun), emitting false-positive function definitions. This breaks symbol navigation in metaprogramming-heavy codebases (macros, quasiquoted templates) because the extractor confuses quoted references with definitions.
Where
src/CodeIndex/Indexer/Symbols/SymbolExtractor.Lisp.cs:90-102 (main loop, quoted-form detection)
src/CodeIndex/Indexer/Symbols/SymbolExtractor.Lisp.cs:178-179 (definition name extraction; SkipLispQuotePrefixes called here but NOT in main loop)
Suggested approach
- In the main loop (Lisp.cs:90-102), call
SkipLispQuotePrefixes(maskedLine, cursor + 1) before checking if TryReadLispListHead should be invoked
- If a quote prefix is found, skip the entire quoted datum (do not treat it as a symbol definition), and advance
cursor past the closing paren
- Refactor
IsQuotedLispForm to return both a boolean and an adjusted cursor position; update call sites to use the adjusted position
- Add a blacklist of known Lisp special forms that should never be treated as definitions even without quotes:
quote, quasiquote, unquote, function, eval-when, etc.
- Write regression tests with
'(defun foo ...), `(let ((x 1)) ...), and ,,(expand-macro ...) to confirm they emit zero symbols (or only the invocation of the macro, not the definition it would produce)
- Extend masking in
MaskLispCodeLines to also mask string-literal quote prefixes so "'symbol" inside a docstring doesn't trigger quoted-form logic
Summary
The Lisp extractor at SymbolExtractor.Lisp.cs detects quoted forms like
'symbol,`symbol,,symbolas bareword symbols becauseIsQuotedLispForm(line 94) checks only for a quote character at the opening paren, not quote prefixes on individual datums. When code contains'defun,`let-binding, or,unquoted-var, the extractor callsTryCreateLispSymbolon the name after the prefix (e.g.defunfrom'defun), emitting false-positive function definitions. This breaks symbol navigation in metaprogramming-heavy codebases (macros, quasiquoted templates) because the extractor confuses quoted references with definitions.Where
src/CodeIndex/Indexer/Symbols/SymbolExtractor.Lisp.cs:90-102(main loop, quoted-form detection)src/CodeIndex/Indexer/Symbols/SymbolExtractor.Lisp.cs:178-179(definition name extraction;SkipLispQuotePrefixescalled here but NOT in main loop)Suggested approach
SkipLispQuotePrefixes(maskedLine, cursor + 1)before checking ifTryReadLispListHeadshould be invokedcursorpast the closing parenIsQuotedLispFormto return both a boolean and an adjusted cursor position; update call sites to use the adjusted positionquote,quasiquote,unquote,function,eval-when, etc.'(defun foo ...),`(let ((x 1)) ...), and,,(expand-macro ...)to confirm they emit zero symbols (or only the invocation of the macro, not the definition it would produce)MaskLispCodeLinesto also mask string-literal quote prefixes so"'symbol"inside a docstring doesn't trigger quoted-form logic