| // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| // Usage: Add the following to your .gclient file (found in the parent |
| // of the "dart" in a gclient checkout of the Dart repositor). |
| // |
| // hooks = [ |
| // { |
| // "pattern": ".", |
| // "action": [ |
| // "dart/sdk/bin/dart", |
| // "dart/sdk/lib/_internal/compiler/samples/darttags/darttags.dart", |
| // "dart/TAGS" |
| // ], |
| // }, |
| // ] |
| // |
| // Modify .emacs to contain: |
| // |
| // (setq tags-table-list |
| // '("DART_LOCATION/dart")) |
| // |
| // Where DART_LOCATION is the gclient directory where you found .gclient. |
| |
| import 'dart:io'; |
| |
| // TODO(ahe): Should be dart:mirrors. |
| import '../../implementation/mirrors/mirrors.dart'; |
| |
| import '../../../libraries.dart' |
| show LIBRARIES, LibraryInfo; |
| |
| import '../../implementation/mirrors/dart2js_mirror.dart' |
| show analyze, BackDoor; |
| |
| import '../../implementation/filenames.dart'; |
| import '../../implementation/source_file.dart'; |
| import '../../implementation/source_file_provider.dart'; |
| import '../../implementation/util/uri_extras.dart'; |
| |
| const DART2JS = '../../implementation/dart2js.dart'; |
| const DART2JS_MIRROR = '../../implementation/mirrors/dart2js_mirror.dart'; |
| const SDK_ROOT = '../../../../../'; |
| |
| bool isPublicDart2jsLibrary(String name) { |
| return !name.startsWith('_') && LIBRARIES[name].isDart2jsLibrary; |
| } |
| |
| var handler; |
| RandomAccessFile output; |
| Uri outputUri; |
| |
| main(List<String> arguments) { |
| handler = new FormattingDiagnosticHandler() |
| ..throwOnError = true; |
| |
| outputUri = |
| handler.provider.cwd.resolve(nativeToUriPath(arguments.first)); |
| output = new File(arguments.first).openSync(mode: FileMode.WRITE); |
| |
| Uri myLocation = |
| handler.provider.cwd.resolve(nativeToUriPath(Platform.script)); |
| |
| // Get the names of public dart2js libraries. |
| Iterable<String> names = LIBRARIES.keys.where(isPublicDart2jsLibrary); |
| |
| // Prepend "dart:" to the names. |
| List<Uri> uris = names.map((String name) => Uri.parse('dart:$name')).toList(); |
| |
| // Append dart2js itself. |
| uris.add(myLocation.resolve(DART2JS)); |
| uris.add(myLocation.resolve(DART2JS_MIRROR)); |
| |
| analyze(uris, myLocation.resolve(SDK_ROOT), null, handler.provider, handler) |
| .then(processMirrors); |
| } |
| |
| processMirrors(MirrorSystem mirrors) { |
| mirrors.libraries.forEach((_, LibraryMirror library) { |
| BackDoor.compilationUnitsOf(library).forEach(emitTagsForCompilationUnit); |
| }); |
| |
| output.closeSync(); |
| } |
| |
| /** |
| * From http://en.wikipedia.org/wiki/Ctags#Etags_2 |
| * |
| * A section starts with a two line header, one line containing a |
| * single <\x0c> character, followed by a line which consists of: |
| * |
| * {src_file},{size_of_tag_definition_data_in_bytes} |
| * |
| * The header is followed by tag definitions, one definition per line, |
| * with the format: |
| * |
| * {tag_definition_text}<\x7f>{tagname}<\x01>{line_number},{byte_offset} |
| */ |
| emitTagsForCompilationUnit(compilationUnit) { |
| // Certain variables in this method do not follow Dart naming |
| // conventions. This is because the format as written on Wikipedia |
| // looks very similar to Dart string interpolation that the author |
| // felt it would make sense to keep the names. |
| Uri uri = compilationUnit.uri; |
| var buffer = new StringBuffer(); |
| SourceFile file = handler.provider.sourceFiles['$uri']; |
| |
| compilationUnit.members.forEach((DeclarationMirror mirror) { |
| var tagname = mirror.simpleName; |
| var byte_offset = mirror.getBeginToken().charOffset; |
| var line_number = file.getLine(byte_offset) + 1; |
| |
| var lineStart = file.lineStarts[line_number - 1]; |
| // TODO(ahe): Most often an empty string. Try to see if we can |
| // get the position of the name token instead. |
| var tag_definition_text = file.slowText().substring(lineStart, byte_offset); |
| |
| // One definition. |
| buffer.write('${tag_definition_text}\x7f${tagname}' |
| '\x01${line_number},${byte_offset}\n'); |
| }); |
| |
| var tag_definition_data = '$buffer'; |
| var src_file = relativize(outputUri, uri, false); |
| var size_of_tag_definition_data_in_bytes = tag_definition_data.length; |
| |
| // The header. |
| output.writeStringSync( |
| '\x0c\n${src_file},${size_of_tag_definition_data_in_bytes}\n'); |
| output.writeStringSync(tag_definition_data); |
| } |