Cache regex matches and add ends_on option for Syntax definitions - #86
Conversation
…_Space(), Buffer_Clear()
…ng block. this leads to more flexibility and better performance
|
@coderabbitai review |
WalkthroughThis PR enhances the Buffer API with const-correctness improvements and extends the syntax definition/highlighting system by introducing an "ends_on" block relationship mechanism. It adds a caching layer for regex matching in the highlighting module with offset-aware matching, updates syntax definition linking to resolve ends_on relationships after child relationships, and adds corresponding test coverage. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~28 minutes The changes span multiple subsystems with mixed complexity: Buffer API updates are straightforward const-correctness improvements, but the ends_on mechanism introduces new definition-parsing phases and memory management, while the highlighting caching layer adds offset-aware regex matching and new block-relation handling. The heterogeneous nature and density of highlighting logic warrant moderate review attention. Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/syntax/definition.h (2)
68-72: Missing headers for bool and ssize_t cause portability/compile failures.
Include stdbool.h and sys/types.h in this public header.Apply this diff:
#include <stdint.h> #include <regex.h> +#include <stdbool.h> +#include <sys/types.h> #include "common/table.h" #include "common/string.h"
41-63: Header docs out of date (allowed_blocks vs child_blocks; add ends_on).
Update narrative to use child_blocks and describe ends_on. Also note root semantics accordingly.Apply this diff (adjust wording as needed):
- * Blocks that define an `end` expression may additionally define a list of - * `allowed_blocks`, which specifies which block types are permitted to appear - * inside the block. + * Blocks that define an `end` expression may additionally define + * `child_blocks`, which specifies which block types may appear inside. + * A block can also define `ends_on`, a list of block types whose start + * implicitly terminates the current block. * - * The root block does not need defined `start` or `end` patterns but should - * define an `allowed_blocks` list (otherwise nothing will be found). + * The root block does not need `start` or `end` patterns but should define + * `child_blocks` (otherwise nothing will be found).
🧹 Nitpick comments (13)
tests/test_syntax_highlighting.c (2)
156-257: Table‑driven tests: good coverage; add one equality-edge case.
Consider adding a case where a child start and a parent end coincide (same byte_offset) to pin down tie-breaking. Current logic uses strict “<” and will prefer the end over the child when equal.
258-279: Ends-on test INI looks correct; add no-comment variant.
Add a case like "foo=value" (no comment) to ensure value runs to EOL and assignment closes as expected.tests/test_syntax_definition.c (1)
211-238: Ends-on linkage test is sound; consider verifying actual targets.
Optionally assert that block1->ends_on[0/1]->name are "block3"/"block2" (order preserved) to catch mapping mistakes.src/syntax/definition.h (2)
102-110: MatchCache API exposure: document lifetime and thread-safety.
Since caches live in SyntaxBlockDef, clarify they’re per-highlight run and not thread-safe; consumers must not share a SyntaxDefinition across concurrent highlight calls without external synchronization.
125-132: Public struct growth: ensure zero-init in creators.
start_cache/end_cache aren’t initialized in SyntaxBlockDef_Create(); highlighting.c does init them before use, but add explicit zero-init here to prevent accidental misuse elsewhere.Apply this diff:
SyntaxBlockDef *SyntaxBlockDef_Create();And in the corresponding implementation (definition.c):
block->children_count = 0; block->ends_on = NULL; block->ends_on_count = 0; +memset(&block->start_cache, 0, sizeof(block->start_cache)); +memset(&block->end_cache, 0, sizeof(block->end_cache));src/syntax/highlighting.c (5)
102-120: regexec_with_cache: semantics OK; guard comment for ‘done’.
Add a brief comment that once a pattern is “done”, no further matches can occur for increasing offsets because regexec scans the remainder. Avoids future regressions.
156-169: Cache init is correct; small nit: use memset for brevity.
Optional style tweak.Apply this diff:
- block->start_cache.match.rm_so = -1; - block->start_cache.match.rm_eo = -1; - block->start_cache.offset = 0; - block->start_cache.done = false; - block->end_cache.match.rm_so = -1; - block->end_cache.match.rm_eo = -1; - block->end_cache.offset = 0; - block->end_cache.done = false; + memset(&block->start_cache, 0, sizeof(block->start_cache)); + block->start_cache.match.rm_so = -1; + block->start_cache.match.rm_eo = -1; + memset(&block->end_cache, 0, sizeof(block->end_cache)); + block->end_cache.match.rm_so = -1; + block->end_cache.match.rm_eo = -1;
218-221: Define tie-breaking explicitly (equal offsets).
Current checks use strict “<”. On equal offsets, end wins over child, and end wins over ends_on. If this is intended, add a comment; if not, switch to “<=” accordingly.Also applies to: 237-239, 258-272
171-183: Thread-safety: caches live in SyntaxBlockDef.
If the same SyntaxDefinition is highlighted concurrently, caches will race. Either:
- document non-thread-safety and require external synchronization, or
- move caches into a per-call structure keyed by SyntaxHighlightingString.
Also applies to: 194-197
51-65: Minor: preallocate tags capacity once.
You allocate tags on Create and then realloc on first add because tags_capacity is 0. Initialize tags_capacity to SHS_TAGS_INITIAL_CAPACITY in Create to avoid the immediate realloc.Apply this diff:
shs->tags = NULL; shs->tags_count = 0; -shs->tags_capacity = 0; +shs->tags_capacity = SHS_TAGS_INITIAL_CAPACITY; ... -shs->tags = malloc(sizeof(SyntaxHighlightingTag) * SHS_TAGS_INITIAL_CAPACITY); +shs->tags = malloc(sizeof(SyntaxHighlightingTag) * shs->tags_capacity);src/syntax/definition.c (3)
220-241: Name mapping: message uses old term.
Error comment still references allowed_blocks; update to child_blocks (and/or ends_on) to match current keys.Apply this diff:
- // something like - // allowed_blocks = block1, non_existing_block + // e.g., child_blocks = block1, non_existing_block
243-281: block_name_list_str_to_blocks: free on error is safe but be explicit.
On error, you already return and SyntaxDefinition_Destroy will free block->children/ends_on. Add a brief comment to clarify the ownership to future readers.
358-365: Comment nit: “construct the ends_by list” → “ends_on list”.Apply this diff:
- // construct the ends_by list + // construct the ends_on list
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/common/buffer.c(2 hunks)src/common/buffer.h(3 hunks)src/syntax/definition.c(5 hunks)src/syntax/definition.h(3 hunks)src/syntax/highlighting.c(4 hunks)tests/test_syntax_definition.c(4 hunks)tests/test_syntax_highlighting.c(5 hunks)
🔇 Additional comments (16)
src/common/buffer.h (3)
51-54: LGTM! Clear API addition.The
Buffer_Clearfunction provides a straightforward way to reset the buffer state without deallocation.
78-78: Excellent const-correctness improvements.Making these read-only accessors accept
const Buffer *is the correct approach and prevents accidental mutations.Also applies to: 81-81, 84-84, 96-96
86-87: LGTM! Useful utility function.The
Buffer_HasSpacedeclaration is appropriate. Will verify the implementation logic in buffer.c.src/common/buffer.c (3)
42-45: LGTM! Clean buffer reset.The implementation correctly resets the buffer state by clearing the count and cursor. Not zeroing the actual memory is appropriate for performance.
73-73: LGTM! Const-correctness properly applied.The implementations correctly match the updated header declarations with const qualifiers.
Also applies to: 77-77, 81-81, 89-89
94-96: Good defensive check added.Adding the NULL guard for
out_elementprevents undefined behavior. This changes the function to return false instead of crashing when NULL is passed, which is a reasonable defensive improvement.tests/test_syntax_highlighting.c (4)
99-103: LGTM: switch to child_blocks in test_ini0 is consistent with parser changes.
137-143: LGTM: updated child_blocks lists reflect nesting rules used in tests.
281-291: LGTM: moderate test validates ends_on transition and tag ordering at the same final offset.
394-394: Suite registration: OK.tests/test_syntax_definition.c (3)
161-161: LGTM: error cases now use child_blocks and assert SYNTAXDEFINITION_BLOCK_DOES_NOT_EXIST.Also applies to: 169-169
193-193: LGTM: children linkage test updated for child_blocks.
247-247: Suite registration: OK.src/syntax/definition.c (3)
50-52: ends_on memory management: OK.Also applies to: 60-63
294-301: child_blocks key linkage: OK.
303-321: ends_on linkage: OK.
* add String_Split() and String_Trim() with tests * add example syntax definition * Feat/Implement Syntax Definitions (#84) * add SyntaxBlockDef and SyntaxDefinition declarations * add TableIterator (#79) * add TableIterator * change include that provides ssize_t * add additional tests * make current slot pointer const * include stdbool.h for bool * Add table iteration API and improve parsing robustness (#83) * add TableIterator (#79) * add TableIterator * change include that provides ssize_t * add additional tests * make current slot pointer const * include stdbool.h for bool * WIP: implement definition loader * add Table_GetUsage() * allow ':' in INI file key names * fix location of tests * fix typo in Doxygen comment * add NULL guard to String_Take() * Add early-exit guards to table lookup functions (#80) * Fix bug in reading operations on an empty table * add check for empty table also to Table_Delete() * add functiond to create SyntaxDefinition_FromTable() with tests. More tests needed * additional tests (still not enough) * fix: free correct regex in regex_end branch in SyntaxBlockDef_FromTable() * fix: wrong numbe of arguments in String_Format() call in SymtaxBlockDef_FromTable() * add explanation * fix correct recognition of root block * fix memory lealk * add NULL guard for strdup in init_definition() * fix last fix * add additional test * add documentation * Feat/Syntax Highlighting: Add module to generate Highlighting information (#85) * add Stack_Copy() and Stack_IsEmpty() * fix: return copy in Stack_Copy() * implement syntax highlighting * add Table_CreateCustom() and Table_CreatePtr() * fix minor typing bugs * add Stack_Create(), Stack_Destroy() * fix but in find_first_child to actually return the child with the first occurence * automatically add patterns to end only_start blocks and to start/end root * fix memory leak produced in last commit * fix tests * fix bug in SyntaxHighllighting_HighlightString(): check if child or block end comes first * add basic tests * use root block it open_blocks parameter is NULL in SyntaxHighlighting_HighlightString() * add random tests * handle src->capacity == 0 in Stack_Copy() * add NULL pointer guard before using the key_free_func() function pointer in the Table module * fix error message for end_regex compilation error in SyntaxBlockDef_FromTable() * correct inlcudes * fix typo * add missing includes * change examples in documentation * change "key == NULL" to "!key" for non pointer keys * do not shadow parameter match in find_first_block() * change first parameter name in SyntaxHighlighting_HighlightString() for consitency * Cache regex matches and add ends_on option for Syntax definitions (#86) * add const to parameter if function does not modify it. add Buffer_Has_Space(), Buffer_Clear() * cache regex results for better performance * add "ends_on" (INI) property to SyntaxBlockDef * implement ends_on in the SyntaxHighlight modul * remove the check if the ends_on block is allowed inside the surrounding block. this leads to more flexibility and better performance * add additional (but just a single) test for the new feature * add Stack_CopyTo() * save open_blocks_at_begin and open_blocks_at_end to SyntaxHighlightingString instances ins SyntaxHighlighting_HighlightString() * Add Syntax Highlighting binding for TextBuffer (#87) * add TableIterator (#79) * add TableIterator * change include that provides ssize_t * add additional tests * make current slot pointer const * include stdbool.h for bool * Add early-exit guards to table lookup functions (#80) * Fix bug in reading operations on an empty table * add check for empty table also to Table_Delete() * Add CodeRabbit configuration template Added a comprehensive configuration template for CodeRabbit, including global settings, review settings, chat configurations, knowledge base settings, and code generation options. * add SyntaxHighlightingBinding to connect SyntaxHighlighting with the TextBuffer/TextLayout * fix some obvious bugs in SyntaxHighlighingBinding * fix memory leak * add basic test * add Stack_Size() * rename test function * add Stack_CopyTo() * save open_blocks_at_begin and open_blocks_at_end to SyntaxHighlightingString instances ins SyntaxHighlighting_HighlightString() * adept code to the changed SyntaxHighlighingString scheme * improve tests * Compare the open_blocks_at_begin with the open_blocks parameter for an early exit int SyntaxHighlighting_HighlightString() * add testcases and improve test framework's flexibility * fix coderabbit config * fix resizing in Stack_CopyTo() * add NULL guard to SyntaxHighlighting_HighlightString() * change multiline string to valid C string * change multiline strings to valid C strings * set shs->tags_capacity correctly in SyntaxHighlioghtingString_Create() * make argv0 available through Config * Add File_Exits(), File_OpenConfig() and File_OpenProjectFile() * change defautl width * fix wrong function calls * use new File_LoadConfig() function * remove unused variable * check if snprintf() truncated the path * fix function declaration of File_OpenProjectFile() * Implement a loader function to load a complete SyntaxHighlighting engine from an INI file Enable compile_commands.json and improve syntax handling (#88) * propagate PATH_MAX by file.h * create compile_commands.json (for correct using include paths in vscode) * add create and destroy functions to SyntaxHighlighting * SyntaxHighlighting now takes the ownership of the used SyntaxDefinition * must not destroy SyntaxDefinition anymore since this is handled by SyntaxHighlighting * fix bug in find_project_file() * implement the SyntaxHighlighting_LoadFromFile() function and tests * add NULL guard * Initialize error properly in SyntaxHighlighting_LoadFromFile() * guard againsst line == NULL and handle last_line == NULL in SyntaxHighlightingBinding_Update() * fix bug in concat_paths() * add test_definition_error to TEST_LIST * Integrate SyntaxHighlighting to the editor (#89) * wip * link to the data directory in the build directory * example syntax definitions * massive changes to get syntax highlighting working... need to optimization and better organisation, lot of work arounds * comment out TESTFILE definition * destroy SyntaxHighlighting instance properly * fix Table_Get() call in draw_visual_line() to use the correct key * improve highlighting * add Config_SetSyntax(), Config_GetSyntax() * use getopt() to parse cmd arguments, take syntax type from cmd arguments * Trigger a full SyntaxHighlighting update once in the beginning * add hint that byte offset is used * update screenshot * improve markdown highlighting * remove TESTFILE debugging stuff * handle the case that no highlighting is selected * deinitialize IniParser at ealry exit if c == NULL in Config_LoadIni() * remove double deinitialization of TextSelection in editor_destroy() * fix parse_arguments() and update print_help() * fix critical bug in Table_Set/Get(): change state of tombstones when reusing them * anchor section block start to newline * fix comment * fix off-by-one bug in Buffer_HasSpace() * guard against NULL in SyntaxHighlightingBinding_UpdateAll() * update syntax definitions * fix off-by-one bug in SyntaxHighlightingString_AddTag() * fix potential int overflow * add comment * minor change to const correctness in cpy_ptr * update readme * fix intendation
Summary by CodeRabbit
New Features
Bug Fixes & Improvements
Refactor
Tests