1/* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31/** 32 * @constructor 33 * @param {number} startLine 34 * @param {number} startColumn 35 * @param {number} endLine 36 * @param {number} endColumn 37 */ 38WebInspector.TextRange = function(startLine, startColumn, endLine, endColumn) 39{ 40 this.startLine = startLine; 41 this.startColumn = startColumn; 42 this.endLine = endLine; 43 this.endColumn = endColumn; 44} 45 46/** 47 * @param {number} line 48 * @param {number} column 49 * @return {!WebInspector.TextRange} 50 */ 51WebInspector.TextRange.createFromLocation = function(line, column) 52{ 53 return new WebInspector.TextRange(line, column, line, column); 54} 55 56/** 57 * @param {!Object} serializedTextRange 58 * @return {!WebInspector.TextRange} 59 */ 60WebInspector.TextRange.fromObject = function(serializedTextRange) 61{ 62 return new WebInspector.TextRange(serializedTextRange.startLine, serializedTextRange.startColumn, serializedTextRange.endLine, serializedTextRange.endColumn); 63} 64 65/** 66 * @param {!WebInspector.TextRange} range1 67 * @param {!WebInspector.TextRange} range2 68 * @return {number} 69 */ 70WebInspector.TextRange.comparator = function(range1, range2) 71{ 72 return range1.compareTo(range2); 73} 74 75WebInspector.TextRange.prototype = { 76 /** 77 * @return {boolean} 78 */ 79 isEmpty: function() 80 { 81 return this.startLine === this.endLine && this.startColumn === this.endColumn; 82 }, 83 84 /** 85 * @param {!WebInspector.TextRange} range 86 * @return {boolean} 87 */ 88 immediatelyPrecedes: function(range) 89 { 90 if (!range) 91 return false; 92 return this.endLine === range.startLine && this.endColumn === range.startColumn; 93 }, 94 95 /** 96 * @param {!WebInspector.TextRange} range 97 * @return {boolean} 98 */ 99 immediatelyFollows: function(range) 100 { 101 if (!range) 102 return false; 103 return range.immediatelyPrecedes(this); 104 }, 105 106 /** 107 * @param {!WebInspector.TextRange} range 108 * @return {boolean} 109 */ 110 follows: function(range) 111 { 112 return (range.endLine === this.startLine && range.endColumn <= this.startColumn) 113 || range.endLine < this.startLine; 114 }, 115 116 /** 117 * @return {number} 118 */ 119 get linesCount() 120 { 121 return this.endLine - this.startLine; 122 }, 123 124 /** 125 * @return {!WebInspector.TextRange} 126 */ 127 collapseToEnd: function() 128 { 129 return new WebInspector.TextRange(this.endLine, this.endColumn, this.endLine, this.endColumn); 130 }, 131 132 /** 133 * @return {!WebInspector.TextRange} 134 */ 135 collapseToStart: function() 136 { 137 return new WebInspector.TextRange(this.startLine, this.startColumn, this.startLine, this.startColumn); 138 }, 139 140 /** 141 * @return {!WebInspector.TextRange} 142 */ 143 normalize: function() 144 { 145 if (this.startLine > this.endLine || (this.startLine === this.endLine && this.startColumn > this.endColumn)) 146 return new WebInspector.TextRange(this.endLine, this.endColumn, this.startLine, this.startColumn); 147 else 148 return this.clone(); 149 }, 150 151 /** 152 * @return {!WebInspector.TextRange} 153 */ 154 clone: function() 155 { 156 return new WebInspector.TextRange(this.startLine, this.startColumn, this.endLine, this.endColumn); 157 }, 158 159 /** 160 * @return {!Object} 161 */ 162 serializeToObject: function() 163 { 164 var serializedTextRange = {}; 165 serializedTextRange.startLine = this.startLine; 166 serializedTextRange.startColumn = this.startColumn; 167 serializedTextRange.endLine = this.endLine; 168 serializedTextRange.endColumn = this.endColumn; 169 return serializedTextRange; 170 }, 171 172 /** 173 * @param {!WebInspector.TextRange} other 174 * @return {number} 175 */ 176 compareTo: function(other) 177 { 178 if (this.startLine > other.startLine) 179 return 1; 180 if (this.startLine < other.startLine) 181 return -1; 182 if (this.startColumn > other.startColumn) 183 return 1; 184 if (this.startColumn < other.startColumn) 185 return -1; 186 return 0; 187 }, 188 189 /** 190 * @param {!WebInspector.TextRange} other 191 * @return {boolean} 192 */ 193 equal: function(other) 194 { 195 return this.startLine === other.startLine && this.endLine === other.endLine && 196 this.startColumn === other.startColumn && this.endColumn === other.endColumn; 197 }, 198 199 /** 200 * @param {number} lineOffset 201 * @return {!WebInspector.TextRange} 202 */ 203 shift: function(lineOffset) 204 { 205 return new WebInspector.TextRange(this.startLine + lineOffset, this.startColumn, this.endLine + lineOffset, this.endColumn); 206 }, 207 208 /** 209 * @param {!WebInspector.TextRange} originalRange 210 * @param {!WebInspector.TextRange} editedRange 211 * @return {!WebInspector.TextRange} 212 */ 213 rebaseAfterTextEdit: function(originalRange, editedRange) 214 { 215 console.assert(originalRange.startLine === editedRange.startLine); 216 console.assert(originalRange.startColumn === editedRange.startColumn); 217 var rebase = this.clone(); 218 if (!this.follows(originalRange)) 219 return rebase; 220 var lineDelta = editedRange.endLine - originalRange.endLine; 221 var columnDelta = editedRange.endColumn - originalRange.endColumn; 222 rebase.startLine += lineDelta; 223 rebase.endLine += lineDelta; 224 if (rebase.startLine === editedRange.endLine) 225 rebase.startColumn += columnDelta; 226 if (rebase.endLine === editedRange.endLine) 227 rebase.endColumn += columnDelta; 228 return rebase; 229 }, 230 231 /** 232 * @return {string} 233 */ 234 toString: function() 235 { 236 return JSON.stringify(this); 237 } 238} 239 240/** 241 * @constructor 242 * @param {number} offset 243 * @param {number} length 244 */ 245WebInspector.SourceRange = function(offset, length) 246{ 247 this.offset = offset; 248 this.length = length; 249} 250