Chromium Code Reviews| 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 Future; |
| 9 | 9 |
| 10 import 'dart:io' show | 10 import 'dart:io' show |
| 11 Platform; | 11 Platform; |
| 12 | 12 |
| 13 import 'package:dart2js_incremental/dart2js_incremental.dart' show | 13 import 'package:dart2js_incremental/dart2js_incremental.dart' show |
| 14 reuseCompiler; | 14 reuseCompiler; |
| 15 | 15 |
| 16 import 'package:compiler/implementation/source_file_provider.dart' show | 16 import 'package:compiler/implementation/source_file_provider.dart' show |
| 17 FormattingDiagnosticHandler, | 17 FormattingDiagnosticHandler, |
| 18 SourceFileProvider; | 18 SourceFileProvider; |
| 19 | 19 |
| 20 import 'package:compiler/compiler.dart' as api show | 20 import 'package:compiler/compiler.dart' as api; |
| 21 Diagnostic; | |
| 22 | 21 |
| 23 import 'package:compiler/implementation/dart2jslib.dart' show | 22 import 'package:compiler/implementation/dart2jslib.dart' show |
| 24 Compiler, | 23 Compiler, |
| 25 Enqueuer, | 24 Enqueuer, |
| 26 QueueFilter, | 25 QueueFilter, |
| 27 WorkItem; | 26 WorkItem; |
| 28 | 27 |
| 29 import 'package:compiler/implementation/elements/visitor.dart' show | 28 import 'package:compiler/implementation/elements/visitor.dart' show |
| 30 ElementVisitor; | 29 ElementVisitor; |
| 31 | 30 |
| 32 import 'package:compiler/implementation/elements/elements.dart' show | 31 import 'package:compiler/implementation/elements/elements.dart' show |
| 33 ClassElement, | 32 ClassElement, |
| 33 CompilationUnitElement, | |
| 34 Element, | 34 Element, |
| 35 LibraryElement, | |
| 35 ScopeContainerElement; | 36 ScopeContainerElement; |
| 36 | 37 |
| 37 import 'package:compiler/implementation/scanner/scannerlib.dart' show | 38 import 'package:compiler/implementation/scanner/scannerlib.dart' show |
| 38 PartialClassElement, | 39 PartialClassElement, |
| 39 PartialElement; | 40 PartialElement; |
| 40 | 41 |
| 42 import 'package:compiler/implementation/util/uri_extras.dart' show | |
| 43 relativize; | |
| 44 | |
| 41 main(List<String> arguments) { | 45 main(List<String> arguments) { |
| 42 Uri script = Uri.base.resolve(arguments.first); | 46 Uri script = Uri.base.resolve(arguments.first); |
| 43 int position = int.parse(arguments[1]); | 47 int position = int.parse(arguments[1]); |
| 44 return runPoi(script, position).then((Element element) { | |
| 45 print('Found $element.'); | |
| 46 }); | |
| 47 } | |
| 48 | 48 |
| 49 Future<Element> runPoi(Uri script, int position) { | |
| 50 FormattingDiagnosticHandler handler = new FormattingDiagnosticHandler(); | 49 FormattingDiagnosticHandler handler = new FormattingDiagnosticHandler(); |
| 51 handler | 50 handler |
| 52 ..verbose = true | 51 ..verbose = true |
| 53 ..enableColors = true; | 52 ..enableColors = true; |
| 53 api.CompilerInputProvider inputProvider = handler.provider; | |
| 54 | |
| 55 inputProvider(script); | |
| 56 handler( | |
| 57 script, position, position + 1, | |
| 58 'Point of interest.', api.Diagnostic.HINT); | |
| 59 | |
| 60 Future future = runPoi(script, position, inputProvider, handler); | |
| 61 return future.then((Element element) { | |
| 62 print(scopeInformation(element, position)); | |
| 63 }); | |
| 64 } | |
| 65 | |
| 66 Future<Element> runPoi( | |
| 67 Uri script, int position, | |
| 68 api.CompilerInputProvider inputProvider, | |
| 69 api.DiagnosticHandler handler) { | |
| 54 | 70 |
| 55 Uri libraryRoot = Uri.base.resolve('sdk/'); | 71 Uri libraryRoot = Uri.base.resolve('sdk/'); |
| 56 Uri packageRoot = Uri.base.resolveUri( | 72 Uri packageRoot = Uri.base.resolveUri( |
| 57 new Uri.file('${Platform.packageRoot}/')); | 73 new Uri.file('${Platform.packageRoot}/')); |
| 58 | 74 |
| 59 var options = [ | 75 var options = [ |
| 60 '--analyze-main', | 76 '--analyze-main', |
| 61 '--analyze-only', | 77 '--analyze-only', |
| 62 '--no-source-maps', | 78 '--no-source-maps', |
| 63 '--verbose', | 79 '--verbose', |
| 64 '--categories=Client,Server', | 80 '--categories=Client,Server', |
| 65 ]; | 81 ]; |
| 66 | 82 |
| 67 Compiler cachedCompiler = null; | 83 Compiler cachedCompiler = null; |
| 68 cachedCompiler = reuseCompiler( | 84 cachedCompiler = reuseCompiler( |
| 69 diagnosticHandler: handler, | 85 diagnosticHandler: handler, |
| 70 inputProvider: handler.provider, | 86 inputProvider: inputProvider, |
| 71 options: options, | 87 options: options, |
| 72 cachedCompiler: cachedCompiler, | 88 cachedCompiler: cachedCompiler, |
| 73 libraryRoot: libraryRoot, | 89 libraryRoot: libraryRoot, |
| 74 packageRoot: packageRoot, | 90 packageRoot: packageRoot, |
| 75 packagesAreImmutable: true); | 91 packagesAreImmutable: true); |
| 76 | 92 |
| 77 cachedCompiler.enqueuerFilter = new ScriptOnlyFilter(script); | 93 cachedCompiler.enqueuerFilter = new ScriptOnlyFilter(script); |
| 78 | 94 |
| 79 return cachedCompiler.run(script).then((success) { | 95 return cachedCompiler.run(script).then((success) { |
| 80 if (success != true) { | 96 if (success != true) { |
| 81 throw 'Compilation failed'; | 97 throw 'Compilation failed'; |
| 82 } | 98 } |
| 83 return poi(cachedCompiler, script, position); | 99 return findPosition(position, cachedCompiler.mainApp); |
| 84 }); | 100 }); |
| 85 } | 101 } |
| 86 | 102 |
| 87 Element poi(Compiler compiler, Uri script, int offset) { | |
| 88 compiler.handler( | |
| 89 script, offset, offset + 1, | |
| 90 'Point of interest.', api.Diagnostic.HINT); | |
| 91 | |
| 92 Element element = findPosition(offset, compiler.mainApp); | |
| 93 | |
| 94 return element; | |
| 95 } | |
| 96 | |
| 97 Element findPosition(int position, Element element) { | 103 Element findPosition(int position, Element element) { |
| 98 FindPositionVisitor visitor = new FindPositionVisitor(position, element); | 104 FindPositionVisitor visitor = new FindPositionVisitor(position, element); |
| 99 element.accept(visitor); | 105 element.accept(visitor); |
| 100 return visitor.element; | 106 return visitor.element; |
| 101 } | 107 } |
| 102 | 108 |
| 109 String scopeInformation(Element element, int position) { | |
| 110 ScopeInformationVisitor vistor = | |
|
Johnni Winther
2014/07/14 10:35:36
'vistor' -> 'visitor'.
ahe
2014/07/14 13:06:07
Done.
| |
| 111 new ScopeInformationVisitor(element, position); | |
| 112 element.accept(vistor); | |
| 113 return '${vistor.buffer}'; | |
| 114 } | |
| 115 | |
| 103 class FindPositionVisitor extends ElementVisitor { | 116 class FindPositionVisitor extends ElementVisitor { |
| 104 final int position; | 117 final int position; |
| 105 Element element; | 118 Element element; |
| 106 | 119 |
| 107 FindPositionVisitor(this.position, this.element); | 120 FindPositionVisitor(this.position, this.element); |
| 108 | 121 |
| 109 visitElement(Element e) { | 122 visitElement(Element e) { |
| 110 if (e is! PartialElement) return; | 123 if (e is PartialElement) { |
| 111 if (e.beginToken.charOffset <= position && | 124 if (e.beginToken.charOffset <= position && |
| 112 position < e.endToken.next.charOffset) { | 125 position < e.endToken.next.charOffset) { |
| 113 element = e; | 126 element = e; |
| 127 } | |
| 114 } | 128 } |
| 115 } | 129 } |
| 116 | 130 |
| 117 visitClassElement(ClassElement e) { | 131 visitClassElement(ClassElement e) { |
| 118 if (e is! PartialClassElement) return; | 132 if (e is PartialClassElement) { |
| 119 if (e.beginToken.charOffset <= position && | 133 if (e.beginToken.charOffset <= position && |
| 120 position < e.endToken.next.charOffset) { | 134 position < e.endToken.next.charOffset) { |
| 121 element = e; | 135 element = e; |
| 122 visitScopeContainerElement(e); | 136 visitScopeContainerElement(e); |
| 137 } | |
| 123 } | 138 } |
| 124 } | 139 } |
| 125 | 140 |
| 126 visitScopeContainerElement(ScopeContainerElement e) { | 141 visitScopeContainerElement(ScopeContainerElement e) { |
| 127 e.forEachLocalMember((Element element) => element.accept(this)); | 142 e.forEachLocalMember((Element element) => element.accept(this)); |
| 128 } | 143 } |
| 129 } | 144 } |
| 130 | 145 |
| 131 class ScriptOnlyFilter implements QueueFilter { | 146 class ScriptOnlyFilter implements QueueFilter { |
| 132 final Uri script; | 147 final Uri script; |
| 133 | 148 |
| 134 ScriptOnlyFilter(this.script); | 149 ScriptOnlyFilter(this.script); |
| 135 | 150 |
| 136 bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) => true; | 151 bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) => true; |
| 137 | 152 |
| 138 void processWorkItem(void f(WorkItem work), WorkItem work) { | 153 void processWorkItem(void f(WorkItem work), WorkItem work) { |
| 139 if (work.element.library.canonicalUri == script) { | 154 if (work.element.library.canonicalUri == script) { |
| 140 f(work); | 155 f(work); |
| 141 } | 156 } |
| 142 } | 157 } |
| 143 } | 158 } |
| 159 | |
| 160 class ScopeInformationVisitor extends ElementVisitor/* <void> */ { | |
| 161 // TODO(ahe): Include function paramters and local variables. | |
|
Johnni Winther
2014/07/14 10:35:36
'paramters' -> 'parameters'
ahe
2014/07/14 13:06:07
Done.
| |
| 162 | |
| 163 final Element element; | |
| 164 final int position; | |
| 165 final StringBuffer buffer = new StringBuffer(); | |
| 166 int indentationLevel = 0; | |
| 167 | |
| 168 ScopeInformationVisitor(this.element, this.position); | |
| 169 | |
| 170 String get indentation => ' ' * indentationLevel; | |
| 171 | |
| 172 StringBuffer get indented => buffer..write(indentation); | |
| 173 | |
| 174 void visitElement(Element e) { | |
| 175 serialize(e, omitEnclosing: false); | |
| 176 } | |
| 177 | |
| 178 void visitLibraryElement(LibraryElement e) { | |
| 179 bool isFirst = true; | |
| 180 serialize( | |
| 181 e, omitEnclosing: true, | |
| 182 name: relativize(Uri.base, e.canonicalUri, false), | |
| 183 serializeMembers: () { | |
| 184 // TODO(ahe): Include imported elements in libraries. | |
| 185 e.forEachLocalMember((Element member) { | |
| 186 if (!isFirst) { | |
| 187 buffer.write(','); | |
| 188 } | |
| 189 buffer.write('\n'); | |
| 190 indented; | |
| 191 serialize(member); | |
| 192 isFirst = false; | |
| 193 }); | |
| 194 }); | |
| 195 } | |
| 196 | |
| 197 void visitScopeContainerElement(ScopeContainerElement e) { | |
| 198 bool isFirst = true; | |
| 199 serialize(e, omitEnclosing: false, serializeMembers: () { | |
| 200 // TODO(ahe): Include inherited members in classes. | |
| 201 e.forEachLocalMember((Element member) { | |
| 202 if (!isFirst) { | |
| 203 buffer.write(','); | |
| 204 } | |
| 205 buffer.write('\n'); | |
| 206 indented; | |
| 207 serialize(member); | |
| 208 isFirst = false; | |
| 209 }); | |
| 210 }); | |
| 211 } | |
| 212 | |
| 213 void visitCompilationUnitElement(CompilationUnitElement e) { | |
| 214 e.enclosingElement.accept(this); | |
| 215 } | |
| 216 | |
| 217 void serialize( | |
| 218 Element element, | |
| 219 {bool omitEnclosing: true, | |
| 220 void serializeMembers(), | |
| 221 String name}) { | |
| 222 if (name == null) { | |
| 223 name = element.name; | |
| 224 } | |
| 225 buffer.write('{\n'); | |
| 226 indentationLevel++; | |
| 227 indented | |
| 228 ..write('"name": "') | |
| 229 ..write(name) | |
| 230 ..write('",\n'); | |
| 231 indented | |
| 232 ..write('"kind": "') | |
| 233 ..write(element.kind) | |
| 234 ..write('"'); | |
| 235 // TODO(ahe): Add a type/signature field. | |
| 236 if (serializeMembers != null) { | |
| 237 buffer.write(',\n'); | |
| 238 indented.write('"members": ['); | |
| 239 indentationLevel++; | |
| 240 serializeMembers(); | |
| 241 indentationLevel--; | |
| 242 buffer.write('\n'); | |
| 243 indented.write(']'); | |
| 244 } | |
| 245 if (!omitEnclosing) { | |
| 246 buffer.write(',\n'); | |
| 247 indented.write('"enclosing": '); | |
| 248 element.enclosingElement.accept(this); | |
| 249 } | |
| 250 indentationLevel--; | |
| 251 buffer.write('\n'); | |
| 252 indented.write('}'); | |
| 253 } | |
| 254 } | |
| OLD | NEW |