| Index: pkg/analysis_server/test/analysis_abstract_test.dart
|
| diff --git a/pkg/analysis_server/test/analysis_abstract_test.dart b/pkg/analysis_server/test/analysis_abstract_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2ea2e1dc6c31bac1dcbdaae4644d29021b5066f1
|
| --- /dev/null
|
| +++ b/pkg/analysis_server/test/analysis_abstract_test.dart
|
| @@ -0,0 +1,280 @@
|
| +// Copyright (c) 2014, 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.
|
| +
|
| +library test.domain.analysis.abstract;
|
| +
|
| +import 'dart:async';
|
| +
|
| +import 'package:analysis_server/src/analysis_server.dart';
|
| +import 'package:analysis_server/src/domain_analysis.dart';
|
| +import 'package:analysis_server/src/constants.dart';
|
| +import 'package:analysis_server/src/protocol.dart';
|
| +import 'package:analysis_server/src/resource.dart';
|
| +import 'package:analyzer/src/generated/source.dart';
|
| +import 'package:unittest/unittest.dart';
|
| +
|
| +import 'mocks.dart';
|
| +
|
| +
|
| +/**
|
| + * An abstract base for all 'analysis' domain tests.
|
| + */
|
| +class AbstractAnalysisTest {
|
| + MockServerChannel serverChannel;
|
| + MemoryResourceProvider resourceProvider;
|
| + AnalysisServer server;
|
| + AnalysisDomainHandler handler;
|
| +
|
| + Map<String, List<String>> analysisSubscriptions = {};
|
| +
|
| + String projectPath = '/project';
|
| + String testFile = '/project/bin/test.dart';
|
| + String testCode;
|
| +
|
| +// Map<String, List<AnalysisError>> filesErrors = {};
|
| +// Map<String, List<Map<String, Object>>> filesHighlights = {};
|
| +// Map<String, List<Map<String, Object>>> filesNavigation = {};
|
| +
|
| +
|
| + AbstractAnalysisTest() {
|
| + }
|
| +
|
| + void setUp() {
|
| + serverChannel = new MockServerChannel();
|
| + resourceProvider = new MemoryResourceProvider();
|
| + server = new AnalysisServer(serverChannel, resourceProvider);
|
| + handler = new AnalysisDomainHandler(server);
|
| + // listen for notifications
|
| + Stream<Notification> notificationStream = serverChannel.notificationController.stream;
|
| + notificationStream.listen((Notification notification) {
|
| + processNotification(notification);
|
| + });
|
| + // create an empty project
|
| + _createEmptyProject();
|
| + }
|
| +
|
| + void addAnalysisSubscription(AnalysisService service, String file) {
|
| + // add file to subscription
|
| + var files = analysisSubscriptions[service.name];
|
| + if (files == null) {
|
| + files = <String>[];
|
| + analysisSubscriptions[service.name] = files;
|
| + }
|
| + files.add(file);
|
| + // set subscriptions
|
| + Request request = new Request('0', METHOD_SET_ANALYSIS_SUBSCRIPTIONS);
|
| + request.setParameter(SUBSCRIPTIONS, analysisSubscriptions);
|
| + handleSuccessfulRequest(request);
|
| + }
|
| +
|
| + void tearDown() {
|
| + server.done();
|
| + handler = null;
|
| + server = null;
|
| + resourceProvider = null;
|
| + serverChannel = null;
|
| + }
|
| +
|
| + void processNotification(Notification notification) {
|
| +// if (notification.event == NOTIFICATION_ERRORS) {
|
| +// String file = notification.getParameter(FILE);
|
| +// List<Map<String, Object>> errorMaps = notification.getParameter(ERRORS);
|
| +// filesErrors[file] = errorMaps.map(jsonToAnalysisError).toList();
|
| +// }
|
| +// if (notification.event == NOTIFICATION_HIGHLIGHTS) {
|
| +// String file = notification.getParameter(FILE);
|
| +// filesHighlights[file] = notification.getParameter(REGIONS);
|
| +// }
|
| +// if (notification.event == NOTIFICATION_NAVIGATION) {
|
| +// String file = notification.getParameter(FILE);
|
| +// filesNavigation[file] = notification.getParameter(REGIONS);
|
| +// }
|
| + }
|
| +
|
| + /**
|
| + * Returns a [Future] that completes when the [AnalysisServer] finishes
|
| + * all its scheduled tasks.
|
| + */
|
| + Future waitForTasksFinished() {
|
| + return waitForServerOperationsPerformed(server);
|
| + }
|
| +
|
| + /**
|
| + * Returns the offset of [search] in [testCode].
|
| + * Fails if not found.
|
| + */
|
| + int findFileOffset(String path, String search) {
|
| + File file = resourceProvider.getResource(path) as File;
|
| + String code = file.createSource(UriKind.FILE_URI).contents.data;
|
| + int offset = code.indexOf(search);
|
| + expect(offset, isNot(-1), reason: '"$search" in\n$code');
|
| + return offset;
|
| + }
|
| +
|
| + /**
|
| + * Returns the offset of [search] in [testCode].
|
| + * Fails if not found.
|
| + */
|
| + int findOffset(String search) {
|
| + int offset = testCode.indexOf(search);
|
| + expect(offset, isNot(-1));
|
| + return offset;
|
| + }
|
| +
|
| +// /**
|
| +// * Returns [AnalysisError]s recorded for the given [file].
|
| +// * May be empty, but not `null`.
|
| +// */
|
| +// List<AnalysisError> getErrors(String file) {
|
| +// List<AnalysisError> errors = filesErrors[file];
|
| +// if (errors != null) {
|
| +// return errors;
|
| +// }
|
| +// return <AnalysisError>[];
|
| +// }
|
| +//
|
| +// /**
|
| +// * Returns highlights recorded for the given [file].
|
| +// * May be empty, but not `null`.
|
| +// */
|
| +// List<Map<String, Object>> getHighlights(String file) {
|
| +// List<Map<String, Object>> highlights = filesHighlights[file];
|
| +// if (highlights != null) {
|
| +// return highlights;
|
| +// }
|
| +// return [];
|
| +// }
|
| +//
|
| +// /**
|
| +// * Returns navigation regions recorded for the given [file].
|
| +// * May be empty, but not `null`.
|
| +// */
|
| +// List<Map<String, Object>> getNavigation(String file) {
|
| +// List<Map<String, Object>> navigation = filesNavigation[file];
|
| +// if (navigation != null) {
|
| +// return navigation;
|
| +// }
|
| +// return [];
|
| +// }
|
| +//
|
| +// /**
|
| +// * Returns [AnalysisError]s recorded for the [testFile].
|
| +// * May be empty, but not `null`.
|
| +// */
|
| +// List<AnalysisError> getTestErrors() {
|
| +// return getErrors(testFile);
|
| +// }
|
| +//
|
| +// /**
|
| +// * Returns highlights recorded for the given [testFile].
|
| +// * May be empty, but not `null`.
|
| +// */
|
| +// List<Map<String, Object>> getTestHighlights() {
|
| +// return getHighlights(testFile);
|
| +// }
|
| +//
|
| +// /**
|
| +// * Returns navigation information recorded for the given [testFile].
|
| +// * May be empty, but not `null`.
|
| +// */
|
| +// List<Map<String, Object>> getTestNavigation() {
|
| +// return getNavigation(testFile);
|
| +// }
|
| +
|
| + /**
|
| + * Creates an empty project `/project/`.
|
| + */
|
| + void _createEmptyProject() {
|
| + resourceProvider.newFolder(projectPath);
|
| + Request request = new Request('0', METHOD_SET_ANALYSIS_ROOTS);
|
| + request.setParameter(INCLUDED, [projectPath]);
|
| + request.setParameter(EXCLUDED, []);
|
| + handleSuccessfulRequest(request);
|
| + }
|
| +
|
| +// /**
|
| +// * Creates a project with a single Dart file `/project/bin/test.dart` with
|
| +// * the given [code].
|
| +// */
|
| +// void createSingleFileProject(code) {
|
| +// this.testCode = _getCodeString(code);
|
| +// resourceProvider.newFolder('/project');
|
| +// resourceProvider.newFile(testFile, testCode);
|
| +// Request request = new Request('0', METHOD_SET_ANALYSIS_ROOTS);
|
| +// request.setParameter(INCLUDED, ['/project']);
|
| +// request.setParameter(EXCLUDED, []);
|
| +// handleSuccessfulRequest(request);
|
| +// }
|
| +
|
| + String addFile(String path, String content) {
|
| + resourceProvider.newFile(path, content);
|
| + return path;
|
| + }
|
| +
|
| + String addTestFile(String content) {
|
| + addFile(testFile, content);
|
| + this.testCode = content;
|
| + return testFile;
|
| + }
|
| +
|
| + /**
|
| + * Validates that the given [request] is handled successfully.
|
| + */
|
| + void handleSuccessfulRequest(Request request) {
|
| + Response response = handler.handleRequest(request);
|
| + expect(response, isResponseSuccess('0'));
|
| + }
|
| +
|
| + static String _getCodeString(code) {
|
| + if (code is List<String>) {
|
| + code = code.join('\n');
|
| + }
|
| + return code as String;
|
| + }
|
| +}
|
| +
|
| +
|
| +
|
| +class AnalysisError {
|
| + final String file;
|
| + final String errorCode;
|
| + final int offset;
|
| + final int length;
|
| + final String message;
|
| + final String correction;
|
| + AnalysisError(this.file, this.errorCode, this.offset, this.length,
|
| + this.message, this.correction);
|
| +
|
| + @override
|
| + String toString() {
|
| + return 'NotificationError(file=$file; errorCode=$errorCode; '
|
| + 'offset=$offset; length=$length; message=$message)';
|
| + }
|
| +}
|
| +
|
| +
|
| +AnalysisError _jsonToAnalysisError(Map<String, Object> json) {
|
| + return new AnalysisError(
|
| + json['file'],
|
| + json['errorCode'],
|
| + json['offset'],
|
| + json['length'],
|
| + json['message'],
|
| + json['correction']);
|
| +}
|
| +
|
| +
|
| +int findIdentifierLength(String search) {
|
| + int length = 0;
|
| + while (length < search.length) {
|
| + int c = search.codeUnitAt(length);
|
| + if (!(c >= 'a'.codeUnitAt(0) && c <= 'z'.codeUnitAt(0) ||
|
| + c >= 'A'.codeUnitAt(0) && c <= 'Z'.codeUnitAt(0) ||
|
| + c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0))) {
|
| + break;
|
| + }
|
| + length++;
|
| + }
|
| + return length;
|
| +}
|
|
|