All files / src/llm-orchestration/action-handlers/matchers exact.matcher.ts

100% Statements 23/23
100% Branches 7/7
100% Functions 3/3
100% Lines 22/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83            9x 39x     26x     26x 5x                 21x 6x                 15x                               6x 6x 6x   6x 6x 18x 18x     12x 12x     12x   12x   12x                 12x     6x      
import { ContentMatcher, MatchResult, MatchCandidate } from './base.matcher';
 
/**
 * Exact string matcher - the original implementation.
 * Fastest but requires character-for-character match.
 */
export class ExactMatcher implements ContentMatcher {
  readonly name = 'ExactMatcher';
 
  match(searchBlock: string, content: string): MatchResult {
    const parts = content.split(searchBlock);
 
    // No match found
    if (parts.length === 1) {
      return {
        found: false,
        unique: false,
        confidence: 0,
        candidates: [],
      };
    }
 
    // Multiple matches (not unique)
    if (parts.length > 2) {
      return {
        found: true,
        unique: false,
        confidence: 1.0,
        candidates: this.extractAllCandidates(searchBlock, content),
      };
    }
 
    // Unique match found
    return {
      found: true,
      unique: true,
      confidence: 1.0,
      before: parts[0],
      after: parts[1],
    };
  }
 
  /**
   * Extract all candidates when multiple exact matches exist.
   */
  private extractAllCandidates(
    searchBlock: string,
    content: string,
  ): MatchCandidate[] {
    const candidates: MatchCandidate[] = [];
    const lines = content.split('\n');
    const searchLines = searchBlock.split('\n');
 
    let currentIndex = 0;
    while (true) {
      const foundIndex = content.indexOf(searchBlock, currentIndex);
      if (foundIndex === -1) break;
 
      // Calculate line numbers
      const startLine = content.substring(0, foundIndex).split('\n').length - 1;
      const endLine = startLine + searchLines.length - 1;
 
      // Extract anchors
      const beforeAnchor = startLine > 0 ? lines[startLine - 1] : undefined;
      const afterAnchor =
        endLine < lines.length - 1 ? lines[endLine + 1] : undefined;
 
      candidates.push({
        block: searchBlock,
        startLine,
        endLine,
        confidence: 1.0,
        beforeAnchor,
        afterAnchor,
      });
 
      currentIndex = foundIndex + 1;
    }
 
    return candidates;
  }
}