Summary
run-histogram-diff.ts의 diffCore에서 앵커를 찾은 뒤 앵커 전후 서브구간에 대해 consumeCommonEdges를 호출하고 있다. 이 로직은 제거해도 정확성에 영향이 없다.
분석
현재 흐름 (96~117행)
앵커 발견
→ consumeCommonEdges(lhsLower~anchor.lhsStart, direction=2 suffix) → 재귀
→ 앵커 UNCHANGED 기록
→ consumeCommonEdges(anchor.lhsEnd~lhsUpper, direction=1 prefix) → 재귀
제거 가능한 이유
-
ID가 이미 정규화된 buffer 위에서 부여됨: buildDiffInput에서 whitespace === "collapse"이면 공백을 삽입한 buffer를 만들고, buildIdTables는 그 buffer의 raw byte로 ID를 부여한다. 즉 ID 자체가 공백 정규화된 텍스트를 반영.
-
SA/LCP가 같은 ID를 본다: findAnchor에서 구축하는 SA/LCP는 _lhsIds/_rhsIds 위에서 동작하므로, consumeCommonEdges의 _lhsIds[i] === _rhsIds[j] 체크가 잡는 것은 SA도 동일하게 잡을 수 있다.
-
matchPrefixTokens/matchSuffixTokens가 SA를 보완하는 실질적 케이스가 없다: 이 함수들은 토큰 경계를 넘어 char-by-char 비교를 하지만, tokenizer가 결정적(deterministic)이므로 같은 텍스트에서 토큰 분할이 달라지는 경우가 사실상 없다. ignoreWhitespace 모드에서도 마찬가지.
-
consume의 유일한 효과는 성능 최적화: 앵커 인접 동일 토큰을 O(k) 스캔으로 먹어서 재귀 + SA 재구축(O(n log n))을 피한다. 하지만 재귀로 내려가도 결국 같은 결과에 도달하므로, 코드 복잡성 대비 가치가 낮다.
앵커 미발견 시 consume (120~123행)
if (_ignoreWhitespaces) {
([lhsLower, lhsUpper, rhsLower, rhsUpper] = consumeCommonEdges(lhsLower, lhsUpper, rhsLower, rhsUpper, 3));
}
이 부분도 같은 논리로, SA가 앵커를 못 찾은 구간에서 matchPrefixTokens가 추가로 잡는 케이스가 사실상 없다.
변경 범위
core/src/diff/run-histogram-diff.ts: consumeCommonEdges 함수 및 호출부 제거
core/src/diff/helpers.ts: matchPrefixTokens, matchSuffixTokens export 제거 가능 (다른 곳에서 사용하지 않는 경우)
검증
- 기존 테스트 통과 확인
whitespace: "collapse" / "ignore" 양쪽 모드에서 diff 결과 동일 확인 필요
Summary
run-histogram-diff.ts의diffCore에서 앵커를 찾은 뒤 앵커 전후 서브구간에 대해consumeCommonEdges를 호출하고 있다. 이 로직은 제거해도 정확성에 영향이 없다.분석
현재 흐름 (96~117행)
제거 가능한 이유
ID가 이미 정규화된 buffer 위에서 부여됨:
buildDiffInput에서whitespace === "collapse"이면 공백을 삽입한 buffer를 만들고,buildIdTables는 그 buffer의 raw byte로 ID를 부여한다. 즉 ID 자체가 공백 정규화된 텍스트를 반영.SA/LCP가 같은 ID를 본다:
findAnchor에서 구축하는 SA/LCP는_lhsIds/_rhsIds위에서 동작하므로,consumeCommonEdges의_lhsIds[i] === _rhsIds[j]체크가 잡는 것은 SA도 동일하게 잡을 수 있다.matchPrefixTokens/matchSuffixTokens가 SA를 보완하는 실질적 케이스가 없다: 이 함수들은 토큰 경계를 넘어 char-by-char 비교를 하지만, tokenizer가 결정적(deterministic)이므로 같은 텍스트에서 토큰 분할이 달라지는 경우가 사실상 없다.ignoreWhitespace모드에서도 마찬가지.consume의 유일한 효과는 성능 최적화: 앵커 인접 동일 토큰을 O(k) 스캔으로 먹어서 재귀 + SA 재구축(O(n log n))을 피한다. 하지만 재귀로 내려가도 결국 같은 결과에 도달하므로, 코드 복잡성 대비 가치가 낮다.
앵커 미발견 시 consume (120~123행)
이 부분도 같은 논리로, SA가 앵커를 못 찾은 구간에서
matchPrefixTokens가 추가로 잡는 케이스가 사실상 없다.변경 범위
core/src/diff/run-histogram-diff.ts:consumeCommonEdges함수 및 호출부 제거core/src/diff/helpers.ts:matchPrefixTokens,matchSuffixTokensexport 제거 가능 (다른 곳에서 사용하지 않는 경우)검증
whitespace: "collapse"/"ignore"양쪽 모드에서 diff 결과 동일 확인 필요