OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 import 'dart:io'; | 5 import 'dart:io'; |
6 import 'dart:convert'; | 6 import 'dart:convert'; |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'package:path/path.dart' as path; | 9 import 'package:path/path.dart' as path; |
10 import 'package:expect/expect.dart'; | 10 import 'package:expect/expect.dart'; |
11 import 'package:source_maps/source_maps.dart' hide SourceFile; | 11 import 'package:source_maps/source_maps.dart' hide SourceFile; |
12 import 'package:compiler/src/apiimpl.dart'; | 12 import 'package:compiler/src/apiimpl.dart'; |
13 import 'package:compiler/src/elements/elements.dart' | 13 import 'package:compiler/src/elements/elements.dart' |
14 show LibraryElement, | 14 show AstElement, |
| 15 ClassElement, |
15 CompilationUnitElement, | 16 CompilationUnitElement, |
16 ClassElement, | 17 Element, |
17 AstElement; | 18 FunctionElement, |
| 19 LibraryElement, |
| 20 MemberElement; |
18 import 'package:compiler/src/io/source_file.dart' show SourceFile; | 21 import 'package:compiler/src/io/source_file.dart' show SourceFile; |
| 22 import 'package:compiler/src/io/source_information.dart' |
| 23 show computeElementNameForSourceMaps; |
19 | 24 |
20 validateSourceMap(Uri targetUri, | 25 validateSourceMap(Uri targetUri, |
21 {Uri mainUri, | 26 {Uri mainUri, |
22 Position mainPosition, | 27 Position mainPosition, |
23 Compiler compiler}) { | 28 Compiler compiler}) { |
24 Uri mapUri = getMapUri(targetUri); | 29 Uri mapUri = getMapUri(targetUri); |
25 List<String> targetLines = new File.fromUri(targetUri).readAsLinesSync(); | 30 List<String> targetLines = new File.fromUri(targetUri).readAsLinesSync(); |
26 SingleMapping sourceMap = getSourceMap(mapUri); | 31 SingleMapping sourceMap = getSourceMap(mapUri); |
27 checkFileReferences(targetUri, mapUri, sourceMap); | 32 checkFileReferences(targetUri, mapUri, sourceMap); |
28 checkIndexReferences(targetLines, mapUri, sourceMap); | 33 checkIndexReferences(targetLines, mapUri, sourceMap); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 Interval intervalFromElement(AstElement element) { | 141 Interval intervalFromElement(AstElement element) { |
137 if (!element.hasNode) return null; | 142 if (!element.hasNode) return null; |
138 | 143 |
139 var begin = element.node.getBeginToken().charOffset; | 144 var begin = element.node.getBeginToken().charOffset; |
140 var end = element.node.getEndToken(); | 145 var end = element.node.getEndToken(); |
141 end = end.charOffset + end.charCount; | 146 end = end.charOffset + end.charCount; |
142 return new Interval(positionFromOffset(begin), | 147 return new Interval(positionFromOffset(begin), |
143 positionFromOffset(end)); | 148 positionFromOffset(end)); |
144 } | 149 } |
145 | 150 |
| 151 AstElement findInnermost(AstElement element) { |
| 152 bool isInsideElement(FunctionElement closure) { |
| 153 Element enclosing = closure; |
| 154 while (enclosing != null) { |
| 155 if (enclosing == element) return true; |
| 156 enclosing = enclosing.enclosingElement; |
| 157 } |
| 158 return false; |
| 159 } |
| 160 |
| 161 if (element is MemberElement) { |
| 162 MemberElement member = element; |
| 163 member.nestedClosures.forEach((closure) { |
| 164 var localFunction = closure.expression; |
| 165 Interval interval = intervalFromElement(localFunction); |
| 166 if (interval != null && |
| 167 interval.contains(sourcePosition) && |
| 168 isInsideElement(localFunction)) { |
| 169 element = localFunction; |
| 170 } |
| 171 }); |
| 172 } |
| 173 return element; |
| 174 } |
| 175 |
146 void match(AstElement element) { | 176 void match(AstElement element) { |
147 Interval interval = intervalFromElement(element); | 177 Interval interval = intervalFromElement(element); |
148 if (interval != null && interval.contains(sourcePosition)) { | 178 if (interval != null && interval.contains(sourcePosition)) { |
149 if (name != 'call') { | 179 AstElement innerElement = findInnermost(element); |
150 // TODO(johnniwinther): Check closures. | 180 String expectedName = |
151 Expect.equals(element.name, name); | 181 computeElementNameForSourceMaps(innerElement); |
152 } else if (name != element.name) { | 182 if (name != expectedName) { |
153 print("${targetUri}$targetPosition:\n" | 183 // For the code |
154 "Name '$name' does not match element $element in " | 184 // (){}(); |
155 "${sourceFile.filename}$sourcePosition."); | 185 // ^ |
| 186 // the indicated position is within the scope of the local |
| 187 // function but it is also the position for the invocation of it. |
| 188 // Allow name to be either from the local or from its calling |
| 189 // context. |
| 190 if (innerElement.isLocal && innerElement.isFunction) { |
| 191 var enclosingElement = innerElement.enclosingElement; |
| 192 String expectedName2 = |
| 193 computeElementNameForSourceMaps(enclosingElement); |
| 194 Expect.isTrue(name == expectedName2, |
| 195 "Unexpected name '${name}', " |
| 196 "expected '${expectedName}' for $innerElement " |
| 197 "or '${expectedName2}' for $enclosingElement."); |
| 198 } else { |
| 199 Expect.equals(expectedName, name, |
| 200 "Unexpected name '${name}', " |
| 201 "expected '${expectedName}' or for $innerElement."); |
| 202 } |
156 } | 203 } |
157 } | 204 } |
158 } | 205 } |
159 | 206 |
160 compilationUnit.forEachLocalMember((AstElement element) { | 207 compilationUnit.forEachLocalMember((AstElement element) { |
161 if (element.isClass) { | 208 if (element.isClass) { |
162 ClassElement classElement = element; | 209 ClassElement classElement = element; |
163 classElement.forEachLocalMember(match); | 210 classElement.forEachLocalMember(match); |
164 } else { | 211 } else { |
165 match(element); | 212 match(element); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 final int line; | 306 final int line; |
260 final int column; | 307 final int column; |
261 | 308 |
262 const Position(this.line, this.column); | 309 const Position(this.line, this.column); |
263 | 310 |
264 bool operator <=(Position other) { | 311 bool operator <=(Position other) { |
265 return line < other.line || | 312 return line < other.line || |
266 line == other.line && column <= other.column; | 313 line == other.line && column <= other.column; |
267 } | 314 } |
268 | 315 |
269 String toString() => '[$line,$column]'; | 316 String toString() => '[${line + 1},${column + 1}]'; |
270 } | 317 } |
271 | 318 |
272 class Interval { | 319 class Interval { |
273 final Position begin; | 320 final Position begin; |
274 final Position end; | 321 final Position end; |
275 | 322 |
276 Interval(this.begin, this.end); | 323 Interval(this.begin, this.end); |
277 | 324 |
278 bool contains(Position other) { | 325 bool contains(Position other) { |
279 return begin <= other && other <= end; | 326 return begin <= other && other <= end; |
280 } | 327 } |
281 | 328 |
282 String toString() => '$begin-$end'; | 329 String toString() => '$begin-$end'; |
283 } | 330 } |
OLD | NEW |