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.integration.analysis.domain; | |
6 | |
7 import 'dart:async'; | |
8 | |
9 import 'package:analysis_testing/reflective_tests.dart'; | |
10 import 'package:path/path.dart'; | |
11 import 'package:unittest/unittest.dart'; | |
12 | |
13 import 'integration_tests.dart'; | |
14 | |
15 @ReflectiveTestCase() | |
16 class AnalysisDomainIntegrationTest extends | |
17 AbstractAnalysisServerIntegrationTest { | |
18 test_getHover() { | |
19 String pathname = sourcePath('test.dart'); | |
20 String text = | |
21 r''' | |
22 library lib.test; | |
23 | |
24 List topLevelVar; | |
25 | |
26 /** | |
27 * Documentation for func | |
28 */ | |
29 void func(int param) { | |
30 num localVar = topLevelVar.length; | |
31 topLevelVar.length = param; | |
32 topLevelVar.add(localVar); | |
33 } | |
34 | |
35 main() { | |
36 func(35); | |
37 } | |
38 '''; | |
39 writeFile(pathname, text); | |
40 standardAnalysisSetup(); | |
41 | |
42 testHover(String target, int length, List<String> descriptionRegexps, String | |
43 kind, List<String> staticTypeRegexps, {bool isCore: false, String docReg
exp: | |
44 null, bool isLiteral: false, List<String> parameterRegexps: | |
45 null, propagatedType: null}) { | |
46 int offset = text.indexOf(target); | |
47 return sendAnalysisGetHover(pathname, offset).then((result) { | |
48 expect(result['hovers'], hasLength(1)); | |
49 var info = result['hovers'][0]; | |
50 expect(info['offset'], equals(offset)); | |
51 expect(info['length'], equals(length)); | |
52 if (isCore) { | |
53 expect(basename(info['containingLibraryPath']), equals('core.dart')); | |
54 expect(info['containingLibraryName'], equals('dart.core')); | |
55 } else if (isLiteral) { | |
56 expect(info['containingLibraryPath'], isNull); | |
57 expect(info['containingLibraryName'], isNull); | |
58 } else { | |
59 expect(info['containingLibraryPath'], equals(pathname)); | |
60 expect(info['containingLibraryName'], equals('lib.test')); | |
61 } | |
62 if (docRegexp == null) { | |
63 expect(info['dartdoc'], isNull); | |
64 } else { | |
65 expect(info['dartdoc'], matches(docRegexp)); | |
66 } | |
67 if (descriptionRegexps == null) { | |
68 expect(info['elementDescription'], isNull); | |
69 } else { | |
70 expect(info['elementDescription'], isString); | |
71 for (String descriptionRegexp in descriptionRegexps) { | |
72 expect(info['elementDescription'], matches(descriptionRegexp)); | |
73 } | |
74 } | |
75 expect(info['elementKind'], equals(kind)); | |
76 if (parameterRegexps == null) { | |
77 expect(info['parameter'], isNull); | |
78 } else { | |
79 expect(info['parameter'], isString); | |
80 for (String parameterRegexp in parameterRegexps) { | |
81 expect(info['parameter'], matches(parameterRegexp)); | |
82 } | |
83 } | |
84 expect(info['propagatedType'], equals(propagatedType)); | |
85 if (staticTypeRegexps == null) { | |
86 expect(info['staticType'], isNull); | |
87 } else { | |
88 expect(info['staticType'], isString); | |
89 for (String staticTypeRegexp in staticTypeRegexps) { | |
90 expect(info['staticType'], matches(staticTypeRegexp)); | |
91 } | |
92 } | |
93 }); | |
94 } | |
95 | |
96 // Note: analysis.getHover doesn't wait for analysis to complete--it simply | |
97 // returns the latest results that are available at the time that the | |
98 // request is made. So wait for analysis to finish before testing anything. | |
99 return analysisFinished.then((_) { | |
100 List<Future> tests = []; | |
101 tests.add(testHover('topLevelVar;', 11, ['List', 'topLevelVar'], | |
102 'top level variable', ['List'])); | |
103 tests.add(testHover('func(', 4, ['func', 'int', 'param'], 'function', | |
104 ['int', 'void'], docRegexp: 'Documentation for func')); | |
105 tests.add(testHover('int param', 3, ['int'], 'class', ['int'], isCore: | |
106 true, docRegexp: '.*')); | |
107 tests.add(testHover('param)', 5, ['int', 'param'], 'parameter', ['int'], | |
108 docRegexp: 'Documentation for func')); | |
109 tests.add(testHover('num localVar', 3, ['num'], 'class', ['num'], isCore: | |
110 true, docRegexp: '.*')); | |
111 tests.add(testHover('localVar =', 8, ['num', 'localVar'], | |
112 'local variable', ['num'], propagatedType: 'int')); | |
113 tests.add(testHover('topLevelVar.length;', 11, ['List', 'topLevelVar'], | |
114 'top level variable', ['List'])); | |
115 tests.add(testHover('length;', 6, ['get', 'length', 'int'], 'getter', | |
116 ['int'], isCore: true, docRegexp: '.*')); | |
117 tests.add(testHover('length =', 6, ['set', 'length', 'int'], 'setter', | |
118 ['int'], isCore: true, docRegexp: '.*')); | |
119 tests.add(testHover('param;', 5, ['int', 'param'], 'parameter', ['int'], | |
120 docRegexp: 'Documentation for func')); | |
121 tests.add(testHover('add(', 3, ['List', 'add'], 'method', null, isCore: | |
122 true, docRegexp: '.*')); | |
123 tests.add(testHover('localVar)', 8, ['num', 'localVar'], 'local variable', | |
124 ['num'], parameterRegexps: ['.*'], propagatedType: 'int')); | |
125 tests.add(testHover('func(35', 4, ['func', 'int', 'param'], 'function', | |
126 null, docRegexp: 'Documentation for func')); | |
127 tests.add(testHover('35', 2, null, null, ['int'], isLiteral: true, | |
128 parameterRegexps: ['int', 'param'])); | |
129 return Future.wait(tests); | |
130 }); | |
131 } | |
132 | |
133 test_getHover_noInfo() { | |
134 String pathname = sourcePath('test.dart'); | |
135 String text = r''' | |
136 main() { | |
137 // no code | |
138 } | |
139 '''; | |
140 writeFile(pathname, text); | |
141 standardAnalysisSetup(); | |
142 | |
143 // Note: analysis.getHover doesn't wait for analysis to complete--it simply | |
144 // returns the latest results that are available at the time that the | |
145 // request is made. So wait for analysis to finish before testing anything. | |
146 return analysisFinished.then((_) { | |
147 return sendAnalysisGetHover(pathname, text.indexOf('no code')).then( | |
148 (result) { | |
149 expect(result['hovers'], hasLength(0)); | |
150 }); | |
151 }); | |
152 } | |
153 | |
154 test_getErrors_before_analysis() { | |
155 return getErrorsTest(false); | |
156 } | |
157 | |
158 test_getErrors_after_analysis() { | |
159 return getErrorsTest(true); | |
160 } | |
161 | |
162 Future getErrorsTest(bool afterAnalysis) { | |
163 String pathname = sourcePath('test.dart'); | |
164 String text = r''' | |
165 main() { | |
166 var x // parse error: missing ';' | |
167 }'''; | |
168 writeFile(pathname, text); | |
169 standardAnalysisSetup(); | |
170 Future finishTest() { | |
171 return sendAnalysisGetErrors(pathname).then((result) { | |
172 expect(result['errors'], equals(currentAnalysisErrors[pathname])); | |
173 }); | |
174 } | |
175 if (afterAnalysis) { | |
176 return analysisFinished.then((_) => finishTest()); | |
177 } else { | |
178 return finishTest(); | |
179 } | |
180 } | |
181 | |
182 test_updateContent_content_only() { | |
183 return updateContentTest(false); | |
184 } | |
185 | |
186 test_updateContent_including_offset_and_lengths() { | |
187 return updateContentTest(true); | |
188 } | |
189 | |
190 Future updateContentTest(bool includeOffsetAndLengths) { | |
191 String pathname = sourcePath('test.dart'); | |
192 String goodText = r''' | |
193 main() { | |
194 print("Hello, world!"); | |
195 }'''; | |
196 String badText = goodText.replaceAll(';', ''); | |
197 writeFile(pathname, badText); | |
198 standardAnalysisSetup(); | |
199 return analysisFinished.then((_) { | |
200 // The contents on disk (badText) are missing a semicolon. | |
201 expect(currentAnalysisErrors[pathname], isNot(isEmpty)); | |
202 | |
203 if (includeOffsetAndLengths) { | |
204 // Before we send a ChangeContentOverlay directive we need to send an | |
205 // AddContentOverlay directive. So send that with badText. | |
206 return sendAnalysisUpdateContent({ | |
207 pathname: { | |
208 'type': 'add', | |
209 'content': badText | |
210 } | |
211 }).then((_) => analysisFinished); | |
212 } | |
213 }).then((_) { | |
214 if (includeOffsetAndLengths) { | |
215 return sendAnalysisUpdateContent({ | |
216 pathname: { | |
217 'type': 'change', | |
218 'offset': goodText.indexOf(';'), | |
219 'length': 0, | |
220 'replacement': ';' | |
221 } | |
222 }); | |
223 } else { | |
224 return sendAnalysisUpdateContent({ | |
225 pathname: { | |
226 'type': 'add', | |
227 'content': goodText | |
228 } | |
229 }); | |
230 } | |
231 }).then((result) => analysisFinished).then((_) { | |
232 // There should be no errors now because the contents on disk have been | |
233 // overriden with goodText. | |
234 expect(currentAnalysisErrors[pathname], isEmpty); | |
235 return sendAnalysisUpdateContent({ | |
236 pathname: { | |
237 'type': 'remove' | |
238 } | |
239 }); | |
240 }).then((result) => analysisFinished).then((_) { | |
241 // Now there should be errors again, because the contents on disk are no | |
242 // longer overridden. | |
243 expect(currentAnalysisErrors[pathname], isNot(isEmpty)); | |
244 }); | |
245 } | |
246 } | |
247 | |
248 main() { | |
249 runReflectiveTests(AnalysisDomainIntegrationTest); | |
250 } | |
OLD | NEW |