| Index: packages/analyzer/test/utils.dart
|
| diff --git a/packages/analyzer/test/utils.dart b/packages/analyzer/test/utils.dart
|
| index 7c9fbe01d274542be37c6747da69fa145036ff6b..3ce44f65670aff16ea9d60e4e75ac1d0a8de26bd 100644
|
| --- a/packages/analyzer/test/utils.dart
|
| +++ b/packages/analyzer/test/utils.dart
|
| @@ -4,11 +4,299 @@
|
|
|
| library analyzer.test.utils;
|
|
|
| -import 'package:analyzer/src/generated/java_io.dart';
|
| +import 'package:analyzer/dart/ast/ast.dart';
|
| +import 'package:analyzer/dart/element/element.dart';
|
| +import 'package:analyzer/dart/element/type.dart';
|
| +import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
|
| import 'package:path/path.dart' as path;
|
| import 'package:unittest/unittest.dart';
|
|
|
| -void initializeTestEnvironment() {
|
| +void initializeTestEnvironment([path.Context context]) {
|
| 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.
|
| + */
|
| +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 {
|
| + /**
|
| + * 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 element of the field with the given [fieldName] in the class
|
| + * with the given [className] in the given compilation [unit].
|
| + */
|
| + static FieldElement getFieldInClassElement(
|
| + CompilationUnit unit, String className, String fieldName) {
|
| + return getFieldInClass(unit, className, fieldName)?.name?.staticElement;
|
| + }
|
| +
|
| + /**
|
| + * 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;
|
| + }
|
| +
|
| + /**
|
| + * Return the top-level variable element with the given [name].
|
| + */
|
| + static TopLevelVariableElement getTopLevelVariableElement(
|
| + CompilationUnit unit, String name) {
|
| + return getTopLevelVariable(unit, name)?.name?.staticElement;
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Class for compositionally building up assertions on types
|
| + */
|
| +class TypeAssertions {
|
| + // TODO(leafp): Make these matchers.
|
| + // https://www.dartdocs.org/documentation/matcher/0.12.0%2B1/matcher/Matcher-class.html
|
| +
|
| + /* 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
|
| + * 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);
|
| }
|
|
|