| 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'; | 11 import 'package:source_maps/source_maps.dart'; |
| 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 AstElement, | 14 show |
| 15 ClassElement, | 15 AstElement, |
| 16 CompilationUnitElement, | 16 ClassElement, |
| 17 Element, | 17 CompilationUnitElement, |
| 18 FunctionElement, | 18 Element, |
| 19 LibraryElement, | 19 FunctionElement, |
| 20 MemberElement; | 20 LibraryElement, |
| 21 MemberElement; |
| 21 import 'package:compiler/src/io/source_file.dart' show SourceFile; | 22 import 'package:compiler/src/io/source_file.dart' show SourceFile; |
| 22 import 'package:compiler/src/io/source_information.dart' | 23 import 'package:compiler/src/io/source_information.dart' |
| 23 show computeElementNameForSourceMaps; | 24 show computeElementNameForSourceMaps; |
| 24 | 25 |
| 25 validateSourceMap(Uri targetUri, | 26 validateSourceMap(Uri targetUri, |
| 26 {Uri mainUri, | 27 {Uri mainUri, Position mainPosition, CompilerImpl compiler}) { |
| 27 Position mainPosition, | |
| 28 CompilerImpl compiler}) { | |
| 29 Uri mapUri = getMapUri(targetUri); | 28 Uri mapUri = getMapUri(targetUri); |
| 30 List<String> targetLines = new File.fromUri(targetUri).readAsLinesSync(); | 29 List<String> targetLines = new File.fromUri(targetUri).readAsLinesSync(); |
| 31 SingleMapping sourceMap = getSourceMap(mapUri); | 30 SingleMapping sourceMap = getSourceMap(mapUri); |
| 32 checkFileReferences(targetUri, mapUri, sourceMap); | 31 checkFileReferences(targetUri, mapUri, sourceMap); |
| 33 checkIndexReferences(targetLines, mapUri, sourceMap); | 32 checkIndexReferences(targetLines, mapUri, sourceMap); |
| 34 checkRedundancy(sourceMap); | 33 checkRedundancy(sourceMap); |
| 35 if (compiler != null) { | 34 if (compiler != null) { |
| 36 checkNames(targetUri, mapUri, sourceMap, compiler); | 35 checkNames(targetUri, mapUri, sourceMap, compiler); |
| 37 } | 36 } |
| 38 if (mainUri != null && mainPosition != null) { | 37 if (mainUri != null && mainPosition != null) { |
| 39 checkMainPosition(targetUri, targetLines ,sourceMap, mainUri, mainPosition); | 38 checkMainPosition(targetUri, targetLines, sourceMap, mainUri, mainPosition); |
| 40 } | 39 } |
| 41 } | 40 } |
| 42 | 41 |
| 43 checkIndexReferences(List<String> targetLines, | 42 checkIndexReferences( |
| 44 Uri mapUri, | 43 List<String> targetLines, Uri mapUri, SingleMapping sourceMap) { |
| 45 SingleMapping sourceMap) { | |
| 46 int urlsLength = sourceMap.urls.length; | 44 int urlsLength = sourceMap.urls.length; |
| 47 List<List<String>> sources = new List(urlsLength); | 45 List<List<String>> sources = new List(urlsLength); |
| 48 print('Reading sources'); | 46 print('Reading sources'); |
| 49 for (int i = 0; i < urlsLength; i++) { | 47 for (int i = 0; i < urlsLength; i++) { |
| 50 sources[i] = new File.fromUri(mapUri.resolve(sourceMap.urls[i])). | 48 sources[i] = new File.fromUri(mapUri.resolve(sourceMap.urls[i])) |
| 51 readAsStringSync().split('\n'); | 49 .readAsStringSync() |
| 50 .split('\n'); |
| 52 } | 51 } |
| 53 | 52 |
| 54 sourceMap.lines.forEach((TargetLineEntry line) { | 53 sourceMap.lines.forEach((TargetLineEntry line) { |
| 55 Expect.isTrue(line.line >= 0); | 54 Expect.isTrue(line.line >= 0); |
| 56 Expect.isTrue(line.line < targetLines.length); | 55 Expect.isTrue(line.line < targetLines.length); |
| 57 for (TargetEntry entry in line.entries) { | 56 for (TargetEntry entry in line.entries) { |
| 58 int urlIndex = entry.sourceUrlId; | 57 int urlIndex = entry.sourceUrlId; |
| 59 | 58 |
| 60 // TODO(zarah): Entry columns sometimes point one or more characters too | 59 // TODO(zarah): Entry columns sometimes point one or more characters too |
| 61 // far. Incomment this check when this is fixed. | 60 // far. Incomment this check when this is fixed. |
| 62 // | 61 // |
| 63 // Expect.isTrue(entry.column < target[line.line].length); | 62 // Expect.isTrue(entry.column < target[line.line].length); |
| 64 Expect.isTrue(entry.column >= 0); | 63 Expect.isTrue(entry.column >= 0); |
| 65 Expect.isTrue(urlIndex == null || | 64 Expect |
| 66 (urlIndex >= 0 && urlIndex < urlsLength)); | 65 .isTrue(urlIndex == null || (urlIndex >= 0 && urlIndex < urlsLength)); |
| 67 Expect.isTrue(entry.sourceLine == null || | 66 Expect.isTrue(entry.sourceLine == null || |
| 68 (entry.sourceLine >= 0 && | 67 (entry.sourceLine >= 0 && |
| 69 entry.sourceLine < sources[urlIndex].length)); | 68 entry.sourceLine < sources[urlIndex].length)); |
| 70 Expect.isTrue(entry.sourceColumn == null || | 69 Expect.isTrue(entry.sourceColumn == null || |
| 71 (entry.sourceColumn >= 0 && | 70 (entry.sourceColumn >= 0 && |
| 72 entry.sourceColumn < sources[urlIndex][entry.sourceLine].length)); | 71 entry.sourceColumn < sources[urlIndex][entry.sourceLine].length)); |
| 73 Expect.isTrue(entry.sourceNameId == null || | 72 Expect.isTrue(entry.sourceNameId == null || |
| 74 (entry.sourceNameId >= 0 && | 73 (entry.sourceNameId >= 0 && |
| 75 entry.sourceNameId < sourceMap.names.length)); | 74 entry.sourceNameId < sourceMap.names.length)); |
| 76 } | 75 } |
| 77 }); | 76 }); |
| 78 } | 77 } |
| 79 | 78 |
| 80 checkFileReferences(Uri targetUri, Uri mapUri, SingleMapping sourceMap) { | 79 checkFileReferences(Uri targetUri, Uri mapUri, SingleMapping sourceMap) { |
| 81 Expect.equals(targetUri, mapUri.resolve(sourceMap.targetUrl)); | 80 Expect.equals(targetUri, mapUri.resolve(sourceMap.targetUrl)); |
| 82 print('Checking sources'); | 81 print('Checking sources'); |
| 83 sourceMap.urls.forEach((String url) { | 82 sourceMap.urls.forEach((String url) { |
| 84 Expect.isTrue(new File.fromUri(mapUri.resolve(url)).existsSync()); | 83 Expect.isTrue(new File.fromUri(mapUri.resolve(url)).existsSync()); |
| 85 }); | 84 }); |
| 86 } | 85 } |
| 87 | 86 |
| 88 checkRedundancy(SingleMapping sourceMap) { | 87 checkRedundancy(SingleMapping sourceMap) { |
| 89 sourceMap.lines.forEach((TargetLineEntry line) { | 88 sourceMap.lines.forEach((TargetLineEntry line) { |
| 90 TargetEntry previous = null; | 89 TargetEntry previous = null; |
| 91 for (TargetEntry next in line.entries) { | 90 for (TargetEntry next in line.entries) { |
| 92 if (previous != null) { | 91 if (previous != null) { |
| 93 Expect.isFalse(sameSourcePoint(previous, next), | 92 Expect.isFalse( |
| 93 sameSourcePoint(previous, next), |
| 94 '$previous and $next are consecutive entries on line $line in the ' | 94 '$previous and $next are consecutive entries on line $line in the ' |
| 95 'source map but point to same source locations'); | 95 'source map but point to same source locations'); |
| 96 } | 96 } |
| 97 previous = next; | 97 previous = next; |
| 98 } | 98 } |
| 99 }); | 99 }); |
| 100 } | 100 } |
| 101 | 101 |
| 102 checkNames(Uri targetUri, Uri mapUri, | 102 checkNames( |
| 103 SingleMapping sourceMap, CompilerImpl compiler) { | 103 Uri targetUri, Uri mapUri, SingleMapping sourceMap, CompilerImpl compiler) { |
| 104 Map<Uri, CompilationUnitElement> compilationUnitMap = {}; | 104 Map<Uri, CompilationUnitElement> compilationUnitMap = {}; |
| 105 | 105 |
| 106 void mapCompilationUnits(LibraryElement library) { | 106 void mapCompilationUnits(LibraryElement library) { |
| 107 library.compilationUnits.forEach((CompilationUnitElement compilationUnit) { | 107 library.compilationUnits.forEach((CompilationUnitElement compilationUnit) { |
| 108 compilationUnitMap[compilationUnit.script.readableUri] = compilationUnit; | 108 compilationUnitMap[compilationUnit.script.readableUri] = compilationUnit; |
| 109 }); | 109 }); |
| 110 } | 110 } |
| 111 | 111 |
| 112 compiler.libraryLoader.libraries.forEach((LibraryElement library) { | 112 compiler.libraryLoader.libraries.forEach((LibraryElement library) { |
| 113 mapCompilationUnits(library); | 113 mapCompilationUnits(library); |
| 114 if (library.patch != null) { | 114 if (library.patch != null) { |
| 115 mapCompilationUnits(library.patch); | 115 mapCompilationUnits(library.patch); |
| 116 } | 116 } |
| 117 }); | 117 }); |
| 118 | 118 |
| 119 sourceMap.lines.forEach((TargetLineEntry line) { | 119 sourceMap.lines.forEach((TargetLineEntry line) { |
| 120 for (TargetEntry entry in line.entries) { | 120 for (TargetEntry entry in line.entries) { |
| 121 if (entry.sourceNameId != null) { | 121 if (entry.sourceNameId != null) { |
| 122 Uri uri = mapUri.resolve(sourceMap.urls[entry.sourceUrlId]); | 122 Uri uri = mapUri.resolve(sourceMap.urls[entry.sourceUrlId]); |
| 123 Position targetPosition = | 123 Position targetPosition = new Position(line.line, entry.column); |
| 124 new Position(line.line, entry.column); | |
| 125 Position sourcePosition = | 124 Position sourcePosition = |
| 126 new Position(entry.sourceLine, entry.sourceColumn); | 125 new Position(entry.sourceLine, entry.sourceColumn); |
| 127 String name = sourceMap.names[entry.sourceNameId]; | 126 String name = sourceMap.names[entry.sourceNameId]; |
| 128 | 127 |
| 129 CompilationUnitElement compilationUnit = compilationUnitMap[uri]; | 128 CompilationUnitElement compilationUnit = compilationUnitMap[uri]; |
| 130 Expect.isNotNull(compilationUnit, | 129 Expect.isNotNull( |
| 131 "No compilation unit found for $uri."); | 130 compilationUnit, "No compilation unit found for $uri."); |
| 132 | 131 |
| 133 SourceFile sourceFile = compilationUnit.script.file; | 132 SourceFile sourceFile = compilationUnit.script.file; |
| 134 | 133 |
| 135 Position positionFromOffset(int offset) { | 134 Position positionFromOffset(int offset) { |
| 136 int line = sourceFile.getLine(offset); | 135 int line = sourceFile.getLine(offset); |
| 137 int column = sourceFile.getColumn(line, offset); | 136 int column = sourceFile.getColumn(line, offset); |
| 138 return new Position(line, column); | 137 return new Position(line, column); |
| 139 } | 138 } |
| 140 | 139 |
| 141 Interval intervalFromElement(AstElement element) { | 140 Interval intervalFromElement(AstElement element) { |
| 142 if (!element.hasNode) return null; | 141 if (!element.hasNode) return null; |
| 143 | 142 |
| 144 var begin = element.node.getBeginToken().charOffset; | 143 var begin = element.node.getBeginToken().charOffset; |
| 145 var end = element.node.getEndToken(); | 144 var end = element.node.getEndToken(); |
| 146 end = end.charOffset + end.charCount; | 145 end = end.charOffset + end.charCount; |
| 147 return new Interval(positionFromOffset(begin), | 146 return new Interval( |
| 148 positionFromOffset(end)); | 147 positionFromOffset(begin), positionFromOffset(end)); |
| 149 } | 148 } |
| 150 | 149 |
| 151 AstElement findInnermost(AstElement element) { | 150 AstElement findInnermost(AstElement element) { |
| 152 bool isInsideElement(FunctionElement closure) { | 151 bool isInsideElement(FunctionElement closure) { |
| 153 Element enclosing = closure; | 152 Element enclosing = closure; |
| 154 while (enclosing != null) { | 153 while (enclosing != null) { |
| 155 if (enclosing == element) return true; | 154 if (enclosing == element) return true; |
| 156 enclosing = enclosing.enclosingElement; | 155 enclosing = enclosing.enclosingElement; |
| 157 } | 156 } |
| 158 return false; | 157 return false; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 170 } | 169 } |
| 171 }); | 170 }); |
| 172 } | 171 } |
| 173 return element; | 172 return element; |
| 174 } | 173 } |
| 175 | 174 |
| 176 void match(AstElement element) { | 175 void match(AstElement element) { |
| 177 Interval interval = intervalFromElement(element); | 176 Interval interval = intervalFromElement(element); |
| 178 if (interval != null && interval.contains(sourcePosition)) { | 177 if (interval != null && interval.contains(sourcePosition)) { |
| 179 AstElement innerElement = findInnermost(element); | 178 AstElement innerElement = findInnermost(element); |
| 180 String expectedName = | 179 String expectedName = computeElementNameForSourceMaps(innerElement); |
| 181 computeElementNameForSourceMaps(innerElement); | |
| 182 if (name != expectedName) { | 180 if (name != expectedName) { |
| 183 // For the code | 181 // For the code |
| 184 // (){}(); | 182 // (){}(); |
| 185 // ^ | 183 // ^ |
| 186 // the indicated position is within the scope of the local | 184 // the indicated position is within the scope of the local |
| 187 // function but it is also the position for the invocation of it. | 185 // 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 | 186 // Allow name to be either from the local or from its calling |
| 189 // context. | 187 // context. |
| 190 if (innerElement.isLocal && innerElement.isFunction) { | 188 if (innerElement.isLocal && innerElement.isFunction) { |
| 191 var enclosingElement = innerElement.enclosingElement; | 189 var enclosingElement = innerElement.enclosingElement; |
| 192 String expectedName2 = | 190 String expectedName2 = |
| 193 computeElementNameForSourceMaps(enclosingElement); | 191 computeElementNameForSourceMaps(enclosingElement); |
| 194 Expect.isTrue(name == expectedName2, | 192 Expect.isTrue( |
| 193 name == expectedName2, |
| 195 "Unexpected name '${name}', " | 194 "Unexpected name '${name}', " |
| 196 "expected '${expectedName}' for $innerElement " | 195 "expected '${expectedName}' for $innerElement " |
| 197 "or '${expectedName2}' for $enclosingElement."); | 196 "or '${expectedName2}' for $enclosingElement."); |
| 198 } else { | 197 } else { |
| 199 Expect.equals(expectedName, name, | 198 Expect.equals( |
| 199 expectedName, |
| 200 name, |
| 200 "Unexpected name '${name}', " | 201 "Unexpected name '${name}', " |
| 201 "expected '${expectedName}' or for $innerElement."); | 202 "expected '${expectedName}' or for $innerElement."); |
| 202 } | 203 } |
| 203 } | 204 } |
| 204 } | 205 } |
| 205 } | 206 } |
| 206 | 207 |
| 207 compilationUnit.forEachLocalMember((AstElement element) { | 208 compilationUnit.forEachLocalMember((AstElement element) { |
| 208 if (element.isClass) { | 209 if (element.isClass) { |
| 209 ClassElement classElement = element; | 210 ClassElement classElement = element; |
| 210 classElement.forEachLocalMember(match); | 211 classElement.forEachLocalMember(match); |
| 211 } else { | 212 } else { |
| 212 match(element); | 213 match(element); |
| 213 } | 214 } |
| 214 }); | 215 }); |
| 215 } | 216 } |
| 216 } | 217 } |
| 217 }); | 218 }); |
| 218 } | 219 } |
| 219 | 220 |
| 220 RegExp mainSignaturePrefix = new RegExp(r'main: \[?function\('); | 221 RegExp mainSignaturePrefix = new RegExp(r'main: \[?function\('); |
| 221 | 222 |
| 222 // Check that the line pointing to by [mainPosition] in [mainUri] contains | 223 // Check that the line pointing to by [mainPosition] in [mainUri] contains |
| 223 // the main function signature. | 224 // the main function signature. |
| 224 checkMainPosition(Uri targetUri, | 225 checkMainPosition(Uri targetUri, List<String> targetLines, |
| 225 List<String> targetLines, | 226 SingleMapping sourceMap, Uri mainUri, Position mainPosition) { |
| 226 SingleMapping sourceMap, | |
| 227 Uri mainUri, | |
| 228 Position mainPosition) { | |
| 229 bool mainPositionFound = false; | 227 bool mainPositionFound = false; |
| 230 sourceMap.lines.forEach((TargetLineEntry lineEntry) { | 228 sourceMap.lines.forEach((TargetLineEntry lineEntry) { |
| 231 lineEntry.entries.forEach((TargetEntry entry) { | 229 lineEntry.entries.forEach((TargetEntry entry) { |
| 232 if (entry.sourceLine == null || entry.sourceUrlId == null) return; | 230 if (entry.sourceLine == null || entry.sourceUrlId == null) return; |
| 233 Uri sourceUri = targetUri.resolve(sourceMap.urls[entry.sourceUrlId]); | 231 Uri sourceUri = targetUri.resolve(sourceMap.urls[entry.sourceUrlId]); |
| 234 if (sourceUri != mainUri) return; | 232 if (sourceUri != mainUri) return; |
| 235 if (entry.sourceLine + 1 == mainPosition.line && | 233 if (entry.sourceLine + 1 == mainPosition.line && |
| 236 entry.sourceColumn + 1 == mainPosition.column) { | 234 entry.sourceColumn + 1 == mainPosition.column) { |
| 237 Expect.isNotNull(entry.sourceNameId, | 235 Expect.isNotNull(entry.sourceNameId, "Main position has no name."); |
| 238 "Main position has no name."); | |
| 239 String name = sourceMap.names[entry.sourceNameId]; | 236 String name = sourceMap.names[entry.sourceNameId]; |
| 240 Expect.equals('main', name, | 237 Expect.equals( |
| 241 "Main position name is not '$name', not 'main'."); | 238 'main', name, "Main position name is not '$name', not 'main'."); |
| 242 String line = targetLines[lineEntry.line]; | 239 String line = targetLines[lineEntry.line]; |
| 243 Expect.isTrue(line.contains(mainSignaturePrefix), | 240 Expect.isTrue( |
| 241 line.contains(mainSignaturePrefix), |
| 244 "Line mapped to main position " | 242 "Line mapped to main position " |
| 245 "([${lineEntry.line + 1},${entry.column + 1}]) " | 243 "([${lineEntry.line + 1},${entry.column + 1}]) " |
| 246 "expected to contain '${mainSignaturePrefix.pattern}':\n$line\n"); | 244 "expected to contain '${mainSignaturePrefix.pattern}':\n$line\n"); |
| 247 mainPositionFound = true; | 245 mainPositionFound = true; |
| 248 } | 246 } |
| 249 }); | 247 }); |
| 250 }); | 248 }); |
| 251 Expect.isTrue(mainPositionFound, | 249 Expect.isTrue( |
| 252 'No main position $mainPosition found in $mainUri'); | 250 mainPositionFound, 'No main position $mainPosition found in $mainUri'); |
| 253 } | 251 } |
| 254 | 252 |
| 255 | |
| 256 sameSourcePoint(TargetEntry entry, TargetEntry otherEntry) { | 253 sameSourcePoint(TargetEntry entry, TargetEntry otherEntry) { |
| 257 return | 254 return (entry.sourceUrlId == otherEntry.sourceUrlId) && |
| 258 (entry.sourceUrlId == otherEntry.sourceUrlId) && | |
| 259 (entry.sourceLine == otherEntry.sourceLine) && | 255 (entry.sourceLine == otherEntry.sourceLine) && |
| 260 (entry.sourceColumn == otherEntry.sourceColumn) && | 256 (entry.sourceColumn == otherEntry.sourceColumn) && |
| 261 (entry.sourceNameId == otherEntry.sourceNameId); | 257 (entry.sourceNameId == otherEntry.sourceNameId); |
| 262 } | 258 } |
| 263 | 259 |
| 264 Uri getMapUri(Uri targetUri) { | 260 Uri getMapUri(Uri targetUri) { |
| 265 print('Accessing $targetUri'); | 261 print('Accessing $targetUri'); |
| 266 File targetFile = new File.fromUri(targetUri); | 262 File targetFile = new File.fromUri(targetUri); |
| 267 Expect.isTrue(targetFile.existsSync(), "File '$targetUri' doesn't exist."); | 263 Expect.isTrue(targetFile.existsSync(), "File '$targetUri' doesn't exist."); |
| 268 List<String> target = targetFile.readAsStringSync().split('\n'); | 264 List<String> target = targetFile.readAsStringSync().split('\n'); |
| 269 String mapReference = target[target.length - 2]; // #sourceMappingURL=<url> | 265 String mapReference = target[target.length - 2]; // #sourceMappingURL=<url> |
| 270 Expect.isTrue(mapReference.startsWith('//# sourceMappingURL=')); | 266 Expect.isTrue(mapReference.startsWith('//# sourceMappingURL=')); |
| 271 String mapName = mapReference.substring(mapReference.indexOf('=') + 1); | 267 String mapName = mapReference.substring(mapReference.indexOf('=') + 1); |
| 272 return targetUri.resolve(mapName); | 268 return targetUri.resolve(mapName); |
| 273 } | 269 } |
| 274 | 270 |
| 275 SingleMapping getSourceMap(Uri mapUri) { | 271 SingleMapping getSourceMap(Uri mapUri) { |
| 276 print('Accessing $mapUri'); | 272 print('Accessing $mapUri'); |
| 277 File mapFile = new File.fromUri(mapUri); | 273 File mapFile = new File.fromUri(mapUri); |
| 278 Expect.isTrue(mapFile.existsSync()); | 274 Expect.isTrue(mapFile.existsSync()); |
| 279 return new SingleMapping.fromJson( | 275 return new SingleMapping.fromJson(JSON.decode(mapFile.readAsStringSync())); |
| 280 JSON.decode(mapFile.readAsStringSync())); | |
| 281 } | 276 } |
| 282 | 277 |
| 283 copyDirectory(Directory sourceDir, Directory destinationDir) { | 278 copyDirectory(Directory sourceDir, Directory destinationDir) { |
| 284 sourceDir.listSync().forEach((FileSystemEntity element) { | 279 sourceDir.listSync().forEach((FileSystemEntity element) { |
| 285 String newPath = path.join(destinationDir.path, | 280 String newPath = |
| 286 path.basename(element.path)); | 281 path.join(destinationDir.path, path.basename(element.path)); |
| 287 if (element is File) { | 282 if (element is File) { |
| 288 element.copySync(newPath); | 283 element.copySync(newPath); |
| 289 } else if (element is Directory) { | 284 } else if (element is Directory) { |
| 290 Directory newDestinationDir = new Directory(newPath); | 285 Directory newDestinationDir = new Directory(newPath); |
| 291 newDestinationDir.createSync(); | 286 newDestinationDir.createSync(); |
| 292 copyDirectory(element, newDestinationDir); | 287 copyDirectory(element, newDestinationDir); |
| 293 } | 288 } |
| 294 }); | 289 }); |
| 295 } | 290 } |
| 296 | 291 |
| 297 Future<Directory> createTempDir() { | 292 Future<Directory> createTempDir() { |
| 298 return Directory.systemTemp | 293 return Directory.systemTemp |
| 299 .createTemp('sourceMap_test-') | 294 .createTemp('sourceMap_test-') |
| 300 .then((Directory dir) { | 295 .then((Directory dir) { |
| 301 return dir; | 296 return dir; |
| 302 }); | 297 }); |
| 303 } | 298 } |
| 304 | 299 |
| 305 class Position { | 300 class Position { |
| 306 final int line; | 301 final int line; |
| 307 final int column; | 302 final int column; |
| 308 | 303 |
| 309 const Position(this.line, this.column); | 304 const Position(this.line, this.column); |
| 310 | 305 |
| 311 bool operator <=(Position other) { | 306 bool operator <=(Position other) { |
| 312 return line < other.line || | 307 return line < other.line || line == other.line && column <= other.column; |
| 313 line == other.line && column <= other.column; | |
| 314 } | 308 } |
| 315 | 309 |
| 316 String toString() => '[${line + 1},${column + 1}]'; | 310 String toString() => '[${line + 1},${column + 1}]'; |
| 317 } | 311 } |
| 318 | 312 |
| 319 class Interval { | 313 class Interval { |
| 320 final Position begin; | 314 final Position begin; |
| 321 final Position end; | 315 final Position end; |
| 322 | 316 |
| 323 Interval(this.begin, this.end); | 317 Interval(this.begin, this.end); |
| 324 | 318 |
| 325 bool contains(Position other) { | 319 bool contains(Position other) { |
| 326 return begin <= other && other <= end; | 320 return begin <= other && other <= end; |
| 327 } | 321 } |
| 328 | 322 |
| 329 String toString() => '$begin-$end'; | 323 String toString() => '$begin-$end'; |
| 330 } | 324 } |
| OLD | NEW |