| // Copyright (c) 2017, 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 "package:expect/expect.dart"; |
| import "package:kernel/ast.dart"; |
| import "package:kernel/core_types.dart"; |
| import "package:kernel/testing/mock_sdk_program.dart"; |
| import "package:kernel/text/ast_to_text.dart"; |
| import "package:kernel/transformations/erasure.dart"; |
| |
| void main([List<String> arguments = const []]) { |
| new Tester().testLocalFunction(); |
| } |
| |
| class Tester { |
| final Program program; |
| |
| final Library library; |
| |
| final Procedure mainMethod; |
| |
| final CoreTypes coreTypes; |
| |
| static final Uri base = |
| new Uri(scheme: "org.dartlang.kernel", host: "", path: "/"); |
| |
| Tester.internal(this.program, this.library, this.mainMethod) |
| : coreTypes = new CoreTypes(program); |
| |
| factory Tester() { |
| Program program = createMockSdkProgram(); |
| Library library = new Library(base.resolve("main.dart"))..parent = program; |
| Procedure mainMethod = buildProcedure("main"); |
| library.addMember(mainMethod); |
| program.libraries.add(library); |
| program.mainMethod = mainMethod; |
| return new Tester.internal(program, library, mainMethod); |
| } |
| |
| void addStatement(Statement statement) { |
| Block body = mainMethod.function.body; |
| body.statements.add(statement); |
| statement.parent = body; |
| } |
| |
| void testLocalFunction() { |
| FunctionDeclaration fDeclaration = buildFunctionDeclaration( |
| "f", buildFunctionNodeWithTypesAndParameters()); |
| FunctionExpression functionExpression = |
| new FunctionExpression(buildFunctionNodeWithTypesAndParameters()); |
| |
| addStatement(fDeclaration); |
| addStatement(new ExpressionStatement(functionExpression)); |
| Expect.stringEquals( |
| "<T extends dynamic, S extends dart.core::List<T>>(S) → T", |
| debugNodeToString(fDeclaration.variable.type).trim()); |
| Expect.stringEquals( |
| "<T extends dynamic, S extends dart.core::List<T>>(S) → T", |
| debugNodeToString(functionExpression.getStaticType(null)).trim()); |
| transformProgram(coreTypes, program); |
| Expect.stringEquals("(dart.core::List<dynamic>) → dynamic", |
| debugNodeToString(fDeclaration.variable.type).trim()); |
| Expect.stringEquals("(dart.core::List<dynamic>) → dynamic", |
| debugNodeToString(functionExpression.getStaticType(null)).trim()); |
| } |
| |
| /// Builds this function: `f<T, S extends List<T>>(S argument) → T {}`. |
| FunctionNode buildFunctionNodeWithTypesAndParameters() { |
| TypeParameter tVariable = new TypeParameter("T", const DynamicType()); |
| TypeParameter sVariable = new TypeParameter("S", const DynamicType()); |
| TypeParameterType tType = new TypeParameterType(tVariable); |
| TypeParameterType sType = new TypeParameterType(sVariable); |
| sVariable.bound = new InterfaceType(coreTypes.listClass, <DartType>[tType]); |
| return new FunctionNode(buildBlock(), |
| positionalParameters: <VariableDeclaration>[ |
| new VariableDeclaration("argument", type: sType), |
| ], |
| typeParameters: <TypeParameter>[tVariable, sVariable], |
| returnType: tType); |
| } |
| |
| static Block buildBlock([List<Statement> statements]) { |
| return new Block(statements ?? <Statement>[]); |
| } |
| |
| static FunctionNode buildFunction([Statement body]) { |
| return new FunctionNode(body ?? buildBlock()); |
| } |
| |
| static Procedure buildProcedure(String name, [FunctionNode function]) { |
| return new Procedure( |
| new Name(name), ProcedureKind.Method, function ?? buildFunction()); |
| } |
| |
| static FunctionDeclaration buildFunctionDeclaration( |
| String name, FunctionNode function) { |
| return new FunctionDeclaration( |
| new VariableDeclaration(name, |
| type: function.functionType, isFinal: true), |
| function); |
| } |
| } |