| 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 |