| // 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. | |
| import 'dart:async'; | |
| import 'package:analysis_server/protocol/protocol_generated.dart'; | |
| import 'package:path/path.dart' as path; | |
| import 'package:test/test.dart'; | |
| import 'package:test_reflective_loader/test_reflective_loader.dart'; | |
| import '../support/integration_tests.dart'; | |
| main() { | |
| defineReflectiveSuite(() { | |
| defineReflectiveTests(AnalysisGetHoverIntegrationTest); | |
| defineReflectiveTests(AnalysisGetHoverIntegrationTest_UseCFE); | |
| }); | |
| } | |
| @reflectiveTest | |
| class AnalysisGetHoverIntegrationTest | |
| extends AbstractAnalysisServerIntegrationTest { | |
| /** | |
| * Pathname of the file containing Dart code. | |
| */ | |
| String pathname; | |
| /** | |
| * Dart code under test. | |
| */ | |
| final String text = r''' | |
| library lib.test; | |
| List topLevelVar; | |
| /** | |
| * Documentation for func | |
| */ | |
| void func(int param) { | |
| num localVar = topLevelVar.length; | |
| topLevelVar.length = param; | |
| topLevelVar.add(localVar); | |
| } | |
| main() { | |
| // comment | |
| func(35); | |
| } | |
| '''; | |
| /** | |
| * Check that a getHover request on the substring [target] produces a result | |
| * which has length [length], has an elementDescription matching every | |
| * regexp in [descriptionRegexps], has a kind of [kind], and has a staticType | |
| * matching [staticTypeRegexps]. | |
| * | |
| * [isCore] means the hover info should indicate that the element is defined | |
| * in dart.core. [docRegexp], if specified, should match the documentation | |
| * string of the element. [isLiteral] means the hover should indicate a | |
| * literal value. [parameterRegexps] means is a set of regexps which should | |
| * match the hover parameters. [propagatedType], if specified, is the | |
| * expected propagated type of the element. | |
| */ | |
| checkHover(String target, int length, List<String> descriptionRegexps, | |
| String kind, List<String> staticTypeRegexps, | |
| {bool isLocal: false, | |
| bool isCore: false, | |
| String docRegexp: null, | |
| bool isLiteral: false, | |
| List<String> parameterRegexps: null, | |
| propagatedType: null}) { | |
| int offset = text.indexOf(target); | |
| return sendAnalysisGetHover(pathname, offset).then((result) { | |
| expect(result.hovers, hasLength(1)); | |
| HoverInformation info = result.hovers[0]; | |
| expect(info.offset, equals(offset)); | |
| expect(info.length, equals(length)); | |
| if (isCore) { | |
| expect(path.basename(info.containingLibraryPath), equals('core.dart')); | |
| expect(info.containingLibraryName, equals('dart.core')); | |
| } else if (isLocal || isLiteral) { | |
| expect(info.containingLibraryPath, isNull); | |
| expect(info.containingLibraryName, isNull); | |
| } else { | |
| expect(info.containingLibraryPath, equals(pathname)); | |
| expect(info.containingLibraryName, equals('lib.test')); | |
| } | |
| if (docRegexp == null) { | |
| expect(info.dartdoc, isNull); | |
| } else { | |
| expect(info.dartdoc, matches(docRegexp)); | |
| } | |
| if (descriptionRegexps == null) { | |
| expect(info.elementDescription, isNull); | |
| } else { | |
| expect(info.elementDescription, isString); | |
| for (String descriptionRegexp in descriptionRegexps) { | |
| expect(info.elementDescription, matches(descriptionRegexp)); | |
| } | |
| } | |
| expect(info.elementKind, equals(kind)); | |
| if (parameterRegexps == null) { | |
| expect(info.parameter, isNull); | |
| } else { | |
| expect(info.parameter, isString); | |
| for (String parameterRegexp in parameterRegexps) { | |
| expect(info.parameter, matches(parameterRegexp)); | |
| } | |
| } | |
| if (staticTypeRegexps == null) { | |
| expect(info.staticType, isNull); | |
| } else { | |
| expect(info.staticType, isString); | |
| for (String staticTypeRegexp in staticTypeRegexps) { | |
| expect(info.staticType, matches(staticTypeRegexp)); | |
| } | |
| } | |
| }); | |
| } | |
| /** | |
| * Check that a getHover request on the substring [target] produces no | |
| * results. | |
| */ | |
| Future checkNoHover(String target) { | |
| int offset = text.indexOf(target); | |
| return sendAnalysisGetHover(pathname, offset).then((result) { | |
| expect(result.hovers, hasLength(0)); | |
| }); | |
| } | |
| setUp() { | |
| return super.setUp().then((_) { | |
| pathname = sourcePath('test.dart'); | |
| }); | |
| } | |
| test_getHover() { | |
| writeFile(pathname, text); | |
| standardAnalysisSetup(); | |
| // Note: analysis.getHover doesn't wait for analysis to complete--it simply | |
| // returns the latest results that are available at the time that the | |
| // request is made. So wait for analysis to finish before testing anything. | |
| return analysisFinished.then((_) { | |
| List<Future> tests = []; | |
| tests.add(checkHover('topLevelVar;', 11, ['List', 'topLevelVar'], | |
| 'top level variable', ['List'])); | |
| tests.add(checkHover( | |
| 'func(', 4, ['func', 'int', 'param'], 'function', null, | |
| docRegexp: 'Documentation for func')); | |
| tests.add(checkHover('int param', 3, ['int'], 'class', null, | |
| isCore: true, docRegexp: '.*')); | |
| tests.add(checkHover('param)', 5, ['int', 'param'], 'parameter', ['int'], | |
| isLocal: true, docRegexp: 'Documentation for func')); | |
| tests.add(checkHover('num localVar', 3, ['num'], 'class', null, | |
| isCore: true, docRegexp: '.*')); | |
| tests.add(checkHover( | |
| 'localVar =', 8, ['num', 'localVar'], 'local variable', ['num'], | |
| isLocal: true, propagatedType: 'int')); | |
| tests.add(checkHover('topLevelVar.length;', 11, ['List', 'topLevelVar'], | |
| 'top level variable', ['List'])); | |
| tests.add(checkHover( | |
| 'length;', 6, ['get', 'length', 'int'], 'getter', null, | |
| isCore: true, docRegexp: '.*')); | |
| tests.add(checkHover( | |
| 'length =', 6, ['set', 'length', 'int'], 'setter', null, | |
| isCore: true, docRegexp: '.*')); | |
| tests.add(checkHover('param;', 5, ['int', 'param'], 'parameter', ['int'], | |
| isLocal: true, | |
| docRegexp: 'Documentation for func', | |
| parameterRegexps: ['.*'])); | |
| tests.add(checkHover( | |
| 'add(', 3, ['List', 'add'], 'method', ['dynamic', 'void'], | |
| isCore: true, docRegexp: '.*')); | |
| tests.add(checkHover( | |
| 'localVar)', 8, ['num', 'localVar'], 'local variable', ['num'], | |
| isLocal: true, parameterRegexps: ['.*'], propagatedType: 'int')); | |
| tests.add(checkHover( | |
| 'func(35', 4, ['func', 'int', 'param'], 'function', ['int', 'void'], | |
| docRegexp: 'Documentation for func')); | |
| tests.add(checkHover('35', 2, null, null, ['int'], | |
| isLiteral: true, parameterRegexps: ['int', 'param'])); | |
| tests.add(checkNoHover('comment')); | |
| return Future.wait(tests); | |
| }); | |
| } | |
| } | |
| @reflectiveTest | |
| class AnalysisGetHoverIntegrationTest_UseCFE | |
| extends AnalysisGetHoverIntegrationTest { | |
| @override | |
| bool get useCFE => true; | |
| @override | |
| @failingTest | |
| test_getHover() { | |
| // TODO(devoncarew): NoSuchMethodError: The getter 'canonicalName' was called on null. | |
| return super.test_getHover(); | |
| } | |
| } |