| OLD | NEW | 
|    1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file |    1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
|    2 // for details. All rights reserved. Use of this source code is governed by a |    2 // for details. All rights reserved. Use of this source code is governed by a | 
|    3 // BSD-style license that can be found in the LICENSE file. |    3 // BSD-style license that can be found in the LICENSE file. | 
|    4  |    4  | 
|    5 // TODO(jimhug): This should be an interface to work better with tools. |    5 #library('source_file'); | 
 |    6  | 
 |    7 #import('../../frog/leg/colors.dart'); | 
 |    8  | 
|    6 /** |    9 /** | 
|    7  * Represents a file of source code. |   10  * Represents a file of source code. | 
|    8  */ |   11  */ | 
|    9 class SourceFile implements Comparable { |   12 class SourceFile { | 
|   10   // TODO(terry): This filename for in memory buffer.  May need to rework if |  | 
|   11   //              filename is used for more than informational. |  | 
|   12   static String IN_MEMORY_FILE = '<buffer>'; |  | 
|   13  |   13  | 
|   14   /** The name of the file. */ |   14   /** The name of the file. */ | 
|   15   final String filename; |   15   final String filename; | 
|   16  |   16  | 
|   17   /** The text content of the file. */ |   17   /** The text content of the file. */ | 
|   18   String _text; |   18   final String text; | 
|   19  |  | 
|   20   /** |  | 
|   21    * The order of the source file in a given library. This is used while we're |  | 
|   22    * writing code for a library. A single source file can be used |  | 
|   23    */ |  | 
|   24   // TODO(jmesserly): I don't like having properties that are only valid |  | 
|   25   // sometimes. An alternative would be to store it in a Map that's used by |  | 
|   26   // WorldGenerator while it's emitting code. This seems simpler. |  | 
|   27   int orderInLibrary; |  | 
|   28  |   19  | 
|   29   List<int> _lineStarts; |   20   List<int> _lineStarts; | 
|   30  |   21  | 
|   31   SourceFile(this.filename, this._text); |   22   SourceFile(this.filename, this.text); | 
|   32  |  | 
|   33   String get text() => _text; |  | 
|   34  |  | 
|   35   set text(String newText) { |  | 
|   36     if (newText != _text) { |  | 
|   37       _text = newText; |  | 
|   38       _lineStarts = null; |  | 
|   39       orderInLibrary = null; |  | 
|   40     } |  | 
|   41   } |  | 
|   42  |   23  | 
|   43   List<int> get lineStarts() { |   24   List<int> get lineStarts() { | 
|   44     if (_lineStarts == null) { |   25     if (_lineStarts == null) { | 
|   45       var starts = [0]; |   26       var starts = [0]; | 
|   46       var index = 0; |   27       var index = 0; | 
|   47       while (index < text.length) { |   28       while (index < text.length) { | 
|   48         index = text.indexOf('\n', index) + 1; |   29         index = text.indexOf('\n', index) + 1; | 
|   49         if (index <= 0) break; |   30         if (index <= 0) break; | 
|   50         starts.add(index); |   31         starts.add(index); | 
|   51       } |   32       } | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
|   66  |   47  | 
|   67   int getColumn(int line, int position) { |   48   int getColumn(int line, int position) { | 
|   68     return position - lineStarts[line]; |   49     return position - lineStarts[line]; | 
|   69   } |   50   } | 
|   70  |   51  | 
|   71   /** |   52   /** | 
|   72    * Create a pretty string representation from a character position |   53    * Create a pretty string representation from a character position | 
|   73    * in the file. |   54    * in the file. | 
|   74    */ |   55    */ | 
|   75   String getLocationMessage(String message, int start, |   56   String getLocationMessage(String message, int start, | 
|   76       [int end, bool includeText=false]) { |   57       [int end, bool includeText=false, bool useColors = true]) { | 
|   77     var line = getLine(start); |   58     var line = getLine(start); | 
|   78     var column = getColumn(line, start); |   59     var column = getColumn(line, start); | 
|   79  |   60  | 
|   80     var buf = new StringBuffer( |   61     var buf = new StringBuffer( | 
|   81         '${filename}:${line + 1}:${column + 1}: $message'); |   62         '${filename}:${line + 1}:${column + 1}: $message'); | 
|   82     if (includeText) { |   63     if (includeText) { | 
|   83       buf.add('\n'); |   64       buf.add('\n'); | 
|   84       var textLine; |   65       var textLine; | 
|   85       // +1 for 0-indexing, +1 again to avoid the last line of the file |   66       // +1 for 0-indexing, +1 again to avoid the last line of the file | 
|   86       if ((line + 2) < _lineStarts.length) { |   67       if ((line + 2) < _lineStarts.length) { | 
|   87         textLine = text.substring(_lineStarts[line], _lineStarts[line+1]); |   68         textLine = text.substring(_lineStarts[line], _lineStarts[line+1]); | 
|   88       } else { |   69       } else { | 
|   89         textLine = text.substring(_lineStarts[line]) + '\n'; |   70         textLine = text.substring(_lineStarts[line]) + '\n'; | 
|   90       } |   71       } | 
|   91  |   72  | 
|   92       int toColumn = Math.min(column + (end-start), textLine.length); |   73       int toColumn = Math.min(column + (end-start), textLine.length); | 
|   93       if (options.useColors) { |   74       if (useColors) { | 
|   94         buf.add(textLine.substring(0, column)); |   75         buf.add(textLine.substring(0, column)); | 
|   95         buf.add(_RED_COLOR); |   76         buf.add(RED_COLOR); | 
|   96         buf.add(textLine.substring(column, toColumn)); |   77         buf.add(textLine.substring(column, toColumn)); | 
|   97         buf.add(_NO_COLOR); |   78         buf.add(NO_COLOR); | 
|   98         buf.add(textLine.substring(toColumn)); |   79         buf.add(textLine.substring(toColumn)); | 
|   99       } else { |   80       } else { | 
|  100         buf.add(textLine); |   81         buf.add(textLine); | 
|  101       } |   82       } | 
|  102  |   83  | 
|  103       int i = 0; |   84       int i = 0; | 
|  104       for (; i < column; i++) { |   85       for (; i < column; i++) { | 
|  105         buf.add(' '); |   86         buf.add(' '); | 
|  106       } |   87       } | 
|  107  |   88  | 
|  108       if (options.useColors) buf.add(_RED_COLOR); |   89       if (useColors) buf.add(RED_COLOR); | 
|  109       for (; i < toColumn; i++) { |   90       for (; i < toColumn; i++) { | 
|  110         buf.add('^'); |   91         buf.add('^'); | 
|  111       } |   92       } | 
|  112       if (options.useColors) buf.add(_NO_COLOR); |   93       if (useColors) buf.add(NO_COLOR); | 
|  113     } |   94     } | 
|  114  |   95  | 
|  115     return buf.toString(); |   96     return buf.toString(); | 
|  116   } |   97   } | 
|  117  |  | 
|  118   /** Compares two source files. */ |  | 
|  119   int compareTo(SourceFile other) { |  | 
|  120     if (orderInLibrary != null && other.orderInLibrary != null) { |  | 
|  121       return orderInLibrary - other.orderInLibrary; |  | 
|  122     } else { |  | 
|  123       return filename.compareTo(other.filename); |  | 
|  124     } |  | 
|  125   } |  | 
|  126 } |   98 } | 
|  127  |  | 
|  128  |  | 
|  129 /** |  | 
|  130  * A range of characters in a [SourceFile].  Used to represent the source |  | 
|  131  * positions of [Token]s and [Node]s for error reporting or other tooling |  | 
|  132  * work. |  | 
|  133  */ |  | 
|  134  // TODO(jmesserly): Rename to Span - but first write cool refactoring tool |  | 
|  135 class SourceSpan implements Comparable { |  | 
|  136   /** The [SourceFile] that contains this span. */ |  | 
|  137   final SourceFile file; |  | 
|  138  |  | 
|  139   /** The character position of the start of this span. */ |  | 
|  140   final int start; |  | 
|  141  |  | 
|  142   /** The character position of the end of this span. */ |  | 
|  143   final int end; |  | 
|  144  |  | 
|  145   SourceSpan(this.file, this.start, this.end); |  | 
|  146  |  | 
|  147   /** Returns the source text corresponding to this [Span]. */ |  | 
|  148   String get text() { |  | 
|  149     return file.text.substring(start, end); |  | 
|  150   } |  | 
|  151  |  | 
|  152   toMessageString(String message) { |  | 
|  153     return file.getLocationMessage(message, start, end: end, includeText: true); |  | 
|  154   } |  | 
|  155  |  | 
|  156   int get line() { |  | 
|  157     return file.getLine(start); |  | 
|  158   } |  | 
|  159  |  | 
|  160   int get column() { |  | 
|  161     return file.getColumn(line, start); |  | 
|  162   } |  | 
|  163  |  | 
|  164   int get endLine() { |  | 
|  165     return file.getLine(end); |  | 
|  166   } |  | 
|  167  |  | 
|  168   int get endColumn() { |  | 
|  169     return file.getColumn(endLine, end); |  | 
|  170   } |  | 
|  171  |  | 
|  172   String get locationText() { |  | 
|  173     var line = file.getLine(start); |  | 
|  174     var column = file.getColumn(line, start); |  | 
|  175     return '${file.filename}:${line + 1}:${column + 1}'; |  | 
|  176   } |  | 
|  177  |  | 
|  178   /** Compares two source spans by file and position. Handles nulls. */ |  | 
|  179   int compareTo(SourceSpan other) { |  | 
|  180     if (file == other.file) { |  | 
|  181       int d = start - other.start; |  | 
|  182       return d == 0 ? (end - other.end) : d; |  | 
|  183     } |  | 
|  184     return file.compareTo(other.file); |  | 
|  185   } |  | 
|  186 } |  | 
| OLD | NEW |