| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 // Usage: Add the following to your .gclient file (found in the parent | |
| 6 // of the "dart" in a gclient checkout of the Dart repositor). | |
| 7 // | |
| 8 // hooks = [ | |
| 9 // { | |
| 10 // "pattern": ".", | |
| 11 // "action": [ | |
| 12 // "dart/sdk/bin/dart", | |
| 13 // "dart/sdk/lib/_internal/compiler/samples/darttags/darttags.dart", | |
| 14 // "dart/TAGS" | |
| 15 // ], | |
| 16 // }, | |
| 17 // ] | |
| 18 // | |
| 19 // Modify .emacs to contain: | |
| 20 // | |
| 21 // (setq tags-table-list | |
| 22 // '("DART_LOCATION/dart")) | |
| 23 // | |
| 24 // Where DART_LOCATION is the gclient directory where you found .gclient. | |
| 25 | |
| 26 import 'dart:io'; | |
| 27 | |
| 28 import 'dart:mirrors'; | |
| 29 | |
| 30 import '../../../libraries.dart' | |
| 31 show LIBRARIES, LibraryInfo; | |
| 32 | |
| 33 import '../../implementation/mirrors/analyze.dart' | |
| 34 show analyze; | |
| 35 import '../../implementation/mirrors/dart2js_mirrors.dart' | |
| 36 show BackDoor; | |
| 37 import '../../implementation/mirrors/mirrors_util.dart' show nameOf; | |
| 38 | |
| 39 import '../../implementation/filenames.dart'; | |
| 40 import '../../implementation/source_file.dart'; | |
| 41 import '../../implementation/source_file_provider.dart'; | |
| 42 import '../../implementation/util/uri_extras.dart'; | |
| 43 | |
| 44 const DART2JS = '../../implementation/dart2js.dart'; | |
| 45 const DART2JS_MIRROR = '../../implementation/mirrors/dart2js_mirrors.dart'; | |
| 46 const SDK_ROOT = '../../../../../'; | |
| 47 | |
| 48 bool isPublicDart2jsLibrary(String name) { | |
| 49 return !name.startsWith('_') && LIBRARIES[name].isDart2jsLibrary; | |
| 50 } | |
| 51 | |
| 52 var handler; | |
| 53 RandomAccessFile output; | |
| 54 Uri outputUri; | |
| 55 | |
| 56 main(List<String> arguments) { | |
| 57 handler = new FormattingDiagnosticHandler() | |
| 58 ..throwOnError = true; | |
| 59 | |
| 60 outputUri = | |
| 61 handler.provider.cwd.resolve(nativeToUriPath(arguments.first)); | |
| 62 output = new File(arguments.first).openSync(mode: FileMode.WRITE); | |
| 63 | |
| 64 Uri myLocation = | |
| 65 handler.provider.cwd.resolveUri(Platform.script); | |
| 66 | |
| 67 // Get the names of public dart2js libraries. | |
| 68 Iterable<String> names = LIBRARIES.keys.where(isPublicDart2jsLibrary); | |
| 69 | |
| 70 // Prepend "dart:" to the names. | |
| 71 List<Uri> uris = names.map((String name) => Uri.parse('dart:$name')).toList(); | |
| 72 | |
| 73 // Append dart2js itself. | |
| 74 uris.add(myLocation.resolve(DART2JS)); | |
| 75 uris.add(myLocation.resolve(DART2JS_MIRROR)); | |
| 76 | |
| 77 analyze(uris, myLocation.resolve(SDK_ROOT), null, handler.provider, handler) | |
| 78 .then(processMirrors); | |
| 79 } | |
| 80 | |
| 81 processMirrors(MirrorSystem mirrors) { | |
| 82 mirrors.libraries.forEach((_, LibraryMirror library) { | |
| 83 BackDoor.compilationUnitsOf(library).forEach(emitTagsForCompilationUnit); | |
| 84 }); | |
| 85 | |
| 86 output.closeSync(); | |
| 87 } | |
| 88 | |
| 89 /** | |
| 90 * From http://en.wikipedia.org/wiki/Ctags#Etags_2 | |
| 91 * | |
| 92 * A section starts with a two line header, one line containing a | |
| 93 * single <\x0c> character, followed by a line which consists of: | |
| 94 * | |
| 95 * {src_file},{size_of_tag_definition_data_in_bytes} | |
| 96 * | |
| 97 * The header is followed by tag definitions, one definition per line, | |
| 98 * with the format: | |
| 99 * | |
| 100 * {tag_definition_text}<\x7f>{tagname}<\x01>{line_number},{byte_offset} | |
| 101 */ | |
| 102 emitTagsForCompilationUnit(compilationUnit) { | |
| 103 // Certain variables in this method do not follow Dart naming | |
| 104 // conventions. This is because the format as written on Wikipedia | |
| 105 // looks very similar to Dart string interpolation that the author | |
| 106 // felt it would make sense to keep the names. | |
| 107 Uri uri = compilationUnit.uri; | |
| 108 var buffer = new StringBuffer(); | |
| 109 SourceFile file = handler.provider.sourceFiles['$uri']; | |
| 110 String src_file = relativize(outputUri, uri, false); | |
| 111 | |
| 112 compilationUnit.declarations.forEach((_, DeclarationMirror mirror) { | |
| 113 Definition definition = new Definition.from(mirror, file); | |
| 114 String name = nameOf(mirror); | |
| 115 definition.writeOn(buffer, name); | |
| 116 | |
| 117 if (mirror is ClassMirror) { | |
| 118 emitTagsForClass(mirror, file, buffer); | |
| 119 } | |
| 120 }); | |
| 121 | |
| 122 var tag_definition_data = '$buffer'; | |
| 123 var size_of_tag_definition_data_in_bytes = tag_definition_data.length; | |
| 124 | |
| 125 // The header. | |
| 126 output.writeStringSync( | |
| 127 '\x0c\n${src_file},${size_of_tag_definition_data_in_bytes}\n'); | |
| 128 output.writeStringSync(tag_definition_data); | |
| 129 } | |
| 130 | |
| 131 void emitTagsForClass(ClassMirror cls, SourceFile file, StringBuffer buffer) { | |
| 132 String className = nameOf(cls); | |
| 133 | |
| 134 cls.declarations.forEach((_, DeclarationMirror mirror) { | |
| 135 Definition definition = new Definition.from(mirror, file); | |
| 136 String name = nameOf(mirror); | |
| 137 if (mirror is MethodMirror && mirror.isConstructor) { | |
| 138 if (name == '') { | |
| 139 name = className; | |
| 140 definition.writeOn(buffer, 'new $className'); | |
| 141 } else { | |
| 142 definition.writeOn(buffer, 'new $className.$name'); | |
| 143 } | |
| 144 } else { | |
| 145 definition.writeOn(buffer, '$className.$name'); | |
| 146 } | |
| 147 definition.writeOn(buffer, name); | |
| 148 }); | |
| 149 } | |
| 150 | |
| 151 class Definition { | |
| 152 final int byte_offset; | |
| 153 final int line_number; | |
| 154 final String tag_definition_text; | |
| 155 | |
| 156 Definition(this.byte_offset, this.line_number, this.tag_definition_text); | |
| 157 | |
| 158 factory Definition.from(DeclarationMirror mirror, SourceFile file) { | |
| 159 var location = mirror.location; | |
| 160 int byte_offset = location.offset; | |
| 161 int line_number = file.getLine(byte_offset) + 1; | |
| 162 | |
| 163 int lineStart = file.lineStarts[line_number - 1]; | |
| 164 | |
| 165 int lineEnd = file.lineStarts.length > line_number | |
| 166 // Subract 1 to remove trailing newline. | |
| 167 ? file.lineStarts[line_number] - 1 | |
| 168 : null; | |
| 169 String tag_definition_text = file.slowText().substring(lineStart, lineEnd); | |
| 170 | |
| 171 return new Definition(byte_offset, line_number, tag_definition_text); | |
| 172 } | |
| 173 | |
| 174 void writeOn(StringBuffer buffer, String tagname) { | |
| 175 buffer.write( | |
| 176 '${tag_definition_text}\x7f${tagname}' | |
| 177 '\x01${line_number},${byte_offset}\n'); | |
| 178 } | |
| 179 } | |
| OLD | NEW |