Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Unified Diff: pkg/analyzer_experimental/lib/src/services/runtime/coverage/coverage_impl.dart

Issue 45573002: Rename analyzer_experimental to analyzer. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Tweaks before publishing. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer_experimental/lib/src/services/runtime/coverage/coverage_impl.dart
diff --git a/pkg/analyzer_experimental/lib/src/services/runtime/coverage/coverage_impl.dart b/pkg/analyzer_experimental/lib/src/services/runtime/coverage/coverage_impl.dart
deleted file mode 100644
index 445aa8317da1d29826b66f4567fa178867c0acc7..0000000000000000000000000000000000000000
--- a/pkg/analyzer_experimental/lib/src/services/runtime/coverage/coverage_impl.dart
+++ /dev/null
@@ -1,341 +0,0 @@
-// 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.
-
-/// A library for code coverage support for Dart.
-library runtime.coverage.impl;
-
-import 'dart:async';
-import 'dart:collection' show SplayTreeMap;
-import 'dart:io';
-
-import 'package:path/path.dart' as pathos;
-
-import 'package:analyzer_experimental/src/generated/java_core.dart' show CharSequence;
-import 'package:analyzer_experimental/src/generated/scanner.dart' show CharSequenceReader, Scanner;
-import 'package:analyzer_experimental/src/generated/parser.dart' show Parser;
-import 'package:analyzer_experimental/src/generated/ast.dart';
-import 'package:analyzer_experimental/src/generated/engine.dart' show RecordingErrorListener;
-
-import '../log.dart' as log;
-import 'models.dart';
-
-/// Run the [targetPath] with code coverage rewriting.
-/// Redirects stdandard process streams.
-/// On process exit dumps coverage statistics into the [outPath].
-void runServerApplication(String targetPath, String outPath) {
- var targetFolder = pathos.dirname(targetPath);
- var targetName = pathos.basename(targetPath);
- var server = new CoverageServer(targetFolder, targetPath, outPath);
- server.start().then((port) {
- var options = new Options();
- var targetArgs = ['http://127.0.0.1:$port/$targetName'];
- var dartExecutable = options.executable;
- return Process.start(dartExecutable, targetArgs);
- }).then((process) {
- stdin.pipe(process.stdin);
- process.stdout.pipe(stdout);
- process.stderr.pipe(stderr);
- return process.exitCode;
- }).then(exit).catchError((e) {
- log.severe('Error starting $targetPath. $e');
- });
-}
-
-
-/// Abstract server to listen requests and serve files, may be rewriting them.
-abstract class RewriteServer {
- final String basePath;
- int port;
-
- RewriteServer(this.basePath);
-
- /// Runs the HTTP server on the ephemeral port and returns [Future] with it.
- Future<int> start() {
- return HttpServer.bind('127.0.0.1', 0).then((server) {
- port = server.port;
- log.info('RewriteServer is listening at: $port.');
- server.listen((request) {
- if (request.method == 'GET') {
- handleGetRequest(request);
- }
- if (request.method == 'POST') {
- handlePostRequest(request);
- }
- });
- return port;
- });
- }
-
- void handlePostRequest(HttpRequest request);
-
- void handleGetRequest(HttpRequest request) {
- var response = request.response;
- // Prepare path.
- var path = getFilePath(request.uri);
- log.info('[$path] Requested.');
- // May be serve using just path.
- {
- var content = rewritePathContent(path);
- if (content != null) {
- log.info('[$path] Request served by path.');
- response.write(content);
- response.close();
- return;
- }
- }
- // Serve from file.
- log.info('[$path] Serving file.');
- var file = new File(path);
- file.exists().then((found) {
- if (found) {
- // May be this files should be sent as is.
- if (!shouldRewriteFile(path)) {
- return sendFile(request, file);
- }
- // Rewrite content of the file.
- return file.readAsString().then((content) {
- log.finest('[$path] Done reading ${content.length} characters.');
- content = rewriteFileContent(path, content);
- log.fine('[$path] Rewritten.');
- response.write(content);
- return response.close();
- });
- } else {
- log.severe('[$path] File not found.');
- response.statusCode = HttpStatus.NOT_FOUND;
- return response.close();
- }
- }).catchError((e) {
- log.severe('[$path] $e.');
- response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
- return response.close();
- });
- }
-
- String getFilePath(Uri uri) {
- var path = uri.path;
- path = pathos.joinAll(uri.pathSegments);
- path = pathos.join(basePath, path);
- return pathos.normalize(path);
- }
-
- Future sendFile(HttpRequest request, File file) {
- file.fullPath().then((fullPath) {
- return file.openRead().pipe(request.response);
- });
- }
-
- bool shouldRewriteFile(String path);
-
- /// Subclasses implement this method to rewrite the provided [code] of the
- /// file with [path]. Returns some content or `null` if file content
- /// should be requested.
- String rewritePathContent(String path);
-
- /// Subclasses implement this method to rewrite the provided [code] of the
- /// file with [path].
- String rewriteFileContent(String path, String code);
-}
-
-
-/// Here `CCC` means 'code coverage configuration'.
-const TEST_UNIT_CCC = '''
-class __CCC extends __cc_ut.Configuration {
- void onDone(bool success) {
- __cc.postStatistics();
- super.onDone(success);
- }
-}''';
-
-const TEST_UNIT_CCC_SET = '__cc_ut.unittestConfiguration = new __CCC();';
-
-
-/// Server that rewrites Dart code so that it reports execution of statements
-/// and other nodes.
-class CoverageServer extends RewriteServer {
- final appInfo = new AppInfo();
- final String targetPath;
- final String outPath;
-
- CoverageServer(String basePath, this.targetPath, this.outPath)
- : super(basePath);
-
- void handlePostRequest(HttpRequest request) {
- var id = 0;
- var executedIds = new Set<int>();
- request.listen((data) {
- log.fine('Received statistics, ${data.length} bytes.');
- while (true) {
- var listIndex = id ~/ 8;
- if (listIndex >= data.length) break;
- var bitIndex = id % 8;
- if ((data[listIndex] & (1 << bitIndex)) != 0) {
- executedIds.add(id);
- }
- id++;
- }
- }).onDone(() {
- log.fine('Received all statistics.');
- var buffer = new StringBuffer();
- appInfo.write(buffer, executedIds);
- new File(outPath).writeAsString(buffer.toString()).then((_) {
- return request.response.close();
- }).catchError((e) {
- log.severe('Error in receiving statistics $e.');
- return request.response.close();
- });
- });
- }
-
- String rewritePathContent(String path) {
- if (path.endsWith('__coverage_lib.dart')) {
- String implPath = pathos.joinAll([
- pathos.dirname(Platform.script),
- '..', 'lib', 'src', 'services', 'runtime', 'coverage',
- 'coverage_lib.dart']);
- var content = new File(implPath).readAsStringSync();
- return content.replaceAll('0; // replaced during rewrite', '$port;');
- }
- return null;
- }
-
- bool shouldRewriteFile(String path) {
- if (pathos.extension(path).toLowerCase() != '.dart') return false;
- // Rewrite target itself, only to send statistics.
- if (path == targetPath) {
- return true;
- }
- // TODO(scheglov) use configuration
- return path.contains('/packages/analyzer_experimental/');
- }
-
- String rewriteFileContent(String path, String code) {
- var unit = _parseCode(code);
- log.finest('[$path] Parsed.');
- var injector = new CodeInjector(code);
- // Inject imports.
- var directives = unit.directives;
- if (directives.isNotEmpty && directives[0] is LibraryDirective) {
- injector.inject(directives[0].end,
- 'import "package:unittest/unittest.dart" as __cc_ut;'
- 'import "http://127.0.0.1:$port/__coverage_lib.dart" as __cc;');
- }
- // Inject statistics sender.
- var isTargetScript = path == targetPath;
- if (isTargetScript) {
- for (var node in unit.declarations) {
- if (node is FunctionDeclaration) {
- var body = node.functionExpression.body;
- if (node.name.name == 'main' && body is BlockFunctionBody) {
- injector.inject(node.offset, TEST_UNIT_CCC);
- injector.inject(body.offset + 1, TEST_UNIT_CCC_SET);
- }
- }
- }
- }
- // Inject touch() invocations.
- if (!isTargetScript) {
- appInfo.enterUnit(path, code);
- unit.accept(new InsertTouchInvocationsVisitor(appInfo, injector));
- }
- // Done.
- return injector.getResult();
- }
-
- CompilationUnit _parseCode(String code) {
- var source = null;
- var errorListener = new RecordingErrorListener();
- var parser = new Parser(source, errorListener);
- var reader = new CharSequenceReader(new CharSequence(code));
- var scanner = new Scanner(null, reader, errorListener);
- var token = scanner.tokenize();
- return parser.parseCompilationUnit(token);
- }
-}
-
-
-/// The visitor that inserts `touch` method invocations.
-class InsertTouchInvocationsVisitor extends GeneralizingASTVisitor {
- final AppInfo appInfo;
- final CodeInjector injector;
-
- InsertTouchInvocationsVisitor(this.appInfo, this.injector);
-
- visitClassDeclaration(ClassDeclaration node) {
- appInfo.enter('class', node.name.name);
- super.visitClassDeclaration(node);
- appInfo.leave();
- }
-
- visitConstructorDeclaration(ConstructorDeclaration node) {
- var className = (node.parent as ClassDeclaration).name.name;
- var constructorName;
- if (node.name == null) {
- constructorName = className;
- } else {
- constructorName = className + '.' + node.name.name;
- }
- appInfo.enter('constructor', constructorName);
- super.visitConstructorDeclaration(node);
- appInfo.leave();
- }
-
- visitMethodDeclaration(MethodDeclaration node) {
- if (node.isAbstract) {
- super.visitMethodDeclaration(node);
- } else {
- var kind;
- if (node.isGetter) {
- kind = 'getter';
- } else if (node.isSetter) {
- kind = 'setter';
- } else {
- kind = 'method';
- }
- appInfo.enter(kind, node.name.name);
- super.visitMethodDeclaration(node);
- appInfo.leave();
- }
- }
-
- visitStatement(Statement node) {
- insertTouch(node);
- super.visitStatement(node);
- }
-
- void insertTouch(Statement node) {
- if (node is Block) return;
- if (node.parent is LabeledStatement) return;
- if (node.parent is! Block) return;
- // Inject 'touch' invocation.
- var offset = node.offset;
- var id = appInfo.addNode(node);
- injector.inject(offset, '__cc.touch($id);');
- }
-}
-
-
-/// Helper for injecting fragments into some existing code.
-class CodeInjector {
- final String _code;
- final offsetFragmentMap = new SplayTreeMap<int, String>();
-
- CodeInjector(this._code);
-
- void inject(int offset, String fragment) {
- offsetFragmentMap[offset] = fragment;
- }
-
- String getResult() {
- var sb = new StringBuffer();
- var lastOffset = 0;
- offsetFragmentMap.forEach((offset, fragment) {
- sb.write(_code.substring(lastOffset, offset));
- sb.write(fragment);
- lastOffset = offset;
- });
- sb.write(_code.substring(lastOffset, _code.length));
- return sb.toString();
- }
-}

Powered by Google App Engine
This is Rietveld 408576698