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 Future; | 8 Completer, |
9 Future, | |
10 Stream; | |
9 | 11 |
10 import 'dart:io' show | 12 import 'dart:io' show |
11 Platform; | 13 HttpClient, |
14 HttpClientRequest, | |
15 HttpClientResponse, | |
16 Platform, | |
17 stdout; | |
18 | |
19 import 'dart:io' as io; | |
20 | |
21 import 'dart:convert' show | |
22 LineSplitter, | |
23 UTF8; | |
12 | 24 |
13 import 'package:dart2js_incremental/dart2js_incremental.dart' show | 25 import 'package:dart2js_incremental/dart2js_incremental.dart' show |
14 reuseCompiler; | 26 reuseCompiler; |
15 | 27 |
16 import 'package:compiler/implementation/source_file_provider.dart' show | 28 import 'package:compiler/implementation/source_file_provider.dart' show |
17 FormattingDiagnosticHandler, | 29 FormattingDiagnosticHandler, |
18 SourceFileProvider; | 30 SourceFileProvider; |
19 | 31 |
20 import 'package:compiler/compiler.dart' as api; | 32 import 'package:compiler/compiler.dart' as api; |
21 | 33 |
22 import 'package:compiler/implementation/dart2jslib.dart' show | 34 import 'package:compiler/implementation/dart2jslib.dart' show |
23 Compiler, | 35 Compiler, |
24 Enqueuer, | 36 Enqueuer, |
25 QueueFilter, | 37 QueueFilter, |
26 WorkItem; | 38 WorkItem; |
27 | 39 |
28 import 'package:compiler/implementation/elements/visitor.dart' show | 40 import 'package:compiler/implementation/elements/visitor.dart' show |
29 ElementVisitor; | 41 ElementVisitor; |
30 | 42 |
31 import 'package:compiler/implementation/elements/elements.dart' show | 43 import 'package:compiler/implementation/elements/elements.dart' show |
32 ClassElement, | 44 ClassElement, |
33 CompilationUnitElement, | 45 CompilationUnitElement, |
34 Element, | 46 Element, |
35 LibraryElement, | 47 LibraryElement, |
36 ScopeContainerElement; | 48 ScopeContainerElement; |
37 | 49 |
38 import 'package:compiler/implementation/scanner/scannerlib.dart' show | 50 import 'package:compiler/implementation/scanner/scannerlib.dart' show |
51 EOF_TOKEN, | |
52 IDENTIFIER_TOKEN, | |
53 KEYWORD_TOKEN, | |
39 PartialClassElement, | 54 PartialClassElement, |
40 PartialElement; | 55 PartialElement, |
56 Token; | |
41 | 57 |
42 import 'package:compiler/implementation/util/uri_extras.dart' show | 58 import 'package:compiler/implementation/util/uri_extras.dart' show |
43 relativize; | 59 relativize; |
44 | 60 |
61 /// Controls if this program should be querying Dart Mind. Used by tests. | |
62 bool enableDartMind = true; | |
63 | |
64 /// Iterator over lines from standard input (or the argument array). | |
65 Iterator<String> stdin; | |
66 | |
67 /// Iterator for reading lines from [io.stdin]. | |
68 class StdinIterator implements Iterator<String> { | |
69 String current; | |
70 | |
71 bool moveNext() { | |
72 current = io.stdin.readLineSync(); | |
73 return true; | |
74 } | |
75 } | |
76 | |
45 main(List<String> arguments) { | 77 main(List<String> arguments) { |
46 Uri script = Uri.base.resolve(arguments.first); | |
47 int position = int.parse(arguments[1]); | |
48 | |
49 FormattingDiagnosticHandler handler = new FormattingDiagnosticHandler(); | 78 FormattingDiagnosticHandler handler = new FormattingDiagnosticHandler(); |
50 handler | 79 handler |
51 ..verbose = true | 80 ..verbose = false |
52 ..enableColors = true; | 81 ..enableColors = true; |
53 api.CompilerInputProvider inputProvider = handler.provider; | 82 api.CompilerInputProvider inputProvider = handler.provider; |
54 | 83 |
84 if (arguments.length == 0) { | |
85 stdin = new StdinIterator(); | |
Johnni Winther
2014/07/17 11:25:11
Double space.
ahe
2014/08/12 13:21:12
Done.
| |
86 } else { | |
87 stdin = arguments.where((String line) { | |
88 print(line); // Simulates user input in terminal. | |
89 return true; | |
90 }).iterator; | |
91 } | |
92 | |
93 return prompt('Dart file: ').then((String fileName) { | |
94 return prompt('Position: ').then((String position) { | |
95 return parseUserInput(fileName, position, inputProvider, handler); | |
96 }); | |
97 }); | |
98 } | |
99 | |
100 Future<String> prompt(message) { | |
101 stdout.write(message); | |
102 return stdout.flush().then((_) { | |
103 stdin.moveNext(); | |
104 return stdin.current; | |
105 }); | |
106 } | |
107 | |
108 Future queryDartMind(String prefix, String info) { | |
109 // TODO(lukechurch): Use [info] for something. | |
110 if (!enableDartMind) return new Future.value("[]"); | |
111 String encodedArg0 = Uri.encodeComponent('"$prefix"'); | |
112 String mindQuery = | |
113 'http://dart-mind.appspot.com/rpc' | |
114 '?action=GetExportingPubCompletions' | |
115 '&arg0=$encodedArg0'; | |
116 Uri uri = Uri.parse(mindQuery); | |
117 | |
118 HttpClient client = new HttpClient(); | |
119 return client.getUrl(uri).then((HttpClientRequest request) { | |
120 return request.close(); | |
121 }).then((HttpClientResponse response) { | |
122 Completer<String> completer = new Completer<String>(); | |
123 response.transform(UTF8.decoder).listen((contents) { | |
124 completer.complete(contents); | |
125 }); | |
126 return completer.future; | |
127 }); | |
128 } | |
129 | |
130 Future parseUserInput( | |
131 String fileName, | |
132 String positionString, | |
133 api.CompilerInputProvider inputProvider, | |
134 api.DiagnosticHandler handler) { | |
135 Future repeat() { | |
136 return prompt('Position: ').then((String positionString) { | |
137 return parseUserInput(fileName, positionString, inputProvider, handler); | |
138 }); | |
139 } | |
140 | |
141 Uri script = Uri.base.resolveUri(new Uri.file(fileName)); | |
142 if (positionString == null) return null; | |
143 int position = int.parse( | |
144 positionString, onError: (_) => print('Please enter an integer.')); | |
145 if (position == null) return repeat(); | |
146 | |
55 inputProvider(script); | 147 inputProvider(script); |
56 handler( | 148 handler( |
57 script, position, position + 1, | 149 script, position, position + 1, |
58 'Point of interest.', api.Diagnostic.HINT); | 150 'Point of interest. Cursor is immediately before highlighted character.', |
151 api.Diagnostic.HINT); | |
152 | |
153 Stopwatch sw = new Stopwatch()..start(); | |
59 | 154 |
60 Future future = runPoi(script, position, inputProvider, handler); | 155 Future future = runPoi(script, position, inputProvider, handler); |
61 return future.then((Element element) { | 156 return future.then((Element element) { |
62 print(scopeInformation(element, position)); | 157 print('Resolving took ${sw.elapsedMicroseconds}us.'); |
158 sw.reset(); | |
159 String info = scopeInformation(element, position); | |
160 print(info); | |
161 print('Scope information took ${sw.elapsedMicroseconds}us.'); | |
162 sw.reset(); | |
163 Token token = findToken(element, position); | |
164 String prefix; | |
165 if (token != null) { | |
166 if (token.charOffset + token.charCount <= position) { | |
167 // After the token; in whitespace, or in the beginning of another token. | |
168 prefix = ""; | |
169 } else if (token.kind == IDENTIFIER_TOKEN || | |
170 token.kind == KEYWORD_TOKEN) { | |
171 prefix = token.value.substring(0, position - token.charOffset); | |
172 } | |
173 } | |
174 print('Find token took ${sw.elapsedMicroseconds}us.'); | |
175 sw.reset(); | |
176 if (prefix != null) { | |
177 return queryDartMind(prefix, info).then((String dartMindSuggestion) { | |
178 sw.stop(); | |
179 print('Dart Mind ($prefix): $dartMindSuggestion.'); | |
180 print('Dart Mind took ${sw.elapsedMicroseconds}us.'); | |
181 return repeat(); | |
182 }); | |
183 } else { | |
184 print("Didn't talk to Dart Mind, no identifier at POI ($token)."); | |
185 return repeat(); | |
186 } | |
63 }); | 187 }); |
64 } | 188 } |
65 | 189 |
190 Token findToken(Element element, int position) { | |
Johnni Winther
2014/07/17 11:25:11
Document this method. What is the semantics/qualit
ahe
2014/08/12 13:21:12
Done.
| |
191 Token beginToken; | |
192 if (element is PartialElement) { | |
193 beginToken = element.beginToken; | |
194 } else if (element is PartialClassElement) { | |
195 beginToken = element.beginToken; | |
196 } else if (element.isLibrary) { | |
197 LibraryElement lib = element; | |
198 var tag = lib.libraryTag; | |
199 if (tag != null) { | |
200 beginToken = tag.libraryKeyword; | |
Johnni Winther
2014/07/17 11:25:11
Why only find a position in the library has a name
ahe
2014/08/12 13:21:12
I could handle more cases, but I'm focusing on oth
| |
201 } | |
202 } else { | |
203 beginToken = element.position; | |
204 } | |
205 if (beginToken == null) return null; | |
206 for (Token token = beginToken; token.kind != EOF_TOKEN; token = token.next) { | |
207 if (token.charOffset < position && position <= token.next.charOffset) { | |
208 return token; | |
209 } | |
210 } | |
211 return null; | |
212 } | |
213 | |
214 Compiler cachedCompiler; | |
215 | |
66 Future<Element> runPoi( | 216 Future<Element> runPoi( |
67 Uri script, int position, | 217 Uri script, int position, |
68 api.CompilerInputProvider inputProvider, | 218 api.CompilerInputProvider inputProvider, |
69 api.DiagnosticHandler handler) { | 219 api.DiagnosticHandler handler) { |
70 | 220 |
71 Uri libraryRoot = Uri.base.resolve('sdk/'); | 221 Uri libraryRoot = Uri.base.resolve('sdk/'); |
72 Uri packageRoot = Uri.base.resolveUri( | 222 Uri packageRoot = Uri.base.resolveUri( |
73 new Uri.file('${Platform.packageRoot}/')); | 223 new Uri.file('${Platform.packageRoot}/')); |
74 | 224 |
75 var options = [ | 225 var options = [ |
76 '--analyze-main', | 226 '--analyze-main', |
77 '--analyze-only', | 227 '--analyze-only', |
78 '--no-source-maps', | 228 '--no-source-maps', |
79 '--verbose', | 229 '--verbose', |
80 '--categories=Client,Server', | 230 '--categories=Client,Server', |
231 '--incremental-support', | |
232 '--disable-type-inference', | |
81 ]; | 233 ]; |
82 | 234 |
83 Compiler cachedCompiler = null; | |
84 cachedCompiler = reuseCompiler( | 235 cachedCompiler = reuseCompiler( |
85 diagnosticHandler: handler, | 236 diagnosticHandler: handler, |
86 inputProvider: inputProvider, | 237 inputProvider: inputProvider, |
87 options: options, | 238 options: options, |
88 cachedCompiler: cachedCompiler, | 239 cachedCompiler: cachedCompiler, |
89 libraryRoot: libraryRoot, | 240 libraryRoot: libraryRoot, |
90 packageRoot: packageRoot, | 241 packageRoot: packageRoot, |
91 packagesAreImmutable: true); | 242 packagesAreImmutable: true); |
92 | 243 |
93 cachedCompiler.enqueuerFilter = new ScriptOnlyFilter(script); | 244 cachedCompiler.enqueuerFilter = new ScriptOnlyFilter(script); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 if (!omitEnclosing) { | 396 if (!omitEnclosing) { |
246 buffer.write(',\n'); | 397 buffer.write(',\n'); |
247 indented.write('"enclosing": '); | 398 indented.write('"enclosing": '); |
248 element.enclosingElement.accept(this); | 399 element.enclosingElement.accept(this); |
249 } | 400 } |
250 indentationLevel--; | 401 indentationLevel--; |
251 buffer.write('\n'); | 402 buffer.write('\n'); |
252 indented.write('}'); | 403 indented.write('}'); |
253 } | 404 } |
254 } | 405 } |
OLD | NEW |