Chromium Code Reviews| Index: pkg/analyzer/test/utils.dart |
| diff --git a/pkg/analyzer/test/utils.dart b/pkg/analyzer/test/utils.dart |
| index 7c9fbe01d274542be37c6747da69fa145036ff6b..12cf112210451bb1ca73dc1f0e112d8d8c88beec 100644 |
| --- a/pkg/analyzer/test/utils.dart |
| +++ b/pkg/analyzer/test/utils.dart |
| @@ -4,7 +4,10 @@ |
| library analyzer.test.utils; |
| +import 'package:analyzer/src/generated/ast.dart'; |
| +import 'package:analyzer/src/generated/element.dart'; |
| import 'package:analyzer/src/generated/java_io.dart'; |
| +import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
| import 'package:path/path.dart' as path; |
| import 'package:unittest/unittest.dart'; |
| @@ -12,3 +15,246 @@ void initializeTestEnvironment() { |
| groupSep = ' | '; |
| JavaFile.pathContext = path.posix; |
| } |
| + |
| +/** The type of an assertion which asserts properties of [T]s. |
| + */ |
| +typedef void Asserter<T>(T type); |
| + |
| +/** The type of a function which given an [S], builds an assertion over [T]s. |
| + */ |
| +typedef Asserter<T> AsserterBuilder<S, T>(S arg); |
| + |
| +/** The type of a function which given an [S0] and an S1, builds an assertion over [T]s. |
|
Jennifer Messerly
2015/11/23 22:11:58
long line (& a few below)
unfortunately dartfmt w
Leaf
2015/12/01 21:49:12
Done.
|
| + */ |
| +typedef Asserter<T> AsserterBuilder2<S0, S1, T>(S0 arg0, S1 arg1); |
| + |
| +/** The type of a function which given an [R] returns an [AsserterBuilder] over |
| + * [S]s and [T]s. That is, it returns a function which given an [S], returns |
| + * a function over [T]s. |
| + */ |
| +typedef AsserterBuilder<S, T> AsserterBuilderBuilder<R, S, T>(R arg); |
| + |
| +class AstFinder { |
|
scheglov
2015/11/21 06:31:35
Could you please move the methods of AstFinder int
Brian Wilkerson
2015/11/21 16:12:22
I'm not a fan of top-level functions; I'd actually
Leaf
2015/11/24 19:32:12
Hmm, I was really annoyed that moving these from l
Brian Wilkerson
2015/11/24 21:17:57
It isn't my favorite solution, but I'm not going t
Leaf
2015/12/01 21:49:12
Ok, leaving as is for now.
|
| + /** |
| + * Return the declaration of the class with the given [className] in the given |
| + * compilation [unit]. |
| + */ |
| + static ClassDeclaration getClass(CompilationUnit unit, String className) { |
| + NodeList<CompilationUnitMember> unitMembers = unit.declarations; |
| + for (CompilationUnitMember unitMember in unitMembers) { |
| + if (unitMember is ClassDeclaration && unitMember.name.name == className) { |
| + return unitMember; |
| + } |
| + } |
| + fail('No class named $className in ${unit.element.source}'); |
| + return null; |
| + } |
| + |
| + /** |
| + * Return the declaration of the constructor with the given [constructorName] in |
| + * the class with the given [className] in the given compilation [unit]. If |
| + * constructorName is null, return the default constructor; |
| + */ |
| + static ConstructorDeclaration getConstructorInClass( |
| + CompilationUnit unit, String className, String constructorName) { |
| + ClassDeclaration unitMember = getClass(unit, className); |
| + NodeList<ClassMember> classMembers = unitMember.members; |
| + for (ClassMember classMember in classMembers) { |
| + if (classMember is ConstructorDeclaration) { |
| + if (classMember.name?.name == constructorName) { |
| + return classMember; |
| + } |
| + } |
| + } |
| + fail('No constructor named $constructorName in $className'); |
| + return null; |
| + } |
| + |
| + /** |
| + * Return the declaration of the field with the given [fieldName] in the class |
| + * with the given [className] in the given compilation [unit]. |
| + */ |
| + static VariableDeclaration getFieldInClass( |
| + CompilationUnit unit, String className, String fieldName) { |
| + ClassDeclaration unitMember = getClass(unit, className); |
| + NodeList<ClassMember> classMembers = unitMember.members; |
| + for (ClassMember classMember in classMembers) { |
| + if (classMember is FieldDeclaration) { |
| + NodeList<VariableDeclaration> fields = classMember.fields.variables; |
| + for (VariableDeclaration field in fields) { |
| + if (field.name.name == fieldName) { |
| + return field; |
| + } |
| + } |
| + } |
| + } |
| + fail('No field named $fieldName in $className'); |
| + return null; |
| + } |
| + |
| + /** |
| + * Return the declaration of the method with the given [methodName] in the |
| + * class with the given [className] in the given compilation [unit]. |
| + */ |
| + static MethodDeclaration getMethodInClass( |
| + CompilationUnit unit, String className, String methodName) { |
| + ClassDeclaration unitMember = getClass(unit, className); |
| + NodeList<ClassMember> classMembers = unitMember.members; |
| + for (ClassMember classMember in classMembers) { |
| + if (classMember is MethodDeclaration) { |
| + if (classMember.name.name == methodName) { |
| + return classMember; |
| + } |
| + } |
| + } |
| + fail('No method named $methodName in $className'); |
| + return null; |
| + } |
| + |
| + /** |
| + * Return the statements in the body of a the method with the given |
| + * [methodName] in the class with the given [className] in the given |
| + * compilation [unit]. |
| + */ |
| + static List<Statement> getStatementsInMethod( |
| + CompilationUnit unit, String className, String methodName) { |
| + MethodDeclaration method = getMethodInClass(unit, className, methodName); |
| + BlockFunctionBody body = method.body; |
| + return body.block.statements; |
| + } |
| + |
| + /** |
| + * Return the statements in the body of the top-level function with the given |
| + * [functionName] in the given compilation [unit]. |
| + */ |
| + static List<Statement> getStatementsInTopLevelFunction( |
| + CompilationUnit unit, String functionName) { |
| + FunctionDeclaration function = getTopLevelFunction(unit, functionName); |
| + BlockFunctionBody body = function.functionExpression.body; |
| + return body.block.statements; |
| + } |
| + |
| + /** |
| + * Return the declaration of the top-level function with the given |
| + * [functionName] in the given compilation [unit]. |
| + */ |
| + static FunctionDeclaration getTopLevelFunction( |
| + CompilationUnit unit, String functionName) { |
| + NodeList<CompilationUnitMember> unitMembers = unit.declarations; |
| + for (CompilationUnitMember unitMember in unitMembers) { |
| + if (unitMember is FunctionDeclaration) { |
| + if (unitMember.name.name == functionName) { |
| + return unitMember; |
| + } |
| + } |
| + } |
| + fail('No toplevel function named $functionName found'); |
| + return null; |
| + } |
| + |
| + /** |
| + * Return the declaration of the top-level variable with the given |
| + * [variableName] in the given compilation [unit]. |
| + */ |
| + static VariableDeclaration getTopLevelVariable( |
| + CompilationUnit unit, String variableName) { |
| + NodeList<CompilationUnitMember> unitMembers = unit.declarations; |
| + for (CompilationUnitMember unitMember in unitMembers) { |
| + if (unitMember is TopLevelVariableDeclaration) { |
| + NodeList<VariableDeclaration> variables = |
| + unitMember.variables.variables; |
| + for (VariableDeclaration variable in variables) { |
| + if (variable.name.name == variableName) { |
| + return variable; |
| + } |
| + } |
| + } |
| + } |
| + fail('No toplevel variable named $variableName found'); |
| + return null; |
| + } |
| +} |
| + |
| +/** Class for compositionally building up assertions on types |
| + */ |
| +class TypeAssertions { |
|
Jennifer Messerly
2015/11/23 22:11:58
note: it'd be slightly nicer to make these be Matc
Leaf
2015/12/01 21:49:12
Added TODO. Nice to know
|
| + /* Provides primitive types for basic type assertions */ |
| + final TypeProvider _typeProvider; |
| + |
| + TypeAssertions(this._typeProvider); |
| + |
| + /** Primitive assertion for the dynamic type */ |
| + Asserter<DartType> get isDynamic => isType(_typeProvider.dynamicType); |
| + |
| + /** Primitive assertion for the int type */ |
| + Asserter<DartType> get isInt => isType(_typeProvider.intType); |
| + |
| + /** Primitive assertion for the list type |
| + */ |
| + Asserter<DartType> get isList => sameElement(_typeProvider.listType); |
| + |
| + /** Primitive assertion for the map type |
| + */ |
| + Asserter<DartType> get isMap => sameElement(_typeProvider.mapType); |
| + |
| + /** Primitive assertion for the num type */ |
| + Asserter<DartType> get isNum => isType(_typeProvider.numType); |
| + |
| + /** Primitive assertion for the string type */ |
| + Asserter<DartType> get isString => isType(_typeProvider.stringType); |
| + |
| + /** Given a type, produce an assertion that a type has the same element. |
| + */ |
| + Asserter<DartType> hasElement(Element element) => |
| + (DartType type) => expect(element, same(type.element)); |
| + |
| +/** Given assertions for the argument and return types, produce an |
|
Brian Wilkerson
2015/11/21 16:12:22
Format the file?
Leaf
2015/12/01 21:49:12
Filed https://github.com/dart-lang/dart_style/issu
|
| + * assertion over unary function types. |
| + */ |
| + Asserter<DartType> isFunction2Of( |
| + Asserter<DartType> argType, Asserter<DartType> returnType) => |
| + (DartType type) { |
| + FunctionType fType = (type as FunctionType); |
| + argType(fType.normalParameterTypes[0]); |
| + returnType(fType.returnType); |
| + }; |
| + |
| + /** Given an assertion for the base type and assertions over the type |
| + * parameters, produce an assertion over instantations. |
| + */ |
| + AsserterBuilder<List<Asserter<DartType>>, DartType> isInstantiationOf( |
| + Asserter<DartType> baseAssert) => |
| + (List<Asserter<DartType>> argAsserts) => (DartType type) { |
| + InterfaceType t = (type as InterfaceType); |
| + baseAssert(t); |
| + List<DartType> typeArguments = t.typeArguments; |
| + expect(typeArguments, hasLength(argAsserts.length)); |
| + for (int i = 0; i < typeArguments.length; i++) { |
| + argAsserts[i](typeArguments[i]); |
| + } |
| + }; |
| + |
| + /** Assert that a type is the List type, and that the given assertion holds |
| + * over the type parameter. |
| + */ |
| + Asserter<InterfaceType> isListOf(Asserter<DartType> argAssert) => |
| + isInstantiationOf(isList)([argAssert]); |
| + |
| + /** Assert that a type is the Map type, and that the given assertions hold |
| + * over the type parameters. |
| + */ |
| + Asserter<InterfaceType> isMapOf( |
| + Asserter<DartType> argAssert0, Asserter<DartType> argAssert1) => |
| + isInstantiationOf(isMap)([argAssert0, argAssert1]); |
| + |
| + /** Assert that one type is the same as another |
| + */ |
| + Asserter<DartType> isType(DartType argument) => (DartType t) { |
| + expect(t, same(argument)); |
| + }; |
| + |
| + /** Given a type, produce an assertion that a type has the same element. |
| + */ |
| + Asserter<DartType> sameElement(DartType elementType) => |
| + hasElement(elementType.element); |
| +} |