import * as vscode from 'vscode' ; import * as interfaces from './interfaces' ; import { DocumentMergeConflict } from './documentMergeConflict' ; import * as vm from 'vm' ; import * as util from 'util' ; export class MergeConflictParser { static scanDocument ( document ) { const conflictMatcher = new RegExp ( [ /(^<<<<<<<\s(.+)\r?\n)/ , /([\s\S]*?)/ , /(^=======\r?\n)/ , /([\s\S]*?)/ , /(^>>>>>>>\s(.+)\r?\n)/ ] . map ( r => r . source ) . join ( '' ) , 'mg' ) ; const offsetGroups = [ 1 , 3 , 4 , 5 , 6 ] ; let text = document . getText ( ) ; let sandboxScope = { result : [ ] , conflictMatcher , text : text } ; const context = vm . createContext ( sandboxScope ) ; const script = new vm . Script ( `
            let match;
            while (match = conflictMatcher.exec(text)) {
                // Ensure we don't get stuck in an infinite loop
                if (match.index === conflictMatcher.lastIndex) {
                    conflictMatcher.lastIndex++;
                }

                result.push(match);
            }` ) ; try { script . runInContext ( context , { timeout : 1000 } ) ; } catch ( ex ) { return [ ] ; } return sandboxScope . result . map ( match => new DocumentMergeConflict ( document , MergeConflictParser . matchesToDescriptor ( document , match , offsetGroups ) ) ) ; } static containsConflict ( document ) { if ( ! document ) { return false ; } let text = document . getText ( ) ; return text . includes ( '<<<<<<<' ) && text . includes ( '>>>>>>>' ) ; } static matchesToDescriptor ( document , match , offsets ? ) { var item = { range : new vscode . Range ( document . positionAt ( match . index ) , document . positionAt ( match . index + match [ 0 ] . length ) ) , current : { name : match [ 2 ] , header : this . getMatchPositions ( document , match , 1 , offsets ) , content : this . getMatchPositions ( document , match , 3 , offsets ) , } , splitter : this . getMatchPositions ( document , match , 4 , offsets ) , incoming : { name : match [ 9 ] , header : this . getMatchPositions ( document , match , 6 , offsets ) , content : this . getMatchPositions ( document , match , 5 , offsets ) , } } ; return item ; } static getMatchPositions ( document , match , groupIndex , offsetGroups ? ) { if ( ! offsetGroups ) { offsetGroups = match . map ( ( i , idx ) => idx ) ; } let start = match . index ; for ( var i = 0 ; i < offsetGroups . length ; i ++ ) { let value = offsetGroups [ i ] ; if ( value >= groupIndex ) { break ; } start += match [ value ] !== undefined ? match [ value ] . length : 0 ; } const groupMatch = match [ groupIndex ] ; let targetMatchLength = groupMatch !== undefined ? groupMatch . length : - 1 ; let end = ( start + targetMatchLength ) ; if ( groupMatch !== undefined ) { if ( match [ groupIndex ] . lastIndexOf ( '\n' ) === targetMatchLength - 1 ) { end -- ; if ( match [ groupIndex ] . lastIndexOf ( '\r' ) === targetMatchLength - 2 ) { end -- ; } } } return new vscode . Range ( document . positionAt ( start ) , document . positionAt ( end ) ) ; } }