@@ -509,54 +509,72 @@ export function mergeCvb(baseCvb: Cvb, tcvb: TCVB) : Cvb
509509
510510function diagnoseMatchFailure ( strContent : string , op : ExactReplaceOperation ) : string
511511{
512- function findLineNumber ( content : string , pattern : RegExp ) : number [ ]
512+ function findLineNumberRange ( content : string , pattern : RegExp ) : [ number , number ]
513513 {
514- const lines = content . split ( "\n" ) ;
515- return lines
516- . map ( ( line , index ) => ( pattern . test ( line ) ? index + 1 : - 1 ) )
517- . filter ( index => index !== - 1 ) ;
514+ let match ;
515+ let minLine = - 1 , maxLine = - 1 ;
516+ while ( ( match = pattern . exec ( content ) ) !== null )
517+ {
518+ const matchStartLine = content . substring ( 0 , match . index ) . split ( "\n" ) . length ;
519+ if ( minLine === - 1 || matchStartLine < minLine )
520+ {
521+ minLine = matchStartLine ;
522+ }
523+ if ( matchStartLine > maxLine )
524+ {
525+ maxLine = matchStartLine ;
526+ }
527+ }
528+ return [ minLine , maxLine ] ;
518529 }
519530
520531 let errorMessages : string [ ] = [ ] ;
521- const beforeAnchorPattern = new RegExp ( op . m_strBeforeAnchor , "gm " ) ;
522- const afterAnchorPattern = new RegExp ( op . m_strAfterAnchor , "gm " ) ;
523- const oldContentPattern = new RegExp ( op . m_strOldContent , "gm " ) ;
532+ const beforeAnchorPattern = new RegExp ( normalizeLineWhitespace ( escapeRegExp ( op . m_strBeforeAnchor ) ) , "gs " ) ;
533+ const afterAnchorPattern = new RegExp ( normalizeLineWhitespace ( escapeRegExp ( op . m_strAfterAnchor ) ) , "gs " ) ;
534+ const oldContentPattern = new RegExp ( normalizeLineWhitespace ( escapeRegExp ( op . m_strOldContent ) ) , "gs " ) ;
524535
525- const beforeAnchorLines = findLineNumber ( strContent , beforeAnchorPattern ) ;
526- const afterAnchorLines = findLineNumber ( strContent , afterAnchorPattern ) ;
527- const oldContentLines = findLineNumber ( strContent , oldContentPattern ) ;
536+ const beforeAnchorRange = findLineNumberRange ( strContent , beforeAnchorPattern ) ;
537+ const afterAnchorRange = findLineNumberRange ( strContent , afterAnchorPattern ) ;
538+ const oldContentRange = findLineNumberRange ( strContent , oldContentPattern ) ;
528539
529- if ( beforeAnchorLines . length === 0 )
540+ if ( beforeAnchorRange [ 0 ] === - 1 )
530541 {
531542 errorMessages . push ( `FILE: ${ op . m_strFilePath } 未找到 BEFORE_ANCHOR:\n\`\`\`\n${ op . m_strBeforeAnchor } \n\`\`\`` ) ;
543+ console . log ( `FILE: ${ op . m_strFilePath } 未找到 BEFORE_ANCHOR:\n\`\`\`\n${ op . m_strBeforeAnchor } \n\`\`\`\n表达式\n${ beforeAnchorPattern } ` ) ;
532544 }
533-
534- if ( afterAnchorLines . length === 0 )
545+
546+ if ( afterAnchorRange [ 0 ] === - 1 )
535547 {
536548 errorMessages . push ( `FILE: ${ op . m_strFilePath } 未找到 AFTER_ANCHOR:\n\`\`\`\n${ op . m_strAfterAnchor } \n\`\`\`` ) ;
549+ console . log ( `FILE: ${ op . m_strFilePath } 未找到 AFTER_ANCHOR:\n\`\`\`\n${ op . m_strAfterAnchor } \n\`\`\`\n表达式\n${ afterAnchorPattern } ` ) ;
537550 }
538-
539- if ( oldContentLines . length === 0 )
551+
552+ if ( oldContentRange [ 0 ] === - 1 )
540553 {
541554 errorMessages . push ( `FILE: ${ op . m_strFilePath } 未找到 OLD_CONTENT:\n\`\`\`\n${ op . m_strOldContent } \n\`\`\`` ) ;
555+ console . log ( `FILE: ${ op . m_strFilePath } 未找到 OLD_CONTENT:\n\`\`\`\n${ op . m_strOldContent } \n\`\`\`\n表达式\n${ oldContentPattern } ` ) ;
542556 }
543557
544558 if ( errorMessages . length === 0 )
545559 {
546- const minBeforeLine = Math . min ( ... beforeAnchorLines ) ;
547- const maxAfterLine = Math . max ( ... afterAnchorLines ) ;
548- const minOldLine = Math . min ( ... oldContentLines ) ;
549- const maxOldLine = Math . max ( ... oldContentLines ) ;
560+ const lastBeforeAnchorLine = beforeAnchorRange [ 1 ] ; // beforeAnchorPattern 最后匹配的行号
561+ const firstAfterAnchorLine = afterAnchorRange [ 0 ] ; // afterAnchorPattern 第一次匹配的行号
562+ const firstOldContentLine = oldContentRange [ 0 ] ; // oldContentPattern 第一次匹配的行号
563+ const lastOldContentLine = oldContentRange [ 1 ] ; // oldContentPattern 最后匹配的行号
550564
551- if ( minOldLine < minBeforeLine || maxOldLine > maxAfterLine )
565+ if ( firstOldContentLine < lastBeforeAnchorLine || lastOldContentLine > firstAfterAnchorLine )
552566 {
553567 errorMessages . push (
554- `FILE: ${ op . m_strFilePath } OLD_CONTENT 应该在 BEFORE_ANCHOR 和 AFTER_ANCHOR 之间:\nBEFORE_ANCHOR:\n\`\`\`\n${ op . m_strBeforeAnchor } \n\`\`\`\nOLD_CONTENT:\n\`\`\`\n${ op . m_strOldContent } \n\`\`\`\nAFTER_ANCHOR:\n\`\`\`\n${ op . m_strAfterAnchor } \n\`\`\``
555- ) ;
568+ `FILE: ${ op . m_strFilePath } OLD_CONTENT 应该在 BEFORE_ANCHOR 和 AFTER_ANCHOR 之间:\nBEFORE_ANCHOR:\n\`\`\`\n${ op . m_strBeforeAnchor } \n\`\`\`\nOLD_CONTENT:\n\`\`\`\n${ op . m_strOldContent } \n\`\`\`\nAFTER_ANCHOR:\n\`\`\`\n${ op . m_strAfterAnchor } \n\`\`\`` ) ;
556569 }
557570 }
558571
559- return errorMessages . length > 0 ? errorMessages . join ( "\n" ) : "" ;
572+ if ( errorMessages . length === 0 ) {
573+ errorMessages . push (
574+ `原因未知, FILE: ${ op . m_strFilePath } BEFORE_ANCHOR:\n\`\`\`\n${ op . m_strBeforeAnchor } \n\`\`\`\nOLD_CONTENT:\n\`\`\`\n${ op . m_strOldContent } \n\`\`\`\nAFTER_ANCHOR:\n\`\`\`\n${ op . m_strAfterAnchor } \n\`\`\`` ) ;
575+ }
576+
577+ return errorMessages . join ( "\n" ) ;
560578}
561579
562580function applyExactReplace ( strContent : string , op : ExactReplaceOperation ) : string
0 commit comments