| // 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:analyzer/dart/ast/ast.dart'; |
| import 'package:analyzer/dart/ast/token.dart'; |
| import 'package:analyzer/dart/element/element.dart'; |
| import 'package:analyzer/dart/element/type.dart'; |
| import 'package:analyzer/error/error.dart'; |
| import 'package:analyzer/error/listener.dart'; |
| import 'package:analyzer/file_system/file_system.dart'; |
| import 'package:analyzer/file_system/memory_file_system.dart'; |
| import 'package:analyzer/file_system/physical_file_system.dart'; |
| import 'package:analyzer/src/dart/ast/utilities.dart' hide ConstantEvaluator; |
| import 'package:analyzer/src/dart/element/builder.dart'; |
| import 'package:analyzer/src/dart/element/element.dart'; |
| import 'package:analyzer/src/dart/sdk/sdk.dart' hide SdkLibrariesReader; |
| import 'package:analyzer/src/error/codes.dart'; |
| import 'package:analyzer/src/file_system/file_system.dart'; |
| import 'package:analyzer/src/generated/engine.dart'; |
| import 'package:analyzer/src/generated/java_engine_io.dart'; |
| import 'package:analyzer/src/generated/java_io.dart'; |
| import 'package:analyzer/src/generated/resolver.dart'; |
| import 'package:analyzer/src/generated/sdk.dart'; |
| import 'package:analyzer/src/generated/sdk_io.dart'; |
| import 'package:analyzer/src/generated/source.dart'; |
| import 'package:analyzer/src/generated/source_io.dart'; |
| import 'package:analyzer/src/generated/testing/ast_test_factory.dart'; |
| import 'package:analyzer/src/generated/testing/element_factory.dart'; |
| import 'package:analyzer/src/generated/testing/test_type_provider.dart'; |
| import 'package:analyzer/src/generated/testing/token_factory.dart'; |
| import 'package:analyzer/src/generated/utilities_dart.dart'; |
| import 'package:path/path.dart' as path; |
| import 'package:source_span/source_span.dart'; |
| import 'package:test/test.dart'; |
| import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| |
| import 'parser_test.dart'; |
| import 'resolver_test_case.dart'; |
| import 'test_support.dart'; |
| |
| main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(ContentCacheTest); |
| // ignore: deprecated_member_use |
| defineReflectiveTests(CustomUriResolverTest); |
| defineReflectiveTests(DartUriResolverTest); |
| defineReflectiveTests(ElementLocatorTest); |
| defineReflectiveTests(EnumMemberBuilderTest); |
| defineReflectiveTests(ErrorReporterTest); |
| defineReflectiveTests(ErrorSeverityTest); |
| defineReflectiveTests(ExitDetectorTest); |
| defineReflectiveTests(ExitDetectorTest2); |
| defineReflectiveTests(FileBasedSourceTest); |
| defineReflectiveTests(ResolveRelativeUriTest); |
| // ignore: deprecated_member_use |
| defineReflectiveTests(SDKLibrariesReaderTest); |
| defineReflectiveTests(UriKindTest); |
| }); |
| } |
| |
| @reflectiveTest |
| class ContentCacheTest { |
| test_setContents() async { |
| Source source = new TestSource(); |
| ContentCache cache = new ContentCache(); |
| expect(cache.getContents(source), isNull); |
| expect(cache.getModificationStamp(source), isNull); |
| String contents = "library lib;"; |
| expect(cache.setContents(source, contents), isNull); |
| expect(cache.getContents(source), contents); |
| expect(cache.getModificationStamp(source), isNotNull); |
| expect(cache.setContents(source, contents), contents); |
| expect(cache.setContents(source, null), contents); |
| expect(cache.getContents(source), isNull); |
| expect(cache.getModificationStamp(source), isNull); |
| expect(cache.setContents(source, null), isNull); |
| } |
| } |
| |
| @deprecated |
| @reflectiveTest |
| class CustomUriResolverTest { |
| void test_creation() { |
| expect(new CustomUriResolver({}), isNotNull); |
| } |
| |
| void test_resolve_unknown_uri() { |
| UriResolver resolver = new CustomUriResolver({ |
| 'custom:library': '/path/to/library.dart', |
| }); |
| Source result = resolver.resolveAbsolute(Uri.parse("custom:non_library")); |
| expect(result, isNull); |
| } |
| |
| void test_resolve_uri() { |
| String filePath = |
| FileUtilities2.createFile("/path/to/library.dart").getAbsolutePath(); |
| UriResolver resolver = new CustomUriResolver({ |
| 'custom:library': filePath, |
| }); |
| Source result = resolver.resolveAbsolute(Uri.parse("custom:library")); |
| expect(result, isNotNull); |
| expect(result.fullName, filePath); |
| } |
| } |
| |
| @reflectiveTest |
| class DartUriResolverTest extends _SimpleDartSdkTest { |
| DartUriResolver resolver; |
| |
| @override |
| setUp() { |
| super.setUp(); |
| resolver = new DartUriResolver(sdk); |
| } |
| |
| void test_creation() { |
| expect(new DartUriResolver(sdk), isNotNull); |
| } |
| |
| void test_isDartUri_null_scheme() { |
| Uri uri = Uri.parse("foo.dart"); |
| expect('', uri.scheme); |
| expect(DartUriResolver.isDartUri(uri), isFalse); |
| } |
| |
| void test_resolve_dart_library() { |
| Source source = resolver.resolveAbsolute(Uri.parse('dart:core')); |
| expect(source, isNotNull); |
| } |
| |
| void test_resolve_dart_nonExistingLibrary() { |
| Source result = resolver.resolveAbsolute(Uri.parse("dart:cor")); |
| expect(result, isNull); |
| } |
| |
| void test_resolve_dart_part() { |
| Source source = resolver.resolveAbsolute(Uri.parse('dart:core/int.dart')); |
| expect(source, isNotNull); |
| } |
| |
| void test_resolve_nonDart() { |
| Source result = |
| resolver.resolveAbsolute(Uri.parse("package:some/file.dart")); |
| expect(result, isNull); |
| } |
| |
| void test_restoreAbsolute_library() { |
| _SourceMock source = new _SourceMock(); |
| Uri fileUri = resourceProvider.pathContext.toUri(coreCorePath); |
| source.uri = fileUri; |
| Uri dartUri = resolver.restoreAbsolute(source); |
| expect(dartUri.toString(), 'dart:core'); |
| } |
| |
| void test_restoreAbsolute_part() { |
| _SourceMock source = new _SourceMock(); |
| Uri fileUri = resourceProvider.pathContext.toUri(coreIntPath); |
| source.uri = fileUri; |
| Uri dartUri = resolver.restoreAbsolute(source); |
| expect(dartUri.toString(), 'dart:core/int.dart'); |
| } |
| } |
| |
| @reflectiveTest |
| class ElementLocatorTest extends ResolverTestCase { |
| void fail_locate_Identifier_partOfDirective() { |
| // Can't resolve the library element without the library declaration. |
| // AstNode id = findNodeIn("foo", "part of foo.bar;"); |
| // Element element = ElementLocator.locate(id); |
| // assertInstanceOf(LibraryElement.class, element); |
| fail("Test this case"); |
| } |
| |
| @override |
| void reset() { |
| AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl(); |
| analysisOptions.hint = false; |
| resetWith(options: analysisOptions); |
| } |
| |
| test_locate_AssignmentExpression() async { |
| AstNode id = await _findNodeIn("+=", r''' |
| int x = 0; |
| void main() { |
| x += 1; |
| }'''); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is MethodElement, MethodElement, element); |
| } |
| |
| test_locate_BinaryExpression() async { |
| AstNode id = await _findNodeIn("+", "var x = 3 + 4;"); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is MethodElement, MethodElement, element); |
| } |
| |
| test_locate_ClassDeclaration() async { |
| AstNode id = await _findNodeIn("class", "class A { }"); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is ClassElement, ClassElement, element); |
| } |
| |
| test_locate_CompilationUnit() async { |
| CompilationUnit cu = await _resolveContents("// only comment"); |
| expect(cu.element, isNotNull); |
| Element element = ElementLocator.locate(cu); |
| expect(element, same(cu.element)); |
| } |
| |
| test_locate_ConstructorDeclaration() async { |
| AstNode id = await _findNodeIndexedIn("bar", 0, r''' |
| class A { |
| A.bar() {} |
| }'''); |
| ConstructorDeclaration declaration = |
| id.getAncestor((node) => node is ConstructorDeclaration); |
| Element element = ElementLocator.locate(declaration); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is ConstructorElement, ConstructorElement, element); |
| } |
| |
| test_locate_ExportDirective() async { |
| AstNode id = await _findNodeIn("export", "export 'dart:core';"); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is ExportElement, ExportElement, element); |
| } |
| |
| test_locate_FunctionDeclaration() async { |
| AstNode id = await _findNodeIn("f", "int f() => 3;"); |
| FunctionDeclaration declaration = |
| id.getAncestor((node) => node is FunctionDeclaration); |
| Element element = ElementLocator.locate(declaration); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is FunctionElement, FunctionElement, element); |
| } |
| |
| test_locate_Identifier_annotationClass_namedConstructor_forSimpleFormalParameter() async { |
| AstNode id = await _findNodeIndexedIn("Class", 2, r''' |
| class Class { |
| const Class.name(); |
| } |
| void main(@Class.name() parameter) { |
| }'''); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is ClassElement, ClassElement, element); |
| } |
| |
| test_locate_Identifier_annotationClass_unnamedConstructor_forSimpleFormalParameter() async { |
| AstNode id = await _findNodeIndexedIn("Class", 2, r''' |
| class Class { |
| const Class(); |
| } |
| void main(@Class() parameter) { |
| }'''); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is ConstructorElement, ConstructorElement, element); |
| } |
| |
| test_locate_Identifier_className() async { |
| AstNode id = await _findNodeIn("A", "class A { }"); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is ClassElement, ClassElement, element); |
| } |
| |
| test_locate_Identifier_constructor_named() async { |
| AstNode id = await _findNodeIndexedIn("bar", 0, r''' |
| class A { |
| A.bar() {} |
| }'''); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is ConstructorElement, ConstructorElement, element); |
| } |
| |
| test_locate_Identifier_constructor_unnamed() async { |
| AstNode id = await _findNodeIndexedIn("A", 1, r''' |
| class A { |
| A() {} |
| }'''); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is ConstructorElement, ConstructorElement, element); |
| } |
| |
| test_locate_Identifier_fieldName() async { |
| AstNode id = await _findNodeIn("x", "class A { var x; }"); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is FieldElement, FieldElement, element); |
| } |
| |
| test_locate_Identifier_libraryDirective() async { |
| AstNode id = await _findNodeIn("foo", "library foo.bar;"); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is LibraryElement, LibraryElement, element); |
| } |
| |
| test_locate_Identifier_propertyAccess() async { |
| AstNode id = await _findNodeIn("length", r''' |
| void main() { |
| int x = 'foo'.length; |
| }'''); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf((obj) => obj is PropertyAccessorElement, |
| PropertyAccessorElement, element); |
| } |
| |
| test_locate_ImportDirective() async { |
| AstNode id = await _findNodeIn("import", "import 'dart:core';"); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is ImportElement, ImportElement, element); |
| } |
| |
| test_locate_IndexExpression() async { |
| AstNode id = await _findNodeIndexedIn("\\[", 1, r''' |
| void main() { |
| List x = [1, 2]; |
| var y = x[0]; |
| }'''); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is MethodElement, MethodElement, element); |
| } |
| |
| test_locate_InstanceCreationExpression() async { |
| AstNode node = await _findNodeIndexedIn("A(", 0, r''' |
| class A {} |
| void main() { |
| new A(); |
| }'''); |
| Element element = ElementLocator.locate(node); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is ConstructorElement, ConstructorElement, element); |
| } |
| |
| test_locate_InstanceCreationExpression_type_prefixedIdentifier() async { |
| // prepare: new pref.A() |
| SimpleIdentifier identifier = AstTestFactory.identifier3("A"); |
| PrefixedIdentifier prefixedIdentifier = |
| AstTestFactory.identifier4("pref", identifier); |
| InstanceCreationExpression creation = |
| AstTestFactory.instanceCreationExpression2( |
| Keyword.NEW, AstTestFactory.typeName3(prefixedIdentifier)); |
| // set ClassElement |
| ClassElement classElement = ElementFactory.classElement2("A"); |
| identifier.staticElement = classElement; |
| // set ConstructorElement |
| ConstructorElement constructorElement = |
| ElementFactory.constructorElement2(classElement, null); |
| creation.constructorName.staticElement = constructorElement; |
| // verify that "A" is resolved to ConstructorElement |
| Element element = ElementLocator.locate(identifier); |
| expect(element, same(classElement)); |
| } |
| |
| test_locate_InstanceCreationExpression_type_simpleIdentifier() async { |
| // prepare: new A() |
| SimpleIdentifier identifier = AstTestFactory.identifier3("A"); |
| InstanceCreationExpression creation = |
| AstTestFactory.instanceCreationExpression2( |
| Keyword.NEW, AstTestFactory.typeName3(identifier)); |
| // set ClassElement |
| ClassElement classElement = ElementFactory.classElement2("A"); |
| identifier.staticElement = classElement; |
| // set ConstructorElement |
| ConstructorElement constructorElement = |
| ElementFactory.constructorElement2(classElement, null); |
| creation.constructorName.staticElement = constructorElement; |
| // verify that "A" is resolved to ConstructorElement |
| Element element = ElementLocator.locate(identifier); |
| expect(element, same(classElement)); |
| } |
| |
| test_locate_LibraryDirective() async { |
| AstNode id = await _findNodeIn("library", "library foo;"); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is LibraryElement, LibraryElement, element); |
| } |
| |
| test_locate_MethodDeclaration() async { |
| AstNode id = await _findNodeIn("m", r''' |
| class A { |
| void m() {} |
| }'''); |
| MethodDeclaration declaration = |
| id.getAncestor((node) => node is MethodDeclaration); |
| Element element = ElementLocator.locate(declaration); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is MethodElement, MethodElement, element); |
| } |
| |
| test_locate_MethodInvocation_method() async { |
| AstNode id = await _findNodeIndexedIn("bar", 1, r''' |
| class A { |
| int bar() => 42; |
| } |
| void main() { |
| var f = new A().bar(); |
| }'''); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is MethodElement, MethodElement, element); |
| } |
| |
| test_locate_MethodInvocation_topLevel() async { |
| String code = r''' |
| foo(x) {} |
| void main() { |
| foo(0); |
| }'''; |
| CompilationUnit cu = await _resolveContents(code); |
| int offset = code.indexOf('foo(0)'); |
| AstNode node = new NodeLocator(offset).searchWithin(cu); |
| MethodInvocation invocation = |
| node.getAncestor((n) => n is MethodInvocation); |
| Element element = ElementLocator.locate(invocation); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is FunctionElement, FunctionElement, element); |
| } |
| |
| test_locate_PartOfDirective() async { |
| Source librarySource = addNamedSource('/lib.dart', ''' |
| library my.lib; |
| part 'part.dart'; |
| '''); |
| Source unitSource = addNamedSource('/part.dart', ''' |
| part of my.lib; |
| '''); |
| CompilationUnit unit = |
| analysisContext.resolveCompilationUnit2(unitSource, librarySource); |
| PartOfDirective partOf = unit.directives.first; |
| Element element = ElementLocator.locate(partOf); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is LibraryElement, LibraryElement, element); |
| } |
| |
| test_locate_PostfixExpression() async { |
| AstNode id = await _findNodeIn("++", "int addOne(int x) => x++;"); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is MethodElement, MethodElement, element); |
| } |
| |
| test_locate_PrefixedIdentifier() async { |
| AstNode id = await _findNodeIn("int", r''' |
| import 'dart:core' as core; |
| core.int value;'''); |
| PrefixedIdentifier identifier = |
| id.getAncestor((node) => node is PrefixedIdentifier); |
| Element element = ElementLocator.locate(identifier); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is ClassElement, ClassElement, element); |
| } |
| |
| test_locate_PrefixExpression() async { |
| AstNode id = await _findNodeIn("++", "int addOne(int x) => ++x;"); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is MethodElement, MethodElement, element); |
| } |
| |
| test_locate_StringLiteral_exportUri() async { |
| addNamedSource("/foo.dart", "library foo;"); |
| AstNode id = await _findNodeIn("'foo.dart'", "export 'foo.dart';"); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is LibraryElement, LibraryElement, element); |
| } |
| |
| test_locate_StringLiteral_expression() async { |
| AstNode id = await _findNodeIn("abc", "var x = 'abc';"); |
| Element element = ElementLocator.locate(id); |
| expect(element, isNull); |
| } |
| |
| test_locate_StringLiteral_importUri() async { |
| addNamedSource("/foo.dart", "library foo; class A {}"); |
| AstNode id = await _findNodeIn( |
| "'foo.dart'", "import 'foo.dart'; class B extends A {}"); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf( |
| (obj) => obj is LibraryElement, LibraryElement, element); |
| } |
| |
| test_locate_StringLiteral_partUri() async { |
| addNamedSource("/foo.dart", "part of app;"); |
| AstNode id = |
| await _findNodeIn("'foo.dart'", "library app; part 'foo.dart';"); |
| Element element = ElementLocator.locate(id); |
| EngineTestCase.assertInstanceOf((obj) => obj is CompilationUnitElement, |
| CompilationUnitElement, element); |
| } |
| |
| test_locate_VariableDeclaration() async { |
| AstNode id = await _findNodeIn("x", "var x = 'abc';"); |
| VariableDeclaration declaration = |
| id.getAncestor((node) => node is VariableDeclaration); |
| Element element = ElementLocator.locate(declaration); |
| EngineTestCase.assertInstanceOf((obj) => obj is TopLevelVariableElement, |
| TopLevelVariableElement, element); |
| } |
| |
| /** |
| * Find the first AST node matching a pattern in the resolved AST for the given source. |
| * |
| * [nodePattern] the (unique) pattern used to identify the node of interest. |
| * [code] the code to resolve. |
| * Returns the matched node in the resolved AST for the given source lines. |
| */ |
| Future<AstNode> _findNodeIn(String nodePattern, String code) async { |
| return await _findNodeIndexedIn(nodePattern, 0, code); |
| } |
| |
| /** |
| * Find the AST node matching the given indexed occurrence of a pattern in the resolved AST for |
| * the given source. |
| * |
| * [nodePattern] the pattern used to identify the node of interest. |
| * [index] the index of the pattern match of interest. |
| * [code] the code to resolve. |
| * Returns the matched node in the resolved AST for the given source lines |
| */ |
| Future<AstNode> _findNodeIndexedIn( |
| String nodePattern, int index, String code) async { |
| CompilationUnit cu = await _resolveContents(code); |
| int start = _getOffsetOfMatch(code, nodePattern, index); |
| int end = start + nodePattern.length; |
| return new NodeLocator(start, end).searchWithin(cu); |
| } |
| |
| int _getOffsetOfMatch(String contents, String pattern, int matchIndex) { |
| if (matchIndex == 0) { |
| return contents.indexOf(pattern); |
| } |
| Iterable<Match> matches = new RegExp(pattern).allMatches(contents); |
| Match match = matches.toList()[matchIndex]; |
| return match.start; |
| } |
| |
| /** |
| * Parse, resolve and verify the given source lines to produce a fully |
| * resolved AST. |
| * |
| * [code] the code to resolve. |
| * |
| * Returns the result of resolving the AST structure representing the content |
| * of the source. |
| * |
| * Throws if source cannot be verified. |
| */ |
| Future<CompilationUnit> _resolveContents(String code) async { |
| Source source = addSource(code); |
| LibraryElement library = resolve2(source); |
| await computeAnalysisResult(source); |
| assertNoErrors(source); |
| verify([source]); |
| return analysisContext.resolveCompilationUnit(source, library); |
| } |
| } |
| |
| @reflectiveTest |
| class EnumMemberBuilderTest extends EngineTestCase { |
| test_visitEnumDeclaration_multiple() async { |
| String firstName = "ONE"; |
| String secondName = "TWO"; |
| String thirdName = "THREE"; |
| EnumDeclaration enumDeclaration = AstTestFactory |
| .enumDeclaration2("E", [firstName, secondName, thirdName]); |
| |
| ClassElement enumElement = _buildElement(enumDeclaration); |
| List<FieldElement> fields = enumElement.fields; |
| expect(fields, hasLength(5)); |
| |
| FieldElement constant = fields[2]; |
| expect(constant, isNotNull); |
| expect(constant.name, firstName); |
| expect(constant.isStatic, isTrue); |
| expect((constant as FieldElementImpl).evaluationResult, isNotNull); |
| _assertGetter(constant); |
| |
| constant = fields[3]; |
| expect(constant, isNotNull); |
| expect(constant.name, secondName); |
| expect(constant.isStatic, isTrue); |
| expect((constant as FieldElementImpl).evaluationResult, isNotNull); |
| _assertGetter(constant); |
| |
| constant = fields[4]; |
| expect(constant, isNotNull); |
| expect(constant.name, thirdName); |
| expect(constant.isStatic, isTrue); |
| expect((constant as FieldElementImpl).evaluationResult, isNotNull); |
| _assertGetter(constant); |
| } |
| |
| test_visitEnumDeclaration_single() async { |
| String firstName = "ONE"; |
| EnumDeclaration enumDeclaration = |
| AstTestFactory.enumDeclaration2("E", [firstName]); |
| enumDeclaration.constants[0].documentationComment = AstTestFactory |
| .documentationComment( |
| [TokenFactory.tokenFromString('/// aaa')..offset = 50], []); |
| |
| ClassElement enumElement = _buildElement(enumDeclaration); |
| List<FieldElement> fields = enumElement.fields; |
| expect(fields, hasLength(3)); |
| |
| FieldElement field = fields[0]; |
| expect(field, isNotNull); |
| expect(field.name, "index"); |
| expect(field.isStatic, isFalse); |
| expect(field.isSynthetic, isTrue); |
| _assertGetter(field); |
| |
| field = fields[1]; |
| expect(field, isNotNull); |
| expect(field.name, "values"); |
| expect(field.isStatic, isTrue); |
| expect(field.isSynthetic, isTrue); |
| expect((field as FieldElementImpl).evaluationResult, isNotNull); |
| _assertGetter(field); |
| |
| FieldElement constant = fields[2]; |
| expect(constant, isNotNull); |
| expect(constant.name, firstName); |
| expect(constant.isStatic, isTrue); |
| expect((constant as FieldElementImpl).evaluationResult, isNotNull); |
| expect(constant.documentationComment, '/// aaa'); |
| _assertGetter(constant); |
| } |
| |
| void _assertGetter(FieldElement field) { |
| PropertyAccessorElement getter = field.getter; |
| expect(getter, isNotNull); |
| expect(getter.variable, same(field)); |
| expect(getter.type, isNotNull); |
| } |
| |
| ClassElement _buildElement(EnumDeclaration enumDeclaration) { |
| ElementHolder holder = new ElementHolder(); |
| ElementBuilder elementBuilder = _makeBuilder(holder); |
| enumDeclaration.accept(elementBuilder); |
| EnumMemberBuilder memberBuilder = |
| new EnumMemberBuilder(new TestTypeProvider()); |
| enumDeclaration.accept(memberBuilder); |
| List<ClassElement> enums = holder.enums; |
| expect(enums, hasLength(1)); |
| return enums[0]; |
| } |
| |
| ElementBuilder _makeBuilder(ElementHolder holder) => |
| new ElementBuilder(holder, new CompilationUnitElementImpl('test.dart')); |
| } |
| |
| @reflectiveTest |
| class ErrorReporterTest extends EngineTestCase { |
| /** |
| * Create a type with the given name in a compilation unit with the given name. |
| * |
| * @param fileName the name of the compilation unit containing the class |
| * @param typeName the name of the type to be created |
| * @return the type that was created |
| */ |
| InterfaceType createType(String fileName, String typeName) { |
| CompilationUnitElementImpl unit = ElementFactory.compilationUnit(fileName); |
| ClassElementImpl element = ElementFactory.classElement2(typeName); |
| unit.types = <ClassElement>[element]; |
| return element.type; |
| } |
| |
| test_creation() async { |
| GatheringErrorListener listener = new GatheringErrorListener(); |
| TestSource source = new TestSource(); |
| expect(new ErrorReporter(listener, source), isNotNull); |
| } |
| |
| test_reportErrorForElement_named() async { |
| DartType type = createType("/test1.dart", "A"); |
| ClassElement element = type.element; |
| GatheringErrorListener listener = new GatheringErrorListener(); |
| ErrorReporter reporter = new ErrorReporter(listener, element.source); |
| reporter.reportErrorForElement( |
| StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER, |
| element, |
| ['A']); |
| AnalysisError error = listener.errors[0]; |
| expect(error.offset, element.nameOffset); |
| } |
| |
| test_reportErrorForElement_unnamed() async { |
| ImportElementImpl element = |
| ElementFactory.importFor(ElementFactory.library(null, ''), null); |
| GatheringErrorListener listener = new GatheringErrorListener(); |
| ErrorReporter reporter = new ErrorReporter( |
| listener, |
| new NonExistingSource( |
| '/test.dart', path.toUri('/test.dart'), UriKind.FILE_URI)); |
| reporter.reportErrorForElement( |
| StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER, |
| element, |
| ['A']); |
| AnalysisError error = listener.errors[0]; |
| expect(error.offset, element.nameOffset); |
| } |
| |
| test_reportErrorForSpan() async { |
| GatheringErrorListener listener = new GatheringErrorListener(); |
| ErrorReporter reporter = new ErrorReporter(listener, new TestSource()); |
| |
| var src = ''' |
| foo: bar |
| zap: baz |
| '''; |
| |
| int offset = src.indexOf('baz'); |
| int length = 'baz'.length; |
| |
| SourceSpan span = new SourceSpanBase( |
| new SourceLocation(offset), new SourceLocation(offset + length), 'baz'); |
| |
| reporter.reportErrorForSpan( |
| AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUE, |
| span, |
| ['test', 'zip', 'zap']); |
| expect(listener.errors, hasLength(1)); |
| expect(listener.errors.first.offset, offset); |
| expect(listener.errors.first.length, length); |
| } |
| |
| test_reportTypeErrorForNode_differentNames() async { |
| DartType firstType = createType("/test1.dart", "A"); |
| DartType secondType = createType("/test2.dart", "B"); |
| GatheringErrorListener listener = new GatheringErrorListener(); |
| ErrorReporter reporter = |
| new ErrorReporter(listener, firstType.element.source); |
| reporter.reportTypeErrorForNode( |
| StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, |
| AstTestFactory.identifier3("x"), |
| [firstType, secondType]); |
| AnalysisError error = listener.errors[0]; |
| expect(error.message.indexOf("(") < 0, isTrue); |
| } |
| |
| test_reportTypeErrorForNode_sameName() async { |
| String typeName = "A"; |
| DartType firstType = createType("/test1.dart", typeName); |
| DartType secondType = createType("/test2.dart", typeName); |
| GatheringErrorListener listener = new GatheringErrorListener(); |
| ErrorReporter reporter = |
| new ErrorReporter(listener, firstType.element.source); |
| reporter.reportTypeErrorForNode( |
| StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, |
| AstTestFactory.identifier3("x"), |
| [firstType, secondType]); |
| AnalysisError error = listener.errors[0]; |
| expect(error.message.indexOf("(") >= 0, isTrue); |
| } |
| } |
| |
| @reflectiveTest |
| class ErrorSeverityTest extends EngineTestCase { |
| test_max_error_error() async { |
| expect(ErrorSeverity.ERROR.max(ErrorSeverity.ERROR), |
| same(ErrorSeverity.ERROR)); |
| } |
| |
| test_max_error_none() async { |
| expect( |
| ErrorSeverity.ERROR.max(ErrorSeverity.NONE), same(ErrorSeverity.ERROR)); |
| } |
| |
| test_max_error_warning() async { |
| expect(ErrorSeverity.ERROR.max(ErrorSeverity.WARNING), |
| same(ErrorSeverity.ERROR)); |
| } |
| |
| test_max_none_error() async { |
| expect( |
| ErrorSeverity.NONE.max(ErrorSeverity.ERROR), same(ErrorSeverity.ERROR)); |
| } |
| |
| test_max_none_none() async { |
| expect( |
| ErrorSeverity.NONE.max(ErrorSeverity.NONE), same(ErrorSeverity.NONE)); |
| } |
| |
| test_max_none_warning() async { |
| expect(ErrorSeverity.NONE.max(ErrorSeverity.WARNING), |
| same(ErrorSeverity.WARNING)); |
| } |
| |
| test_max_warning_error() async { |
| expect(ErrorSeverity.WARNING.max(ErrorSeverity.ERROR), |
| same(ErrorSeverity.ERROR)); |
| } |
| |
| test_max_warning_none() async { |
| expect(ErrorSeverity.WARNING.max(ErrorSeverity.NONE), |
| same(ErrorSeverity.WARNING)); |
| } |
| |
| test_max_warning_warning() async { |
| expect(ErrorSeverity.WARNING.max(ErrorSeverity.WARNING), |
| same(ErrorSeverity.WARNING)); |
| } |
| } |
| |
| /** |
| * Tests for the [ExitDetector] that do not require that the AST be resolved. |
| * |
| * See [ExitDetectorTest2] for tests that require the AST to be resolved. |
| */ |
| @reflectiveTest |
| class ExitDetectorTest extends ParserTestCase { |
| test_asExpression() async { |
| _assertFalse("a as Object;"); |
| } |
| |
| test_asExpression_throw() async { |
| _assertTrue("throw '' as Object;"); |
| } |
| |
| test_assertStatement() async { |
| _assertFalse("assert(a);"); |
| } |
| |
| test_assertStatement_throw() async { |
| _assertFalse("assert((throw 0));"); |
| } |
| |
| test_assignmentExpression() async { |
| _assertFalse("v = 1;"); |
| } |
| |
| test_assignmentExpression_compound_lazy() async { |
| enableLazyAssignmentOperators = true; |
| _assertFalse("v ||= false;"); |
| } |
| |
| test_assignmentExpression_lhs_throw() async { |
| _assertTrue("a[throw ''] = 0;"); |
| } |
| |
| test_assignmentExpression_rhs_throw() async { |
| _assertTrue("v = throw '';"); |
| } |
| |
| test_await_false() async { |
| _assertFalse("await x;"); |
| } |
| |
| test_await_throw_true() async { |
| _assertTrue("bool b = await (throw '' || true);"); |
| } |
| |
| test_binaryExpression_and() async { |
| _assertFalse("a && b;"); |
| } |
| |
| test_binaryExpression_and_lhs() async { |
| _assertTrue("throw '' && b;"); |
| } |
| |
| test_binaryExpression_and_rhs() async { |
| _assertFalse("a && (throw '');"); |
| } |
| |
| test_binaryExpression_and_rhs2() async { |
| _assertFalse("false && (throw '');"); |
| } |
| |
| test_binaryExpression_and_rhs3() async { |
| _assertTrue("true && (throw '');"); |
| } |
| |
| test_binaryExpression_ifNull() async { |
| _assertFalse("a ?? b;"); |
| } |
| |
| test_binaryExpression_ifNull_lhs() async { |
| _assertTrue("throw '' ?? b;"); |
| } |
| |
| test_binaryExpression_ifNull_rhs() async { |
| _assertFalse("a ?? (throw '');"); |
| } |
| |
| test_binaryExpression_ifNull_rhs2() async { |
| _assertFalse("null ?? (throw '');"); |
| } |
| |
| test_binaryExpression_or() async { |
| _assertFalse("a || b;"); |
| } |
| |
| test_binaryExpression_or_lhs() async { |
| _assertTrue("throw '' || b;"); |
| } |
| |
| test_binaryExpression_or_rhs() async { |
| _assertFalse("a || (throw '');"); |
| } |
| |
| test_binaryExpression_or_rhs2() async { |
| _assertFalse("true || (throw '');"); |
| } |
| |
| test_binaryExpression_or_rhs3() async { |
| _assertTrue("false || (throw '');"); |
| } |
| |
| test_block_empty() async { |
| _assertFalse("{}"); |
| } |
| |
| test_block_noReturn() async { |
| _assertFalse("{ int i = 0; }"); |
| } |
| |
| test_block_return() async { |
| _assertTrue("{ return 0; }"); |
| } |
| |
| test_block_returnNotLast() async { |
| _assertTrue("{ return 0; throw 'a'; }"); |
| } |
| |
| test_block_throwNotLast() async { |
| _assertTrue("{ throw 0; x = null; }"); |
| } |
| |
| test_cascadeExpression_argument() async { |
| _assertTrue("a..b(throw '');"); |
| } |
| |
| test_cascadeExpression_index() async { |
| _assertTrue("a..[throw ''];"); |
| } |
| |
| test_cascadeExpression_target() async { |
| _assertTrue("throw ''..b();"); |
| } |
| |
| test_conditional_ifElse_bothThrows() async { |
| _assertTrue("c ? throw '' : throw '';"); |
| } |
| |
| test_conditional_ifElse_elseThrows() async { |
| _assertFalse("c ? i : throw '';"); |
| } |
| |
| test_conditional_ifElse_noThrow() async { |
| _assertFalse("c ? i : j;"); |
| } |
| |
| test_conditional_ifElse_thenThrow() async { |
| _assertFalse("c ? throw '' : j;"); |
| } |
| |
| test_conditionalAccess() async { |
| _assertFalse("a?.b;"); |
| } |
| |
| test_conditionalAccess_lhs() async { |
| _assertTrue("(throw '')?.b;"); |
| } |
| |
| test_conditionalAccessAssign() async { |
| _assertFalse("a?.b = c;"); |
| } |
| |
| test_conditionalAccessAssign_lhs() async { |
| _assertTrue("(throw '')?.b = c;"); |
| } |
| |
| test_conditionalAccessAssign_rhs() async { |
| _assertFalse("a?.b = throw '';"); |
| } |
| |
| test_conditionalAccessAssign_rhs2() async { |
| _assertFalse("null?.b = throw '';"); |
| } |
| |
| test_conditionalAccessIfNullAssign() async { |
| _assertFalse("a?.b ??= c;"); |
| } |
| |
| test_conditionalAccessIfNullAssign_lhs() async { |
| _assertTrue("(throw '')?.b ??= c;"); |
| } |
| |
| test_conditionalAccessIfNullAssign_rhs() async { |
| _assertFalse("a?.b ??= throw '';"); |
| } |
| |
| test_conditionalAccessIfNullAssign_rhs2() async { |
| _assertFalse("null?.b ??= throw '';"); |
| } |
| |
| test_conditionalCall() async { |
| _assertFalse("a?.b(c);"); |
| } |
| |
| test_conditionalCall_lhs() async { |
| _assertTrue("(throw '')?.b(c);"); |
| } |
| |
| test_conditionalCall_rhs() async { |
| _assertFalse("a?.b(throw '');"); |
| } |
| |
| test_conditionalCall_rhs2() async { |
| _assertFalse("null?.b(throw '');"); |
| } |
| |
| test_creation() async { |
| expect(new ExitDetector(), isNotNull); |
| } |
| |
| test_doStatement_break_and_throw() async { |
| _assertFalse("{ do { if (1==1) break; throw 'T'; } while (0==1); }"); |
| } |
| |
| test_doStatement_continue_and_throw() async { |
| _assertFalse("{ do { if (1==1) continue; throw 'T'; } while (0==1); }"); |
| } |
| |
| test_doStatement_continueDoInSwitch_and_throw() async { |
| _assertFalse(''' |
| { |
| D: do { |
| switch (1) { |
| L: case 0: continue D; |
| M: case 1: break; |
| } |
| throw 'T'; |
| } while (0 == 1); |
| }'''); |
| } |
| |
| test_doStatement_continueInSwitch_and_throw() async { |
| _assertFalse(''' |
| { |
| do { |
| switch (1) { |
| L: case 0: continue; |
| M: case 1: break; |
| } |
| throw 'T'; |
| } while (0 == 1); |
| }'''); |
| } |
| |
| test_doStatement_return() async { |
| _assertTrue("{ do { return null; } while (1 == 2); }"); |
| } |
| |
| test_doStatement_throwCondition() async { |
| _assertTrue("{ do {} while (throw ''); }"); |
| } |
| |
| test_doStatement_true_break() async { |
| _assertFalse("{ do { break; } while (true); }"); |
| } |
| |
| test_doStatement_true_continue() async { |
| _assertTrue("{ do { continue; } while (true); }"); |
| } |
| |
| test_doStatement_true_continueWithLabel() async { |
| _assertTrue("{ x: do { continue x; } while (true); }"); |
| } |
| |
| test_doStatement_true_if_return() async { |
| _assertTrue("{ do { if (true) {return null;} } while (true); }"); |
| } |
| |
| test_doStatement_true_noBreak() async { |
| _assertTrue("{ do {} while (true); }"); |
| } |
| |
| test_doStatement_true_return() async { |
| _assertTrue("{ do { return null; } while (true); }"); |
| } |
| |
| test_emptyStatement() async { |
| _assertFalse(";"); |
| } |
| |
| test_forEachStatement() async { |
| _assertFalse("for (element in list) {}"); |
| } |
| |
| test_forEachStatement_throw() async { |
| _assertTrue("for (element in throw '') {}"); |
| } |
| |
| test_forStatement_condition() async { |
| _assertTrue("for (; throw 0;) {}"); |
| } |
| |
| test_forStatement_implicitTrue() async { |
| _assertTrue("for (;;) {}"); |
| } |
| |
| test_forStatement_implicitTrue_break() async { |
| _assertFalse("for (;;) { break; }"); |
| } |
| |
| test_forStatement_implicitTrue_if_break() async { |
| _assertFalse("{ for (;;) { if (1==2) { var a = 1; } else { break; } } }"); |
| } |
| |
| test_forStatement_initialization() async { |
| _assertTrue("for (i = throw 0;;) {}"); |
| } |
| |
| test_forStatement_true() async { |
| _assertTrue("for (; true; ) {}"); |
| } |
| |
| test_forStatement_true_break() async { |
| _assertFalse("{ for (; true; ) { break; } }"); |
| } |
| |
| test_forStatement_true_continue() async { |
| _assertTrue("{ for (; true; ) { continue; } }"); |
| } |
| |
| test_forStatement_true_if_return() async { |
| _assertTrue("{ for (; true; ) { if (true) {return null;} } }"); |
| } |
| |
| test_forStatement_true_noBreak() async { |
| _assertTrue("{ for (; true; ) {} }"); |
| } |
| |
| test_forStatement_updaters() async { |
| _assertTrue("for (;; i++, throw 0) {}"); |
| } |
| |
| test_forStatement_variableDeclaration() async { |
| _assertTrue("for (int i = throw 0;;) {}"); |
| } |
| |
| test_functionExpression() async { |
| _assertFalse("(){};"); |
| } |
| |
| test_functionExpression_bodyThrows() async { |
| _assertFalse("(int i) => throw '';"); |
| } |
| |
| test_functionExpressionInvocation() async { |
| _assertFalse("f(g);"); |
| } |
| |
| test_functionExpressionInvocation_argumentThrows() async { |
| _assertTrue("f(throw '');"); |
| } |
| |
| test_functionExpressionInvocation_targetThrows() async { |
| _assertTrue("throw ''(g);"); |
| } |
| |
| test_identifier_prefixedIdentifier() async { |
| _assertFalse("a.b;"); |
| } |
| |
| test_identifier_simpleIdentifier() async { |
| _assertFalse("a;"); |
| } |
| |
| test_if_false_else_return() async { |
| _assertTrue("if (false) {} else { return 0; }"); |
| } |
| |
| test_if_false_noReturn() async { |
| _assertFalse("if (false) {}"); |
| } |
| |
| test_if_false_return() async { |
| _assertFalse("if (false) { return 0; }"); |
| } |
| |
| test_if_noReturn() async { |
| _assertFalse("if (c) i++;"); |
| } |
| |
| test_if_return() async { |
| _assertFalse("if (c) return 0;"); |
| } |
| |
| test_if_true_noReturn() async { |
| _assertFalse("if (true) {}"); |
| } |
| |
| test_if_true_return() async { |
| _assertTrue("if (true) { return 0; }"); |
| } |
| |
| test_ifElse_bothReturn() async { |
| _assertTrue("if (c) return 0; else return 1;"); |
| } |
| |
| test_ifElse_elseReturn() async { |
| _assertFalse("if (c) i++; else return 1;"); |
| } |
| |
| test_ifElse_noReturn() async { |
| _assertFalse("if (c) i++; else j++;"); |
| } |
| |
| test_ifElse_thenReturn() async { |
| _assertFalse("if (c) return 0; else j++;"); |
| } |
| |
| test_ifNullAssign() async { |
| _assertFalse("a ??= b;"); |
| } |
| |
| test_ifNullAssign_rhs() async { |
| _assertFalse("a ??= throw '';"); |
| } |
| |
| test_indexExpression() async { |
| _assertFalse("a[b];"); |
| } |
| |
| test_indexExpression_index() async { |
| _assertTrue("a[throw ''];"); |
| } |
| |
| test_indexExpression_target() async { |
| _assertTrue("throw ''[b];"); |
| } |
| |
| test_instanceCreationExpression() async { |
| _assertFalse("new A(b);"); |
| } |
| |
| test_instanceCreationExpression_argumentThrows() async { |
| _assertTrue("new A(throw '');"); |
| } |
| |
| test_isExpression() async { |
| _assertFalse("A is B;"); |
| } |
| |
| test_isExpression_throws() async { |
| _assertTrue("throw '' is B;"); |
| } |
| |
| test_labeledStatement() async { |
| _assertFalse("label: a;"); |
| } |
| |
| test_labeledStatement_throws() async { |
| _assertTrue("label: throw '';"); |
| } |
| |
| test_literal_boolean() async { |
| _assertFalse("true;"); |
| } |
| |
| test_literal_double() async { |
| _assertFalse("1.1;"); |
| } |
| |
| test_literal_integer() async { |
| _assertFalse("1;"); |
| } |
| |
| test_literal_null() async { |
| _assertFalse("null;"); |
| } |
| |
| test_literal_String() async { |
| _assertFalse("'str';"); |
| } |
| |
| test_methodInvocation() async { |
| _assertFalse("a.b(c);"); |
| } |
| |
| test_methodInvocation_argument() async { |
| _assertTrue("a.b(throw '');"); |
| } |
| |
| test_methodInvocation_target() async { |
| _assertTrue("throw ''.b(c);"); |
| } |
| |
| test_parenthesizedExpression() async { |
| _assertFalse("(a);"); |
| } |
| |
| test_parenthesizedExpression_throw() async { |
| _assertTrue("(throw '');"); |
| } |
| |
| test_propertyAccess() async { |
| _assertFalse("new Object().a;"); |
| } |
| |
| test_propertyAccess_throws() async { |
| _assertTrue("(throw '').a;"); |
| } |
| |
| test_rethrow() async { |
| _assertTrue("rethrow;"); |
| } |
| |
| test_return() async { |
| _assertTrue("return 0;"); |
| } |
| |
| test_superExpression() async { |
| _assertFalse("super.a;"); |
| } |
| |
| test_switch_allReturn() async { |
| _assertTrue("switch (i) { case 0: return 0; default: return 1; }"); |
| } |
| |
| test_switch_defaultWithNoStatements() async { |
| _assertFalse("switch (i) { case 0: return 0; default: }"); |
| } |
| |
| test_switch_fallThroughToNotReturn() async { |
| _assertFalse("switch (i) { case 0: case 1: break; default: return 1; }"); |
| } |
| |
| test_switch_fallThroughToReturn() async { |
| _assertTrue("switch (i) { case 0: case 1: return 0; default: return 1; }"); |
| } |
| |
| // The ExitDetector could conceivably follow switch continue labels and |
| // determine that `case 0` exits, `case 1` continues to an exiting case, and |
| // `default` exits, so the switch exits. |
| @failingTest |
| test_switch_includesContinue() async { |
| _assertTrue(''' |
| switch (i) { |
| zero: case 0: return 0; |
| case 1: continue zero; |
| default: return 1; |
| }'''); |
| } |
| |
| test_switch_noDefault() async { |
| _assertFalse("switch (i) { case 0: return 0; }"); |
| } |
| |
| test_switch_nonReturn() async { |
| _assertFalse("switch (i) { case 0: i++; default: return 1; }"); |
| } |
| |
| test_thisExpression() async { |
| _assertFalse("this.a;"); |
| } |
| |
| test_throwExpression() async { |
| _assertTrue("throw new Object();"); |
| } |
| |
| test_tryStatement_noReturn() async { |
| _assertFalse("try {} catch (e, s) {} finally {}"); |
| } |
| |
| test_tryStatement_noReturn_noFinally() async { |
| _assertFalse("try {} catch (e, s) {}"); |
| } |
| |
| test_tryStatement_return_catch() async { |
| _assertFalse("try {} catch (e, s) { return 1; } finally {}"); |
| } |
| |
| test_tryStatement_return_catch_noFinally() async { |
| _assertFalse("try {} catch (e, s) { return 1; }"); |
| } |
| |
| test_tryStatement_return_finally() async { |
| _assertTrue("try {} catch (e, s) {} finally { return 1; }"); |
| } |
| |
| test_tryStatement_return_try_noCatch() async { |
| _assertTrue("try { return 1; } finally {}"); |
| } |
| |
| test_tryStatement_return_try_oneCatchDoesNotExit() async { |
| _assertFalse("try { return 1; } catch (e, s) {} finally {}"); |
| } |
| |
| test_tryStatement_return_try_oneCatchDoesNotExit_noFinally() async { |
| _assertFalse("try { return 1; } catch (e, s) {}"); |
| } |
| |
| test_tryStatement_return_try_oneCatchExits() async { |
| _assertTrue("try { return 1; } catch (e, s) { return 1; } finally {}"); |
| } |
| |
| test_tryStatement_return_try_oneCatchExits_noFinally() async { |
| _assertTrue("try { return 1; } catch (e, s) { return 1; }"); |
| } |
| |
| test_tryStatement_return_try_twoCatchesDoExit() async { |
| _assertTrue(''' |
| try { return 1; } |
| on int catch (e, s) { return 1; } |
| on String catch (e, s) { return 1; } |
| finally {}'''); |
| } |
| |
| test_tryStatement_return_try_twoCatchesDoExit_noFinally() async { |
| _assertTrue(''' |
| try { return 1; } |
| on int catch (e, s) { return 1; } |
| on String catch (e, s) { return 1; }'''); |
| } |
| |
| test_tryStatement_return_try_twoCatchesDoNotExit() async { |
| _assertFalse(''' |
| try { return 1; } |
| on int catch (e, s) {} |
| on String catch (e, s) {} |
| finally {}'''); |
| } |
| |
| test_tryStatement_return_try_twoCatchesDoNotExit_noFinally() async { |
| _assertFalse(''' |
| try { return 1; } |
| on int catch (e, s) {} |
| on String catch (e, s) {}'''); |
| } |
| |
| test_tryStatement_return_try_twoCatchesMixed() async { |
| _assertFalse(''' |
| try { return 1; } |
| on int catch (e, s) {} |
| on String catch (e, s) { return 1; } |
| finally {}'''); |
| } |
| |
| test_tryStatement_return_try_twoCatchesMixed_noFinally() async { |
| _assertFalse(''' |
| try { return 1; } |
| on int catch (e, s) {} |
| on String catch (e, s) { return 1; }'''); |
| } |
| |
| test_variableDeclarationStatement_noInitializer() async { |
| _assertFalse("int i;"); |
| } |
| |
| test_variableDeclarationStatement_noThrow() async { |
| _assertFalse("int i = 0;"); |
| } |
| |
| test_variableDeclarationStatement_throw() async { |
| _assertTrue("int i = throw new Object();"); |
| } |
| |
| test_whileStatement_false_nonReturn() async { |
| _assertFalse("{ while (false) {} }"); |
| } |
| |
| test_whileStatement_throwCondition() async { |
| _assertTrue("{ while (throw '') {} }"); |
| } |
| |
| test_whileStatement_true_break() async { |
| _assertFalse("{ while (true) { break; } }"); |
| } |
| |
| test_whileStatement_true_break_and_throw() async { |
| _assertFalse("{ while (true) { if (1==1) break; throw 'T'; } }"); |
| } |
| |
| test_whileStatement_true_continue() async { |
| _assertTrue("{ while (true) { continue; } }"); |
| } |
| |
| test_whileStatement_true_continueWithLabel() async { |
| _assertTrue("{ x: while (true) { continue x; } }"); |
| } |
| |
| test_whileStatement_true_doStatement_scopeRequired() async { |
| _assertTrue("{ while (true) { x: do { continue x; } while (true); } }"); |
| } |
| |
| test_whileStatement_true_if_return() async { |
| _assertTrue("{ while (true) { if (true) {return null;} } }"); |
| } |
| |
| test_whileStatement_true_noBreak() async { |
| _assertTrue("{ while (true) {} }"); |
| } |
| |
| test_whileStatement_true_return() async { |
| _assertTrue("{ while (true) { return null; } }"); |
| } |
| |
| test_whileStatement_true_throw() async { |
| _assertTrue("{ while (true) { throw ''; } }"); |
| } |
| |
| void _assertFalse(String source) { |
| _assertHasReturn(false, source); |
| } |
| |
| void _assertHasReturn(bool expectedResult, String source) { |
| Statement statement = parseStatement(source, |
| enableLazyAssignmentOperators: enableLazyAssignmentOperators); |
| expect(ExitDetector.exits(statement), expectedResult); |
| } |
| |
| void _assertTrue(String source) { |
| _assertHasReturn(true, source); |
| } |
| } |
| |
| /** |
| * Tests for the [ExitDetector] that require that the AST be resolved. |
| * |
| * See [ExitDetectorTest] for tests that do not require the AST to be resolved. |
| */ |
| @reflectiveTest |
| class ExitDetectorTest2 extends ResolverTestCase { |
| test_forStatement_implicitTrue_breakWithLabel() async { |
| Source source = addSource(r''' |
| void f() { |
| x: for (;;) { |
| if (1 < 2) { |
| break x; |
| } |
| return; |
| } |
| } |
| '''); |
| _assertNthStatementDoesNotExit(source, 0); |
| } |
| |
| test_switch_withEnum_false_noDefault() async { |
| Source source = addSource(r''' |
| enum E { A, B } |
| String f(E e) { |
| var x; |
| switch (e) { |
| case A: |
| x = 'A'; |
| case B: |
| x = 'B'; |
| } |
| return x; |
| } |
| '''); |
| _assertNthStatementDoesNotExit(source, 1); |
| } |
| |
| test_switch_withEnum_false_withDefault() async { |
| Source source = addSource(r''' |
| enum E { A, B } |
| String f(E e) { |
| var x; |
| switch (e) { |
| case A: |
| x = 'A'; |
| default: |
| x = '?'; |
| } |
| return x; |
| } |
| '''); |
| _assertNthStatementDoesNotExit(source, 1); |
| } |
| |
| test_switch_withEnum_true_noDefault() async { |
| Source source = addSource(r''' |
| enum E { A, B } |
| String f(E e) { |
| switch (e) { |
| case A: |
| return 'A'; |
| case B: |
| return 'B'; |
| } |
| } |
| '''); |
| _assertNthStatementDoesNotExit(source, 0); |
| } |
| |
| test_switch_withEnum_true_withExitingDefault() async { |
| Source source = addSource(r''' |
| enum E { A, B } |
| String f(E e) { |
| switch (e) { |
| case A: |
| return 'A'; |
| default: |
| return '?'; |
| } |
| } |
| '''); |
| _assertNthStatementExits(source, 0); |
| } |
| |
| test_switch_withEnum_true_withNonExitingDefault() async { |
| Source source = addSource(r''' |
| enum E { A, B } |
| String f(E e) { |
| var x; |
| switch (e) { |
| case A: |
| return 'A'; |
| default: |
| x = '?'; |
| } |
| } |
| '''); |
| _assertNthStatementDoesNotExit(source, 1); |
| } |
| |
| test_whileStatement_breakWithLabel() async { |
| Source source = addSource(r''' |
| void f() { |
| x: while (true) { |
| if (1 < 2) { |
| break x; |
| } |
| return; |
| } |
| } |
| '''); |
| _assertNthStatementDoesNotExit(source, 0); |
| } |
| |
| test_whileStatement_breakWithLabel_afterExiting() async { |
| Source source = addSource(r''' |
| void f() { |
| x: while (true) { |
| return; |
| if (1 < 2) { |
| break x; |
| } |
| } |
| } |
| '''); |
| _assertNthStatementExits(source, 0); |
| } |
| |
| test_whileStatement_switchWithBreakWithLabel() async { |
| Source source = addSource(r''' |
| void f() { |
| x: while (true) { |
| switch (true) { |
| case false: break; |
| case true: break x; |
| } |
| } |
| } |
| '''); |
| _assertNthStatementDoesNotExit(source, 0); |
| } |
| |
| test_yieldStatement_plain() async { |
| Source source = addSource(r''' |
| void f() sync* { |
| yield 1; |
| } |
| '''); |
| _assertNthStatementDoesNotExit(source, 0); |
| } |
| |
| test_yieldStatement_star_plain() async { |
| Source source = addSource(r''' |
| void f() sync* { |
| yield* 1; |
| } |
| '''); |
| _assertNthStatementDoesNotExit(source, 0); |
| } |
| |
| test_yieldStatement_star_throw() async { |
| Source source = addSource(r''' |
| void f() sync* { |
| yield* throw ''; |
| } |
| '''); |
| _assertNthStatementExits(source, 0); |
| } |
| |
| test_yieldStatement_throw() async { |
| Source source = addSource(r''' |
| void f() sync* { |
| yield throw ''; |
| } |
| '''); |
| _assertNthStatementExits(source, 0); |
| } |
| |
| void _assertHasReturn(bool expectedResult, Source source, int n) { |
| LibraryElement element = resolve2(source); |
| CompilationUnit unit = resolveCompilationUnit(source, element); |
| FunctionDeclaration function = unit.declarations.last; |
| BlockFunctionBody body = function.functionExpression.body; |
| Statement statement = body.block.statements[n]; |
| expect(ExitDetector.exits(statement), expectedResult); |
| } |
| |
| // Assert that the [n]th statement in the last function declaration of |
| // [source] exits. |
| void _assertNthStatementDoesNotExit(Source source, int n) { |
| _assertHasReturn(false, source, n); |
| } |
| |
| // Assert that the [n]th statement in the last function declaration of |
| // [source] does not exit. |
| void _assertNthStatementExits(Source source, int n) { |
| _assertHasReturn(true, source, n); |
| } |
| } |
| |
| @reflectiveTest |
| class FileBasedSourceTest { |
| test_equals_false_differentFiles() async { |
| JavaFile file1 = FileUtilities2.createFile("/does/not/exist1.dart"); |
| JavaFile file2 = FileUtilities2.createFile("/does/not/exist2.dart"); |
| FileBasedSource source1 = new FileBasedSource(file1); |
| FileBasedSource source2 = new FileBasedSource(file2); |
| expect(source1 == source2, isFalse); |
| } |
| |
| test_equals_false_null() async { |
| JavaFile file = FileUtilities2.createFile("/does/not/exist1.dart"); |
| FileBasedSource source1 = new FileBasedSource(file); |
| expect(source1 == null, isFalse); |
| } |
| |
| test_equals_true() async { |
| JavaFile file1 = FileUtilities2.createFile("/does/not/exist.dart"); |
| JavaFile file2 = FileUtilities2.createFile("/does/not/exist.dart"); |
| FileBasedSource source1 = new FileBasedSource(file1); |
| FileBasedSource source2 = new FileBasedSource(file2); |
| expect(source1 == source2, isTrue); |
| } |
| |
| test_fileReadMode() async { |
| expect(FileBasedSource.fileReadMode('a'), 'a'); |
| expect(FileBasedSource.fileReadMode('a\n'), 'a\n'); |
| expect(FileBasedSource.fileReadMode('ab'), 'ab'); |
| expect(FileBasedSource.fileReadMode('abc'), 'abc'); |
| expect(FileBasedSource.fileReadMode('a\nb'), 'a\nb'); |
| expect(FileBasedSource.fileReadMode('a\rb'), 'a\rb'); |
| expect(FileBasedSource.fileReadMode('a\r\nb'), 'a\r\nb'); |
| } |
| |
| test_fileReadMode_changed() async { |
| FileBasedSource.fileReadMode = (String s) => s + 'xyz'; |
| expect(FileBasedSource.fileReadMode('a'), 'axyz'); |
| expect(FileBasedSource.fileReadMode('a\n'), 'a\nxyz'); |
| expect(FileBasedSource.fileReadMode('ab'), 'abxyz'); |
| expect(FileBasedSource.fileReadMode('abc'), 'abcxyz'); |
| FileBasedSource.fileReadMode = (String s) => s; |
| } |
| |
| test_fileReadMode_normalize_eol_always() async { |
| FileBasedSource.fileReadMode = |
| PhysicalResourceProvider.NORMALIZE_EOL_ALWAYS; |
| expect(FileBasedSource.fileReadMode('a'), 'a'); |
| |
| // '\n' -> '\n' as first, last and only character |
| expect(FileBasedSource.fileReadMode('\n'), '\n'); |
| expect(FileBasedSource.fileReadMode('a\n'), 'a\n'); |
| expect(FileBasedSource.fileReadMode('\na'), '\na'); |
| |
| // '\r\n' -> '\n' as first, last and only character |
| expect(FileBasedSource.fileReadMode('\r\n'), '\n'); |
| expect(FileBasedSource.fileReadMode('a\r\n'), 'a\n'); |
| expect(FileBasedSource.fileReadMode('\r\na'), '\na'); |
| |
| // '\r' -> '\n' as first, last and only character |
| expect(FileBasedSource.fileReadMode('\r'), '\n'); |
| expect(FileBasedSource.fileReadMode('a\r'), 'a\n'); |
| expect(FileBasedSource.fileReadMode('\ra'), '\na'); |
| |
| FileBasedSource.fileReadMode = (String s) => s; |
| } |
| |
| test_getEncoding() async { |
| SourceFactory factory = new SourceFactory( |
| [new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)]); |
| String fullPath = "/does/not/exist.dart"; |
| JavaFile file = FileUtilities2.createFile(fullPath); |
| FileBasedSource source = new FileBasedSource(file); |
| expect(factory.fromEncoding(source.encoding), source); |
| } |
| |
| test_getFullName() async { |
| String fullPath = "/does/not/exist.dart"; |
| JavaFile file = FileUtilities2.createFile(fullPath); |
| FileBasedSource source = new FileBasedSource(file); |
| expect(source.fullName, file.getAbsolutePath()); |
| } |
| |
| test_getShortName() async { |
| JavaFile file = FileUtilities2.createFile("/does/not/exist.dart"); |
| FileBasedSource source = new FileBasedSource(file); |
| expect(source.shortName, "exist.dart"); |
| } |
| |
| test_hashCode() async { |
| JavaFile file1 = FileUtilities2.createFile("/does/not/exist.dart"); |
| JavaFile file2 = FileUtilities2.createFile("/does/not/exist.dart"); |
| FileBasedSource source1 = new FileBasedSource(file1); |
| FileBasedSource source2 = new FileBasedSource(file2); |
| expect(source2.hashCode, source1.hashCode); |
| } |
| |
| test_isInSystemLibrary_contagious() async { |
| DartSdk sdk = (new _SimpleDartSdkTest()..setUp()).sdk; |
| UriResolver resolver = new DartUriResolver(sdk); |
| SourceFactory factory = new SourceFactory([resolver]); |
| // resolve dart:core |
| Source result = resolver.resolveAbsolute(Uri.parse("dart:core")); |
| expect(result, isNotNull); |
| expect(result.isInSystemLibrary, isTrue); |
| // system libraries reference only other system libraries |
| Source partSource = factory.resolveUri(result, "num.dart"); |
| expect(partSource, isNotNull); |
| expect(partSource.isInSystemLibrary, isTrue); |
| } |
| |
| test_isInSystemLibrary_false() async { |
| JavaFile file = FileUtilities2.createFile("/does/not/exist.dart"); |
| FileBasedSource source = new FileBasedSource(file); |
| expect(source, isNotNull); |
| expect(source.fullName, file.getAbsolutePath()); |
| expect(source.isInSystemLibrary, isFalse); |
| } |
| |
| test_issue14500() async { |
| // see https://code.google.com/p/dart/issues/detail?id=14500 |
| FileBasedSource source = new FileBasedSource( |
| FileUtilities2.createFile("/some/packages/foo:bar.dart")); |
| expect(source, isNotNull); |
| expect(source.exists(), isFalse); |
| } |
| |
| test_resolveRelative_file_fileName() async { |
| if (OSUtilities.isWindows()) { |
| // On Windows, the URI that is produced includes a drive letter, |
| // which I believe is not consistent across all machines that might run |
| // this test. |
| return; |
| } |
| JavaFile file = FileUtilities2.createFile("/a/b/test.dart"); |
| FileBasedSource source = new FileBasedSource(file); |
| expect(source, isNotNull); |
| Uri relative = resolveRelativeUri(source.uri, Uri.parse("lib.dart")); |
| expect(relative, isNotNull); |
| expect(relative.toString(), "file:///a/b/lib.dart"); |
| } |
| |
| test_resolveRelative_file_filePath() async { |
| if (OSUtilities.isWindows()) { |
| // On Windows, the URI that is produced includes a drive letter, |
| // which I believe is not consistent across all machines that might run |
| // this test. |
| return; |
| } |
| JavaFile file = FileUtilities2.createFile("/a/b/test.dart"); |
| FileBasedSource source = new FileBasedSource(file); |
| expect(source, isNotNull); |
| Uri relative = resolveRelativeUri(source.uri, Uri.parse("c/lib.dart")); |
| expect(relative, isNotNull); |
| expect(relative.toString(), "file:///a/b/c/lib.dart"); |
| } |
| |
| test_resolveRelative_file_filePathWithParent() async { |
| if (OSUtilities.isWindows()) { |
| // On Windows, the URI that is produced includes a drive letter, which I |
| // believe is not consistent across all machines that might run this test. |
| return; |
| } |
| JavaFile file = FileUtilities2.createFile("/a/b/test.dart"); |
| FileBasedSource source = new FileBasedSource(file); |
| expect(source, isNotNull); |
| Uri relative = resolveRelativeUri(source.uri, Uri.parse("../c/lib.dart")); |
| expect(relative, isNotNull); |
| expect(relative.toString(), "file:///a/c/lib.dart"); |
| } |
| |
| test_system() async { |
| JavaFile file = FileUtilities2.createFile("/does/not/exist.dart"); |
| FileBasedSource source = new FileBasedSource(file, Uri.parse("dart:core")); |
| expect(source, isNotNull); |
| expect(source.fullName, file.getAbsolutePath()); |
| expect(source.isInSystemLibrary, isTrue); |
| } |
| } |
| |
| @reflectiveTest |
| class ResolveRelativeUriTest { |
| test_resolveRelative_dart_dartUri() async { |
| _assertResolve('dart:foo', 'dart:bar', 'dart:bar'); |
| } |
| |
| test_resolveRelative_dart_fileName() async { |
| _assertResolve('dart:test', 'lib.dart', 'dart:test/lib.dart'); |
| } |
| |
| test_resolveRelative_dart_filePath() async { |
| _assertResolve('dart:test', 'c/lib.dart', 'dart:test/c/lib.dart'); |
| } |
| |
| test_resolveRelative_dart_filePathWithParent() async { |
| _assertResolve( |
| 'dart:test/b/test.dart', '../c/lib.dart', 'dart:test/c/lib.dart'); |
| } |
| |
| test_resolveRelative_package_dartUri() async { |
| _assertResolve('package:foo/bar.dart', 'dart:test', 'dart:test'); |
| } |
| |
| test_resolveRelative_package_emptyPath() async { |
| _assertResolve('package:foo/bar.dart', '', 'package:foo/bar.dart'); |
| } |
| |
| test_resolveRelative_package_fileName() async { |
| _assertResolve('package:b/test.dart', 'lib.dart', 'package:b/lib.dart'); |
| } |
| |
| test_resolveRelative_package_fileNameWithoutPackageName() async { |
| _assertResolve('package:test.dart', 'lib.dart', 'package:lib.dart'); |
| } |
| |
| test_resolveRelative_package_filePath() async { |
| _assertResolve('package:b/test.dart', 'c/lib.dart', 'package:b/c/lib.dart'); |
| } |
| |
| test_resolveRelative_package_filePathWithParent() async { |
| _assertResolve( |
| 'package:a/b/test.dart', '../c/lib.dart', 'package:a/c/lib.dart'); |
| } |
| |
| void _assertResolve(String baseStr, String containedStr, String expectedStr) { |
| Uri base = Uri.parse(baseStr); |
| Uri contained = Uri.parse(containedStr); |
| Uri result = resolveRelativeUri(base, contained); |
| expect(result, isNotNull); |
| expect(result.toString(), expectedStr); |
| } |
| } |
| |
| @deprecated |
| @reflectiveTest |
| class SDKLibrariesReaderTest extends EngineTestCase { |
| test_readFrom_dart2js() async { |
| LibraryMap libraryMap = new SdkLibrariesReader(true) |
| .readFromFile(FileUtilities2.createFile("/libs.dart"), r''' |
| final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> { |
| 'first' : const LibraryInfo( |
| 'first/first.dart', |
| categories: 'Client', |
| documented: true, |
| platforms: VM_PLATFORM, |
| dart2jsPath: 'first/first_dart2js.dart'), |
| };'''); |
| expect(libraryMap, isNotNull); |
| expect(libraryMap.size(), 1); |
| SdkLibrary first = libraryMap.getLibrary("dart:first"); |
| expect(first, isNotNull); |
| expect(first.category, "Client"); |
| expect(first.path, "first/first_dart2js.dart"); |
| expect(first.shortName, "dart:first"); |
| expect(first.isDart2JsLibrary, false); |
| expect(first.isDocumented, true); |
| expect(first.isImplementation, false); |
| expect(first.isVmLibrary, true); |
| } |
| |
| test_readFrom_empty() async { |
| LibraryMap libraryMap = new SdkLibrariesReader(false) |
| .readFromFile(FileUtilities2.createFile("/libs.dart"), ""); |
| expect(libraryMap, isNotNull); |
| expect(libraryMap.size(), 0); |
| } |
| |
| test_readFrom_normal() async { |
| LibraryMap libraryMap = new SdkLibrariesReader(false) |
| .readFromFile(FileUtilities2.createFile("/libs.dart"), r''' |
| final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> { |
| 'first' : const LibraryInfo( |
| 'first/first.dart', |
| categories: 'Client', |
| documented: true, |
| platforms: VM_PLATFORM), |
| |
| 'second' : const LibraryInfo( |
| 'second/second.dart', |
| categories: 'Server', |
| documented: false, |
| implementation: true, |
| platforms: 0), |
| };'''); |
| expect(libraryMap, isNotNull); |
| expect(libraryMap.size(), 2); |
| SdkLibrary first = libraryMap.getLibrary("dart:first"); |
| expect(first, isNotNull); |
| expect(first.category, "Client"); |
| expect(first.path, "first/first.dart"); |
| expect(first.shortName, "dart:first"); |
| expect(first.isDart2JsLibrary, false); |
| expect(first.isDocumented, true); |
| expect(first.isImplementation, false); |
| expect(first.isVmLibrary, true); |
| SdkLibrary second = libraryMap.getLibrary("dart:second"); |
| expect(second, isNotNull); |
| expect(second.category, "Server"); |
| expect(second.path, "second/second.dart"); |
| expect(second.shortName, "dart:second"); |
| expect(second.isDart2JsLibrary, false); |
| expect(second.isDocumented, false); |
| expect(second.isImplementation, true); |
| expect(second.isVmLibrary, false); |
| } |
| } |
| |
| @reflectiveTest |
| class UriKindTest { |
| test_fromEncoding() async { |
| expect(UriKind.fromEncoding(0x64), same(UriKind.DART_URI)); |
| expect(UriKind.fromEncoding(0x66), same(UriKind.FILE_URI)); |
| expect(UriKind.fromEncoding(0x70), same(UriKind.PACKAGE_URI)); |
| expect(UriKind.fromEncoding(0x58), same(null)); |
| } |
| |
| test_getEncoding() async { |
| expect(UriKind.DART_URI.encoding, 0x64); |
| expect(UriKind.FILE_URI.encoding, 0x66); |
| expect(UriKind.PACKAGE_URI.encoding, 0x70); |
| } |
| } |
| |
| class _SimpleDartSdkTest { |
| MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); |
| String coreCorePath; |
| String coreIntPath; |
| DartSdk sdk; |
| |
| void setUp() { |
| Folder sdkFolder = |
| resourceProvider.newFolder(resourceProvider.convertPath('/sdk')); |
| resourceProvider.newFile( |
| resourceProvider.convertPath( |
| '/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart'), |
| ''' |
| const Map<String, LibraryInfo> libraries = const { |
| "core": const LibraryInfo("core/core.dart") |
| }; |
| '''); |
| coreCorePath = resourceProvider.convertPath('/sdk/lib/core/core.dart'); |
| resourceProvider.newFile(coreCorePath, ''' |
| library dart.core; |
| part 'int.dart'; |
| '''); |
| coreIntPath = resourceProvider.convertPath('/sdk/lib/core/int.dart'); |
| resourceProvider.newFile(coreIntPath, ''' |
| part of dart.core; |
| '''); |
| sdk = new FolderBasedDartSdk(resourceProvider, sdkFolder); |
| } |
| } |
| |
| class _SourceMock implements Source { |
| @override |
| Uri uri; |
| |
| @override |
| noSuchMethod(Invocation invocation) { |
| throw new StateError('Unexpected invocation of ${invocation.memberName}'); |
| } |
| } |