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