-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
pkg:presetIssues related to preset packagesIssues related to preset packagespriority:lowLow priorityLow priorityrulesMigration rules and patternsMigration rules and patternstype:featureNew feature or requestNew feature or request
Description
Summary
Enhance findMatchingBrace helper to correctly skip braces inside strings, comments, and template literals to avoid false positives when parsing code blocks.
Problem
Current implementation (in packages/preset-basic/src/helpers.ts) naively counts braces without considering context:
const findMatchingBrace = (content: string, startIndex: number): number => {
let depth = 1;
for (let i = startIndex + 1; i < content.length; i++) {
if (content[i] === '{') depth++;
if (content[i] === '}') depth--;
if (depth === 0) return i;
}
return -1;
};Edge cases that fail:
Effect.gen(function* () {
const message = "hello { world }"; // Braces in string
const template = `value: ${count}`; // Braces in template literal
// { This brace in a comment }
yield* doSomething();
});Proposed Solution
Enhance the function to:
- Skip string literals (single and double quoted)
- Skip template literals (backtick strings)
- Skip single-line comments (
//) - Skip multi-line comments (
/* */)
Alternative approach: Use TypeScript AST parsing with @typescript-eslint/parser for accurate parsing (more robust but heavier dependency).
Implementation Sketch
function findMatchingBrace(content: string, startIndex: number): number {
let depth = 1;
let inString: string | null = null; // ', ", or `
let inSingleLineComment = false;
let inMultiLineComment = false;
for (let i = startIndex + 1; i < content.length; i++) {
const char = content[i];
const nextChar = content[i + 1];
const prevChar = content[i - 1];
// Handle comment starts
if (!inString && char === '/' && nextChar === '/') {
inSingleLineComment = true;
i++; continue;
}
if (!inString && char === '/' && nextChar === '*') {
inMultiLineComment = true;
i++; continue;
}
// Handle comment ends
if (inSingleLineComment && char === '\n') {
inSingleLineComment = false;
continue;
}
if (inMultiLineComment && char === '*' && nextChar === '/') {
inMultiLineComment = false;
i++; continue;
}
// Skip if in comment
if (inSingleLineComment || inMultiLineComment) continue;
// Handle strings
if ((char === '"' || char === "'" || char === '`') && prevChar !== '\\') {
if (inString === char) {
inString = null;
} else if (!inString) {
inString = char;
}
continue;
}
// Skip if in string
if (inString) continue;
// Count braces
if (char === '{') depth++;
if (char === '}') depth--;
if (depth === 0) return i;
}
return -1;
}Acceptance Criteria
- Handles braces in double-quoted strings
- Handles braces in single-quoted strings
- Handles braces in template literals
- Handles braces in single-line comments
- Handles braces in multi-line comments
- Handles escaped quotes (
\\"and\\') - All existing tests pass
- New edge-case tests added
Alternative: TypeScript AST Parsing
For maximum robustness, consider using @typescript-eslint/parser:
import { parse } from '@typescript-eslint/parser';
// Parse and walk AST instead of regex/string matchingPros: Bulletproof parsing, handles all edge cases
Cons: Heavier dependency, slower for simple rules
Related
- Issue refactor(preset-basic): move helper functions to @effect-migrate/core #32 - Move helpers to core (should be done first)
- Identified during PR review: feat(cli,preset-basic): implement first-class preset support
- Thread: https://ampcode.com/threads/T-09db5199-2c22-42fd-9730-3a6f1c42e570
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
pkg:presetIssues related to preset packagesIssues related to preset packagespriority:lowLow priorityLow priorityrulesMigration rules and patternsMigration rules and patternstype:featureNew feature or requestNew feature or request