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 library trydart.poi; | 5 library trydart.poi; |
6 | 6 |
7 import 'dart:async' show | 7 import 'dart:async' show |
8 Completer, | 8 Completer, |
9 Future, | 9 Future, |
10 Stream; | 10 Stream; |
11 | 11 |
12 import 'dart:io' show | 12 import 'dart:io' show |
| 13 File, |
13 HttpClient, | 14 HttpClient, |
14 HttpClientRequest, | 15 HttpClientRequest, |
15 HttpClientResponse, | 16 HttpClientResponse, |
16 Platform, | 17 Platform, |
17 stdout; | 18 stdout; |
18 | 19 |
19 import 'dart:io' as io; | 20 import 'dart:io' as io; |
20 | 21 |
21 import 'dart:convert' show | 22 import 'dart:convert' show |
22 LineSplitter, | 23 LineSplitter, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 PartialClassElement, | 63 PartialClassElement, |
63 PartialElement, | 64 PartialElement, |
64 Token; | 65 Token; |
65 | 66 |
66 /// Controls if this program should be querying Dart Mind. Used by tests. | 67 /// Controls if this program should be querying Dart Mind. Used by tests. |
67 bool enableDartMind = true; | 68 bool enableDartMind = true; |
68 | 69 |
69 /// Iterator over lines from standard input (or the argument array). | 70 /// Iterator over lines from standard input (or the argument array). |
70 Iterator<String> stdin; | 71 Iterator<String> stdin; |
71 | 72 |
| 73 /// Enabled by the option --simulate-mutation. When true, this program will |
| 74 /// only prompt for one file name, and subsequent runs will read |
| 75 /// FILENAME.N.dart, where N starts at 1, and is increased on each iteration. |
| 76 /// For example, if the program is invoked as: |
| 77 /// |
| 78 /// dart poi.dart --simulate-mutation test.dart 11 22 33 44 |
| 79 /// |
| 80 /// The program will first read the file 'test.dart' and compute scope |
| 81 /// information about position 11, then position 22 in test.dart.1.dart, then |
| 82 /// position 33 in test.dart.2.dart, and finally position 44 in |
| 83 /// test.dart.3.dart. |
| 84 bool isSimulateMutationEnabled = false; |
| 85 |
| 86 /// Counts the number of times [runPoi] has been invoked. |
| 87 int poiCount; |
| 88 |
| 89 int globalCounter = 0; |
| 90 |
72 /// Iterator for reading lines from [io.stdin]. | 91 /// Iterator for reading lines from [io.stdin]. |
73 class StdinIterator implements Iterator<String> { | 92 class StdinIterator implements Iterator<String> { |
74 String current; | 93 String current; |
75 | 94 |
76 bool moveNext() { | 95 bool moveNext() { |
77 current = io.stdin.readLineSync(); | 96 current = io.stdin.readLineSync(); |
78 return true; | 97 return true; |
79 } | 98 } |
80 } | 99 } |
81 | 100 |
82 main(List<String> arguments) { | 101 main(List<String> arguments) { |
| 102 poiCount = 0; |
| 103 List<String> nonOptionArguments = []; |
| 104 for (String argument in arguments) { |
| 105 if (argument.startsWith('-')) { |
| 106 switch (argument) { |
| 107 case '--simulate-mutation': |
| 108 isSimulateMutationEnabled = true; |
| 109 break; |
| 110 default: |
| 111 throw 'Unknown option: $argument.'; |
| 112 } |
| 113 } else { |
| 114 nonOptionArguments.add(argument); |
| 115 } |
| 116 } |
| 117 if (nonOptionArguments.isEmpty) { |
| 118 stdin = new StdinIterator(); |
| 119 } else { |
| 120 stdin = nonOptionArguments.iterator; |
| 121 } |
| 122 |
83 FormattingDiagnosticHandler handler = new FormattingDiagnosticHandler(); | 123 FormattingDiagnosticHandler handler = new FormattingDiagnosticHandler(); |
84 handler | 124 handler |
85 ..verbose = false | 125 ..verbose = false |
86 ..enableColors = true; | 126 ..enableColors = true; |
87 api.CompilerInputProvider inputProvider = handler.provider; | 127 api.CompilerInputProvider inputProvider = handler.provider; |
88 | 128 |
89 if (arguments.length == 0) { | |
90 stdin = new StdinIterator(); | |
91 } else { | |
92 stdin = arguments.where((String line) { | |
93 print(line); // Simulates user input in terminal. | |
94 return true; | |
95 }).iterator; | |
96 } | |
97 | |
98 return prompt('Dart file: ').then((String fileName) { | 129 return prompt('Dart file: ').then((String fileName) { |
| 130 if (isSimulateMutationEnabled) { |
| 131 inputProvider = simulateMutation(fileName, inputProvider); |
| 132 } |
99 return prompt('Position: ').then((String position) { | 133 return prompt('Position: ').then((String position) { |
100 return parseUserInput(fileName, position, inputProvider, handler); | 134 return parseUserInput(fileName, position, inputProvider, handler); |
101 }); | 135 }); |
102 }); | 136 }); |
103 } | 137 } |
104 | 138 |
| 139 /// Create an input provider that implements the behavior documented at |
| 140 /// [simulateMutation]. |
| 141 api.CompilerInputProvider simulateMutation( |
| 142 String fileName, |
| 143 SourceFileProvider inputProvider) { |
| 144 Uri script = Uri.base.resolveUri(new Uri.file(fileName)); |
| 145 int count = poiCount; |
| 146 Future cache; |
| 147 String cachedFileName = script.toFilePath(); |
| 148 int counter = ++globalCounter; |
| 149 return (Uri uri) { |
| 150 if (counter != globalCounter) throw 'Using old provider'; |
| 151 print('fake inputProvider#$counter($uri): $poiCount $count'); |
| 152 if (uri == script) { |
| 153 if (poiCount == count) { |
| 154 cachedFileName = uri.toFilePath(); |
| 155 if (count != 0) { |
| 156 cachedFileName = '$cachedFileName.$count.dart'; |
| 157 } |
| 158 print('Not using cached version of $cachedFileName'); |
| 159 cache = new File(cachedFileName).readAsBytes().then((data) { |
| 160 print('Read file $cachedFileName: ${UTF8.decode(data)}'); |
| 161 return data; |
| 162 }); |
| 163 count++; |
| 164 } else { |
| 165 print('Using cached version of $cachedFileName'); |
| 166 } |
| 167 return cache; |
| 168 } else { |
| 169 print('Using realProvider for $uri'); |
| 170 return inputProvider(uri); |
| 171 } |
| 172 }; |
| 173 } |
| 174 |
105 Future<String> prompt(message) { | 175 Future<String> prompt(message) { |
106 stdout.write(message); | 176 if (stdin is StdinIterator) { |
| 177 stdout.write(message); |
| 178 } |
107 return stdout.flush().then((_) { | 179 return stdout.flush().then((_) { |
108 stdin.moveNext(); | 180 stdin.moveNext(); |
109 return stdin.current; | 181 return stdin.current; |
110 }); | 182 }); |
111 } | 183 } |
112 | 184 |
113 Future queryDartMind(String prefix, String info) { | 185 Future queryDartMind(String prefix, String info) { |
114 // TODO(lukechurch): Use [info] for something. | 186 // TODO(lukechurch): Use [info] for something. |
115 if (!enableDartMind) return new Future.value("[]"); | 187 if (!enableDartMind) return new Future.value("[]"); |
116 String encodedArg0 = Uri.encodeComponent('"$prefix"'); | 188 String encodedArg0 = Uri.encodeComponent('"$prefix"'); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 inputProvider(script); | 224 inputProvider(script); |
153 handler( | 225 handler( |
154 script, position, position + 1, | 226 script, position, position + 1, |
155 'Point of interest. Cursor is immediately before highlighted character.', | 227 'Point of interest. Cursor is immediately before highlighted character.', |
156 api.Diagnostic.HINT); | 228 api.Diagnostic.HINT); |
157 | 229 |
158 Stopwatch sw = new Stopwatch()..start(); | 230 Stopwatch sw = new Stopwatch()..start(); |
159 | 231 |
160 Future future = runPoi(script, position, inputProvider, handler); | 232 Future future = runPoi(script, position, inputProvider, handler); |
161 return future.then((Element element) { | 233 return future.then((Element element) { |
| 234 poiCount++; |
162 print('Resolving took ${sw.elapsedMicroseconds}us.'); | 235 print('Resolving took ${sw.elapsedMicroseconds}us.'); |
163 sw.reset(); | 236 sw.reset(); |
164 String info = scopeInformation(element, position); | 237 String info = scopeInformation(element, position); |
165 sw.stop(); | 238 sw.stop(); |
166 print(info); | 239 print(info); |
167 print('Scope information took ${sw.elapsedMicroseconds}us.'); | 240 print('Scope information took ${sw.elapsedMicroseconds}us.'); |
168 sw..reset()..start(); | 241 sw..reset()..start(); |
169 Token token = findToken(element, position); | 242 Token token = findToken(element, position); |
170 String prefix; | 243 String prefix; |
171 if (token != null) { | 244 if (token != null) { |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 buffer.write('\n'); | 637 buffer.write('\n'); |
565 indented.write('}'); | 638 indented.write('}'); |
566 } | 639 } |
567 } | 640 } |
568 | 641 |
569 modelx.ScopeX localScope(modelx.LibraryElementX element) => element.localScope; | 642 modelx.ScopeX localScope(modelx.LibraryElementX element) => element.localScope; |
570 | 643 |
571 modelx.ImportScope importScope(modelx.LibraryElementX element) { | 644 modelx.ImportScope importScope(modelx.LibraryElementX element) { |
572 return element.importScope; | 645 return element.importScope; |
573 } | 646 } |
OLD | NEW |