Home | History | Annotate | Download | only in common
      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  */
     38 WebInspector.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  */
     51 WebInspector.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  */
     60 WebInspector.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  */
     70 WebInspector.TextRange.comparator = function(range1, range2)
     71 {
     72     return range1.compareTo(range2);
     73 }
     74 
     75 WebInspector.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  */
    245 WebInspector.SourceRange = function(offset, length)
    246 {
    247     this.offset = offset;
    248     this.length = length;
    249 }
    250