diff --git a/lib/project/results-model.js b/lib/project/results-model.js index 171393fe..038e571a 100644 --- a/lib/project/results-model.js +++ b/lib/project/results-model.js @@ -5,16 +5,57 @@ const escapeHelper = require('../escape-helper') class Result { static create (result) { if (result && result.matches && result.matches.length) { - const matches = result.matches.map(m => - ({ - matchText: m.matchText, - lineText: m.lineText, - lineTextOffset: m.lineTextOffset, - range: Range.fromObject(m.range), - leadingContextLines: m.leadingContextLines, - trailingContextLines: m.trailingContextLines - }) - ) + const matches = [] + + for (const m of result.matches) { + const range = Range.fromObject(m.range) + const matchSplit = m.matchText.split('\n') + const linesSplit = m.lineText.split('\n') + + // If the result spans across multiple lines, process each of + // them separately by creating separate `matches` objects for + // each line on the match. + for (let row = range.start.row; row <= range.end.row; row++) { + const lineText = linesSplit[row - range.start.row] + const matchText = matchSplit[row - range.start.row] + + // When receiving multiline results from opened buffers, only + // the first result line is provided on the `lineText` property. + // This makes it impossible to properly render the part of the result + // that's part of other lines. + // In order to prevent an error we just need to ignore these parts. + if (lineText === undefined || matchText === undefined) { + continue + } + + // Adapt the range column number based on which line we're at: + // - the first line of a multiline result will always start at the range start + // and will end at the end of the line. + // - middle lines will start at 0 and end at the end of the line + // - last line will start at 0 and end at the range end. + const startColumn = row === range.start.row ? range.start.column : 0 + const endColumn = row === range.end.row ? range.end.column : lineText.length - 1 + + matches.push({ + matchText, + lineText, + lineTextOffset: m.lineTextOffset, + range: { + start: { + row, + column: startColumn + }, + end: { + row, + column: endColumn + } + }, + leadingContextLines: m.leadingContextLines, + trailingContextLines: m.trailingContextLines + }) + } + } + return new Result({filePath: result.filePath, matches}) } else { return null