| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library test.domain.analysis.abstract; | |
| 6 | |
| 7 import 'dart:async'; | |
| 8 | |
| 9 import 'package:analysis_server/src/analysis_server.dart'; | |
| 10 import 'package:analysis_server/src/domain_analysis.dart'; | |
| 11 import 'package:analysis_server/src/constants.dart'; | |
| 12 import 'package:analysis_server/src/protocol.dart'; | |
| 13 import 'package:analysis_server/src/resource.dart'; | |
| 14 import 'package:analyzer/src/generated/source.dart'; | |
| 15 import 'package:unittest/unittest.dart'; | |
| 16 | |
| 17 import 'mocks.dart'; | |
| 18 | |
| 19 | |
| 20 main() { | |
| 21 } | |
| 22 | |
| 23 | |
| 24 /** | |
| 25 * An abstract base for all 'analysis' domain tests. | |
| 26 */ | |
| 27 class AbstractAnalysisTest { | |
| 28 MockServerChannel serverChannel; | |
| 29 MemoryResourceProvider resourceProvider; | |
| 30 AnalysisServer server; | |
| 31 AnalysisDomainHandler handler; | |
| 32 | |
| 33 Map<String, List<String>> analysisSubscriptions = {}; | |
| 34 | |
| 35 String projectPath = '/project'; | |
| 36 String testFile = '/project/bin/test.dart'; | |
| 37 String testCode; | |
| 38 | |
| 39 // Map<String, List<AnalysisError>> filesErrors = {}; | |
| 40 // Map<String, List<Map<String, Object>>> filesHighlights = {}; | |
| 41 // Map<String, List<Map<String, Object>>> filesNavigation = {}; | |
| 42 | |
| 43 | |
| 44 AbstractAnalysisTest() { | |
| 45 } | |
| 46 | |
| 47 void setUp() { | |
| 48 serverChannel = new MockServerChannel(); | |
| 49 resourceProvider = new MemoryResourceProvider(); | |
| 50 server = new AnalysisServer(serverChannel, resourceProvider); | |
| 51 handler = new AnalysisDomainHandler(server); | |
| 52 // listen for notifications | |
| 53 Stream<Notification> notificationStream = serverChannel.notificationControll
er.stream; | |
| 54 notificationStream.listen((Notification notification) { | |
| 55 processNotification(notification); | |
| 56 }); | |
| 57 // create an empty project | |
| 58 _createEmptyProject(); | |
| 59 } | |
| 60 | |
| 61 void addAnalysisSubscription(AnalysisService service, String file) { | |
| 62 // add file to subscription | |
| 63 var files = analysisSubscriptions[service.name]; | |
| 64 if (files == null) { | |
| 65 files = <String>[]; | |
| 66 analysisSubscriptions[service.name] = files; | |
| 67 } | |
| 68 files.add(file); | |
| 69 // set subscriptions | |
| 70 Request request = new Request('0', METHOD_SET_ANALYSIS_SUBSCRIPTIONS); | |
| 71 request.setParameter(SUBSCRIPTIONS, analysisSubscriptions); | |
| 72 handleSuccessfulRequest(request); | |
| 73 } | |
| 74 | |
| 75 void tearDown() { | |
| 76 server.done(); | |
| 77 handler = null; | |
| 78 server = null; | |
| 79 resourceProvider = null; | |
| 80 serverChannel = null; | |
| 81 } | |
| 82 | |
| 83 void processNotification(Notification notification) { | |
| 84 // if (notification.event == NOTIFICATION_ERRORS) { | |
| 85 // String file = notification.getParameter(FILE); | |
| 86 // List<Map<String, Object>> errorMaps = notification.getParameter(ERRORS); | |
| 87 // filesErrors[file] = errorMaps.map(jsonToAnalysisError).toList(); | |
| 88 // } | |
| 89 // if (notification.event == NOTIFICATION_HIGHLIGHTS) { | |
| 90 // String file = notification.getParameter(FILE); | |
| 91 // filesHighlights[file] = notification.getParameter(REGIONS); | |
| 92 // } | |
| 93 // if (notification.event == NOTIFICATION_NAVIGATION) { | |
| 94 // String file = notification.getParameter(FILE); | |
| 95 // filesNavigation[file] = notification.getParameter(REGIONS); | |
| 96 // } | |
| 97 } | |
| 98 | |
| 99 /** | |
| 100 * Returns a [Future] that completes when the [AnalysisServer] finishes | |
| 101 * all its scheduled tasks. | |
| 102 */ | |
| 103 Future waitForTasksFinished() { | |
| 104 return waitForServerOperationsPerformed(server); | |
| 105 } | |
| 106 | |
| 107 /** | |
| 108 * Returns the offset of [search] in [testCode]. | |
| 109 * Fails if not found. | |
| 110 */ | |
| 111 int findFileOffset(String path, String search) { | |
| 112 File file = resourceProvider.getResource(path) as File; | |
| 113 String code = file.createSource(UriKind.FILE_URI).contents.data; | |
| 114 int offset = code.indexOf(search); | |
| 115 expect(offset, isNot(-1), reason: '"$search" in\n$code'); | |
| 116 return offset; | |
| 117 } | |
| 118 | |
| 119 /** | |
| 120 * Returns the offset of [search] in [testCode]. | |
| 121 * Fails if not found. | |
| 122 */ | |
| 123 int findOffset(String search) { | |
| 124 int offset = testCode.indexOf(search); | |
| 125 expect(offset, isNot(-1)); | |
| 126 return offset; | |
| 127 } | |
| 128 | |
| 129 // /** | |
| 130 // * Returns [AnalysisError]s recorded for the given [file]. | |
| 131 // * May be empty, but not `null`. | |
| 132 // */ | |
| 133 // List<AnalysisError> getErrors(String file) { | |
| 134 // List<AnalysisError> errors = filesErrors[file]; | |
| 135 // if (errors != null) { | |
| 136 // return errors; | |
| 137 // } | |
| 138 // return <AnalysisError>[]; | |
| 139 // } | |
| 140 // | |
| 141 // /** | |
| 142 // * Returns highlights recorded for the given [file]. | |
| 143 // * May be empty, but not `null`. | |
| 144 // */ | |
| 145 // List<Map<String, Object>> getHighlights(String file) { | |
| 146 // List<Map<String, Object>> highlights = filesHighlights[file]; | |
| 147 // if (highlights != null) { | |
| 148 // return highlights; | |
| 149 // } | |
| 150 // return []; | |
| 151 // } | |
| 152 // | |
| 153 // /** | |
| 154 // * Returns navigation regions recorded for the given [file]. | |
| 155 // * May be empty, but not `null`. | |
| 156 // */ | |
| 157 // List<Map<String, Object>> getNavigation(String file) { | |
| 158 // List<Map<String, Object>> navigation = filesNavigation[file]; | |
| 159 // if (navigation != null) { | |
| 160 // return navigation; | |
| 161 // } | |
| 162 // return []; | |
| 163 // } | |
| 164 // | |
| 165 // /** | |
| 166 // * Returns [AnalysisError]s recorded for the [testFile]. | |
| 167 // * May be empty, but not `null`. | |
| 168 // */ | |
| 169 // List<AnalysisError> getTestErrors() { | |
| 170 // return getErrors(testFile); | |
| 171 // } | |
| 172 // | |
| 173 // /** | |
| 174 // * Returns highlights recorded for the given [testFile]. | |
| 175 // * May be empty, but not `null`. | |
| 176 // */ | |
| 177 // List<Map<String, Object>> getTestHighlights() { | |
| 178 // return getHighlights(testFile); | |
| 179 // } | |
| 180 // | |
| 181 // /** | |
| 182 // * Returns navigation information recorded for the given [testFile]. | |
| 183 // * May be empty, but not `null`. | |
| 184 // */ | |
| 185 // List<Map<String, Object>> getTestNavigation() { | |
| 186 // return getNavigation(testFile); | |
| 187 // } | |
| 188 | |
| 189 /** | |
| 190 * Creates an empty project `/project/`. | |
| 191 */ | |
| 192 void _createEmptyProject() { | |
| 193 resourceProvider.newFolder(projectPath); | |
| 194 Request request = new Request('0', METHOD_SET_ANALYSIS_ROOTS); | |
| 195 request.setParameter(INCLUDED, [projectPath]); | |
| 196 request.setParameter(EXCLUDED, []); | |
| 197 handleSuccessfulRequest(request); | |
| 198 } | |
| 199 | |
| 200 // /** | |
| 201 // * Creates a project with a single Dart file `/project/bin/test.dart` with | |
| 202 // * the given [code]. | |
| 203 // */ | |
| 204 // void createSingleFileProject(code) { | |
| 205 // this.testCode = _getCodeString(code); | |
| 206 // resourceProvider.newFolder('/project'); | |
| 207 // resourceProvider.newFile(testFile, testCode); | |
| 208 // Request request = new Request('0', METHOD_SET_ANALYSIS_ROOTS); | |
| 209 // request.setParameter(INCLUDED, ['/project']); | |
| 210 // request.setParameter(EXCLUDED, []); | |
| 211 // handleSuccessfulRequest(request); | |
| 212 // } | |
| 213 | |
| 214 String addFile(String path, String content) { | |
| 215 resourceProvider.newFile(path, content); | |
| 216 return path; | |
| 217 } | |
| 218 | |
| 219 String addTestFile(String content) { | |
| 220 addFile(testFile, content); | |
| 221 this.testCode = content; | |
| 222 return testFile; | |
| 223 } | |
| 224 | |
| 225 /** | |
| 226 * Validates that the given [request] is handled successfully. | |
| 227 */ | |
| 228 void handleSuccessfulRequest(Request request) { | |
| 229 Response response = handler.handleRequest(request); | |
| 230 expect(response, isResponseSuccess('0')); | |
| 231 } | |
| 232 | |
| 233 static String _getCodeString(code) { | |
| 234 if (code is List<String>) { | |
| 235 code = code.join('\n'); | |
| 236 } | |
| 237 return code as String; | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 | |
| 242 | |
| 243 class AnalysisError { | |
| 244 final String file; | |
| 245 final String errorCode; | |
| 246 final int offset; | |
| 247 final int length; | |
| 248 final String message; | |
| 249 final String correction; | |
| 250 AnalysisError(this.file, this.errorCode, this.offset, this.length, | |
| 251 this.message, this.correction); | |
| 252 | |
| 253 @override | |
| 254 String toString() { | |
| 255 return 'NotificationError(file=$file; errorCode=$errorCode; ' | |
| 256 'offset=$offset; length=$length; message=$message)'; | |
| 257 } | |
| 258 } | |
| 259 | |
| 260 | |
| 261 AnalysisError _jsonToAnalysisError(Map<String, Object> json) { | |
| 262 return new AnalysisError( | |
| 263 json['file'], | |
| 264 json['errorCode'], | |
| 265 json['offset'], | |
| 266 json['length'], | |
| 267 json['message'], | |
| 268 json['correction']); | |
| 269 } | |
| 270 | |
| 271 | |
| 272 int findIdentifierLength(String search) { | |
| 273 int length = 0; | |
| 274 while (length < search.length) { | |
| 275 int c = search.codeUnitAt(length); | |
| 276 if (!(c >= 'a'.codeUnitAt(0) && c <= 'z'.codeUnitAt(0) || | |
| 277 c >= 'A'.codeUnitAt(0) && c <= 'Z'.codeUnitAt(0) || | |
| 278 c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0))) { | |
| 279 break; | |
| 280 } | |
| 281 length++; | |
| 282 } | |
| 283 return length; | |
| 284 } | |
| OLD | NEW |