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); |
+} |