Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: pkg/kernel/lib/ast.dart

Issue 2788373002: Add Source.getTextLine and use it to display source snippets in error messages. (Closed)
Patch Set: dartfmt Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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 /// ----------------------------------------------------------------------- 5 /// -----------------------------------------------------------------------
6 /// ERROR HANDLING 6 /// ERROR HANDLING
7 /// ----------------------------------------------------------------------- 7 /// -----------------------------------------------------------------------
8 /// 8 ///
9 /// As a rule of thumb, errors that can be detected statically are handled by 9 /// As a rule of thumb, errors that can be detected statically are handled by
10 /// the frontend, typically by translating the erroneous code into a 'throw' or 10 /// the frontend, typically by translating the erroneous code into a 'throw' or
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 /// 43 ///
44 /// Use [Transformer] for bulk transformations that are likely to transform lots 44 /// Use [Transformer] for bulk transformations that are likely to transform lots
45 /// of nodes, and [TreeNode.replaceWith] for sparse transformations that mutate 45 /// of nodes, and [TreeNode.replaceWith] for sparse transformations that mutate
46 /// relatively few nodes. Or use whichever is more convenient. 46 /// relatively few nodes. Or use whichever is more convenient.
47 /// 47 ///
48 /// The AST can also be mutated by direct field manipulation, but the user then 48 /// The AST can also be mutated by direct field manipulation, but the user then
49 /// has to update parent pointers manually. 49 /// has to update parent pointers manually.
50 /// 50 ///
51 library kernel.ast; 51 library kernel.ast;
52 52
53 import 'dart:convert' show UTF8;
54
53 import 'visitor.dart'; 55 import 'visitor.dart';
54 export 'visitor.dart'; 56 export 'visitor.dart';
55 57
56 import 'canonical_name.dart' show CanonicalName; 58 import 'canonical_name.dart' show CanonicalName;
57 export 'canonical_name.dart' show CanonicalName; 59 export 'canonical_name.dart' show CanonicalName;
58 60
59 import 'transformations/flags.dart'; 61 import 'transformations/flags.dart';
60 import 'text/ast_to_text.dart'; 62 import 'text/ast_to_text.dart';
61 import 'type_algebra.dart'; 63 import 'type_algebra.dart';
62 import 'type_environment.dart'; 64 import 'type_environment.dart';
(...skipping 4037 matching lines...) Expand 10 before | Expand all | Expand 10 after
4100 } 4102 }
4101 4103
4102 transformChildren(Transformer v) { 4104 transformChildren(Transformer v) {
4103 transformList(libraries, v, this); 4105 transformList(libraries, v, this);
4104 } 4106 }
4105 4107
4106 Program get enclosingProgram => this; 4108 Program get enclosingProgram => this;
4107 4109
4108 /// Translates an offset to line and column numbers in the given file. 4110 /// Translates an offset to line and column numbers in the given file.
4109 Location getLocation(String file, int offset) { 4111 Location getLocation(String file, int offset) {
4110 List<int> lines = uriToSource[file].lineStarts; 4112 return uriToSource[file]?.getLocation(file, offset);
4111 int low = 0, high = lines.length - 1;
4112 while (low < high) {
4113 int mid = high - ((high - low) >> 1); // Get middle, rounding up.
4114 int pivot = lines[mid];
4115 if (pivot <= offset) {
4116 low = mid;
4117 } else {
4118 high = mid - 1;
4119 }
4120 }
4121 int lineIndex = low;
4122 int lineStart = lines[lineIndex];
4123 int lineNumber = 1 + lineIndex;
4124 int columnNumber = 1 + offset - lineStart;
4125 return new Location(file, lineNumber, columnNumber);
4126 } 4113 }
4127 } 4114 }
4128 4115
4129 /// A tuple with file, line, and column number, for displaying human-readable 4116 /// A tuple with file, line, and column number, for displaying human-readable
4130 /// locations. 4117 /// locations.
4131 class Location { 4118 class Location {
4132 final String file; 4119 final String file;
4133 final int line; // 1-based. 4120 final int line; // 1-based.
4134 final int column; // 1-based. 4121 final int column; // 1-based.
4135 4122
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
4221 if (node == child) { 4208 if (node == child) {
4222 return replacement; 4209 return replacement;
4223 } else { 4210 } else {
4224 return node; 4211 return node;
4225 } 4212 }
4226 } 4213 }
4227 } 4214 }
4228 4215
4229 class Source { 4216 class Source {
4230 final List<int> lineStarts; 4217 final List<int> lineStarts;
4218
4231 final List<int> source; 4219 final List<int> source;
4232 4220
4221 String cachedText;
4222
4233 Source(this.lineStarts, this.source); 4223 Source(this.lineStarts, this.source);
4224
4225 /// Return the text corresponding to [line] which is a 1-based line
4226 /// number. The returned line contains no line separators.
4227 String getTextLine(int line) {
4228 _rangeCheck(line, 1, lineStarts.length, "line");
4229 if (source == null) return null;
4230
4231 cachedText ??= UTF8.decode(source, allowMalformed: true);
4232 // -1 as line numbers start at 1.
4233 int index = line - 1;
4234 if (index + 1 == lineStarts.length) {
4235 // Last line.
4236 return cachedText.substring(lineStarts[index]);
4237 } else if (index < lineStarts.length) {
4238 // We subtract 1 from the next line for two reasons:
4239 // 1. If the file isn't terminated by a newline, that index is invalid.
4240 // 2. To remove the newline at the end of the line.
4241 int endOfLine = lineStarts[index + 1] - 1;
4242 if (endOfLine > index && cachedText[endOfLine - 1] == "\r") {
4243 --endOfLine; // Windows line endings.
4244 }
4245 return cachedText.substring(lineStarts[index], endOfLine);
4246 }
4247 // This shouldn't happen: should have been caught by the range check above.
4248 throw "Internal error";
4249 }
4250
4251 /// Translates an offset to line and column numbers in the given file.
4252 Location getLocation(String file, int offset) {
4253 _rangeCheck(offset, 0, lineStarts.last, "offset");
4254 int low = 0, high = lineStarts.length - 1;
4255 while (low < high) {
4256 int mid = high - ((high - low) >> 1); // Get middle, rounding up.
4257 int pivot = lineStarts[mid];
4258 if (pivot <= offset) {
4259 low = mid;
4260 } else {
4261 high = mid - 1;
4262 }
4263 }
4264 int lineIndex = low;
4265 int lineStart = lineStarts[lineIndex];
4266 int lineNumber = 1 + lineIndex;
4267 int columnNumber = 1 + offset - lineStart;
4268 return new Location(file, lineNumber, columnNumber);
4269 }
4270 }
4271
4272 void _rangeCheck(int value, int min, int max, String name) {
4273 RangeError.checkValueInInterval(value, min, max, name,
4274 "The value of '$name' ($value) must be between $min and $max.");
sra1 2017/05/04 05:44:39 Please remove this interpolation. It is expensive
4234 } 4275 }
4235 4276
4236 /// Returns the [Reference] object for the given member. 4277 /// Returns the [Reference] object for the given member.
4237 /// 4278 ///
4238 /// Returns `null` if the member is `null`. 4279 /// Returns `null` if the member is `null`.
4239 Reference getMemberReference(Member member) { 4280 Reference getMemberReference(Member member) {
4240 return member?.reference; 4281 return member?.reference;
4241 } 4282 }
4242 4283
4243 /// Returns the [Reference] object for the given class. 4284 /// Returns the [Reference] object for the given class.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4275 /// library has not been assigned a canonical name yet. 4316 /// library has not been assigned a canonical name yet.
4276 /// 4317 ///
4277 /// Returns `null` if the library is `null`. 4318 /// Returns `null` if the library is `null`.
4278 CanonicalName getCanonicalNameOfLibrary(Library library) { 4319 CanonicalName getCanonicalNameOfLibrary(Library library) {
4279 if (library == null) return null; 4320 if (library == null) return null;
4280 if (library.canonicalName == null) { 4321 if (library.canonicalName == null) {
4281 throw '$library has no canonical name'; 4322 throw '$library has no canonical name';
4282 } 4323 }
4283 return library.canonicalName; 4324 return library.canonicalName;
4284 } 4325 }
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/messages.dart ('k') | tests/compiler/dart2js/line_column_provider_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698