Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 1 | // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | /** |
| 6 | * @param {!Object} config |
| 7 | * @param {{diffRows: !Array<!Changes.ChangesView.Row>, baselineLines: !Array<string>, currentLines: !Array<string>, mimeType: string}} parserConfig |
| 8 | * @return {{ |
| 9 | * startState: function():!Changes.ChangesHighlighter.DiffState, |
| 10 | * token: function(!CodeMirror.StringStream, !Changes.ChangesHighlighter.DiffState):string, |
| 11 | * blankLine: function(!Changes.ChangesHighlighter.DiffState):string, |
| 12 | * copyState: function(!Changes.ChangesHighlighter.DiffState):Changes.ChangesHighlighter.DiffState |
| 13 | * }} |
| 14 | */ |
| 15 | Changes.ChangesHighlighter = function(config, parserConfig) { |
| 16 | const diffRows = parserConfig.diffRows; |
| 17 | const baselineLines = parserConfig.baselineLines; |
| 18 | const currentLines = parserConfig.currentLines; |
| 19 | const syntaxHighlightMode = CodeMirror.getMode({}, parserConfig.mimeType); |
| 20 | |
| 21 | /** |
| 22 | * @param {!Changes.ChangesHighlighter.DiffState} state |
| 23 | * @param {number} baselineLineNumber |
| 24 | * @param {number} currentLineNumber |
| 25 | */ |
| 26 | function fastForward(state, baselineLineNumber, currentLineNumber) { |
| 27 | if (baselineLineNumber > state.baselineLineNumber) { |
| 28 | fastForwardSyntaxHighlighter(state.baselineSyntaxState, state.baselineLineNumber, baselineLineNumber, baselineLines); |
| 29 | state.baselineLineNumber = baselineLineNumber; |
| 30 | } |
| 31 | if (currentLineNumber > state.currentLineNumber) { |
| 32 | fastForwardSyntaxHighlighter(state.currentSyntaxState, state.currentLineNumber, currentLineNumber, currentLines); |
| 33 | state.currentLineNumber = currentLineNumber; |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | /** |
| 38 | * @param {!Object} syntaxState |
| 39 | * @param {number} from |
| 40 | * @param {number} to |
| 41 | * @param {!Array<string>} lines |
| 42 | */ |
| 43 | function fastForwardSyntaxHighlighter(syntaxState, from, to, lines) { |
| 44 | let lineNumber = from; |
| 45 | while (lineNumber < to && lineNumber < lines.length) { |
| 46 | const stream = new CodeMirror.StringStream(lines[lineNumber]); |
| 47 | if (stream.eol() && syntaxHighlightMode.blankLine) |
| 48 | syntaxHighlightMode.blankLine(syntaxState); |
| 49 | while (!stream.eol()) { |
| 50 | syntaxHighlightMode.token(stream, syntaxState); |
| 51 | stream.start = stream.pos; |
| 52 | } |
| 53 | lineNumber++; |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | return { |
| 58 | /** |
| 59 | * @return {!Changes.ChangesHighlighter.DiffState} |
| 60 | */ |
| 61 | startState: function() { |
| 62 | return { |
| 63 | rowNumber: 0, |
| 64 | diffTokenIndex: 0, |
| 65 | currentLineNumber: 0, |
| 66 | baselineLineNumber: 0, |
| 67 | currentSyntaxState: CodeMirror.startState(syntaxHighlightMode), |
| 68 | baselineSyntaxState: CodeMirror.startState(syntaxHighlightMode), |
| 69 | syntaxPosition: 0, |
| 70 | diffPosition: 0, |
| 71 | syntaxStyle: '', |
| 72 | diffStyle: '' |
| 73 | }; |
| 74 | }, |
| 75 | |
| 76 | /** |
| 77 | * @param {!CodeMirror.StringStream} stream |
| 78 | * @param {!Changes.ChangesHighlighter.DiffState} state |
| 79 | * @return {string} |
| 80 | */ |
| 81 | token: function(stream, state) { |
| 82 | const diffRow = diffRows[state.rowNumber]; |
| 83 | if (!diffRow) { |
| 84 | stream.next(); |
| 85 | return ''; |
| 86 | } |
| 87 | fastForward(state, diffRow.baselineLineNumber - 1, diffRow.currentLineNumber - 1); |
| 88 | let classes = ''; |
| 89 | if (stream.pos === 0) |
| 90 | classes += ' line-background-' + diffRow.type + ' line-' + diffRow.type; |
| 91 | |
| 92 | const syntaxHighlighterNeedsRefresh = state.diffPosition >= state.syntaxPosition; |
| 93 | if (state.diffPosition <= state.syntaxPosition) { |
| 94 | state.diffPosition += diffRow.tokens[state.diffTokenIndex].text.length; |
| 95 | state.diffStyle = diffRow.tokens[state.diffTokenIndex].className; |
| 96 | state.diffTokenIndex++; |
| 97 | } |
| 98 | |
| 99 | if (syntaxHighlighterNeedsRefresh) { |
| 100 | if (diffRow.type === Changes.ChangesView.RowType.Deletion || diffRow.type === Changes.ChangesView.RowType.Addition || |
| 101 | diffRow.type === Changes.ChangesView.RowType.Equal) { |
| 102 | state.syntaxStyle = syntaxHighlightMode.token( |
| 103 | stream, diffRow.type === Changes.ChangesView.RowType.Deletion ? state.baselineSyntaxState : state.currentSyntaxState); |
| 104 | state.syntaxPosition = stream.pos; |
| 105 | } else { |
| 106 | state.syntaxStyle = ''; |
| 107 | state.syntaxPosition = Infinity; |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | stream.pos = Math.min(state.syntaxPosition, state.diffPosition); |
| 112 | classes += ' ' + state.syntaxStyle; |
| 113 | classes += ' ' + state.diffStyle; |
| 114 | |
| 115 | if (stream.eol()) { |
| 116 | state.rowNumber++; |
| 117 | if (diffRow.type === Changes.ChangesView.RowType.Deletion) |
| 118 | state.baselineLineNumber++; |
| 119 | else |
| 120 | state.currentLineNumber++; |
| 121 | state.diffPosition = 0; |
| 122 | state.syntaxPosition = 0; |
| 123 | state.diffTokenIndex = 0; |
| 124 | } |
| 125 | return classes; |
| 126 | }, |
| 127 | |
| 128 | /** |
| 129 | * @param {!Changes.ChangesHighlighter.DiffState} state |
| 130 | * @return {string} |
| 131 | */ |
| 132 | blankLine: function(state) { |
| 133 | const diffRow = diffRows[state.rowNumber]; |
| 134 | state.rowNumber++; |
| 135 | state.syntaxPosition = 0; |
| 136 | state.diffPosition = 0; |
| 137 | state.diffTokenIndex = 0; |
| 138 | if (!diffRow) |
| 139 | return ''; |
| 140 | |
| 141 | let style = ''; |
| 142 | if (syntaxHighlightMode.blankLine) { |
| 143 | if (diffRow.type === Changes.ChangesView.RowType.Equal || diffRow.type === Changes.ChangesView.RowType.Addition) { |
| 144 | style = syntaxHighlightMode.blankLine(state.currentSyntaxState); |
| 145 | state.currentLineNumber++; |
| 146 | } else if (diffRow.type === Changes.ChangesView.RowType.Deletion) { |
| 147 | style = syntaxHighlightMode.blankLine(state.baselineSyntaxState); |
| 148 | state.baselineLineNumber++; |
| 149 | } |
| 150 | } |
| 151 | return style + ' line-background-' + diffRow.type + ' line-' + diffRow.type; |
| 152 | }, |
| 153 | |
| 154 | /** |
| 155 | * @param {!Changes.ChangesHighlighter.DiffState} state |
| 156 | * @return {!Changes.ChangesHighlighter.DiffState} |
| 157 | */ |
| 158 | copyState: function(state) { |
| 159 | const newState = Object.assign({}, state); |
| 160 | newState.currentSyntaxState = CodeMirror.copyState(syntaxHighlightMode, state.currentSyntaxState); |
| 161 | newState.baselineSyntaxState = CodeMirror.copyState(syntaxHighlightMode, state.baselineSyntaxState); |
| 162 | return /** @type {!Changes.ChangesHighlighter.DiffState} */ (newState); |
| 163 | } |
| 164 | }; |
| 165 | }; |
| 166 | |
| 167 | /** |
| 168 | * @typedef {!{ |
| 169 | * rowNumber: number, |
| 170 | * diffTokenIndex: number, |
| 171 | * currentLineNumber: number, |
| 172 | * baselineLineNumber: number, |
| 173 | * currentSyntaxState: !Object, |
| 174 | * baselineSyntaxState: !Object, |
| 175 | * syntaxPosition: number, |
| 176 | * diffPosition: number, |
| 177 | * syntaxStyle: string, |
| 178 | * diffStyle: string |
| 179 | * }} |
| 180 | */ |
| 181 | Changes.ChangesHighlighter.DiffState; |
| 182 | |
| 183 | CodeMirror.defineMode('devtools-diff', Changes.ChangesHighlighter); |