// Copyright (c) 2018, 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 'dart:io' show File;

import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/fasta/ast_body_builder.dart';
import 'package:analyzer/src/generated/parser.dart' as analyzer;
import 'package:analyzer/src/generated/resolver.dart';
import "package:front_end/src/api_prototype/front_end.dart";
import "package:front_end/src/api_prototype/memory_file_system.dart";
import "package:front_end/src/base/processed_options.dart";
import "package:front_end/src/compute_platform_binaries_location.dart";
import 'package:front_end/src/fasta/compiler_context.dart';
import 'package:front_end/src/fasta/constant_context.dart';
import 'package:front_end/src/fasta/dill/dill_target.dart';
import "package:front_end/src/fasta/fasta_codes.dart";
import 'package:front_end/src/fasta/kernel/forest.dart' hide Identifier;
import 'package:front_end/src/fasta/kernel/kernel_builder.dart';
import "package:front_end/src/fasta/kernel/kernel_target.dart";
import 'package:front_end/src/fasta/modifier.dart' as Modifier;
import 'package:front_end/src/fasta/parser/async_modifier.dart';
import 'package:front_end/src/fasta/parser/parser.dart';
import 'package:front_end/src/fasta/scanner.dart';
import 'package:front_end/src/fasta/ticker.dart';
import 'package:front_end/src/fasta/type_inference/type_inferrer.dart';
import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart';
import 'package:front_end/src/fasta/uri_translator_impl.dart';
import 'package:kernel/class_hierarchy.dart' as kernel;
import 'package:kernel/core_types.dart' as kernel;
import 'package:kernel/kernel.dart' as kernel;
import 'package:test/test.dart';

import '../../generated/parser_test.dart';
import '../../generated/test_support.dart';

Element _buildElement(kernel.Class coreType) {
  ClassElementImpl element =
      new ClassElementImpl(coreType.name, coreType.fileOffset);
  element.typeParameters = coreType.typeParameters.map((parameter) {
    TypeParameterElementImpl element =
        new TypeParameterElementImpl(parameter.name, parameter.fileOffset);
    element.type = new TypeParameterTypeImpl(element);
    return element;
  }).toList();
  return element;
}

class CompilerTestContext extends CompilerContext {
  KernelTarget kernelTarget;
  TypeProvider _typeProvider;

  CompilerTestContext(ProcessedOptions options) : super(options);

  Uri get entryPoint => options.inputs.single;

  static Future<T> runWithTestOptions<T>(
      Future<T> action(CompilerTestContext c)) async {
    // TODO(danrubel): Consider HybridFileSystem.
    final MemoryFileSystem fs =
        new MemoryFileSystem(Uri.parse("org-dartlang-test:///"));

    /// The custom URI used to locate the dill file in the MemoryFileSystem.
    final Uri sdkSummary = fs.currentDirectory.resolve("vm_platform.dill");

    /// The in memory test code URI
    final Uri entryPoint = fs.currentDirectory.resolve("main.dart");

    // Read the dill file containing kernel platform summaries into memory.
    List<int> sdkSummaryBytes = await new File.fromUri(
            computePlatformBinariesLocation().resolve("vm_platform.dill"))
        .readAsBytes();
    fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryBytes);

    final CompilerOptions optionBuilder = new CompilerOptions()
      ..strongMode = false // TODO(danrubel): enable strong mode.
      ..reportMessages = true
      ..verbose = false
      ..fileSystem = fs
      ..sdkSummary = sdkSummary
      ..onProblem = (FormattedMessage problem, Severity severity,
          List<FormattedMessage> context) {
        // TODO(danrubel): Capture problems and check against expectations.
//        print(problem.formatted);
      };

    final ProcessedOptions options =
        new ProcessedOptions(optionBuilder, [entryPoint]);

    UriTranslatorImpl uriTranslator = await options.getUriTranslator();

    return await new CompilerTestContext(options)
        .runInContext<T>((CompilerContext _c) async {
      CompilerTestContext c = _c;
      DillTarget dillTarget = new DillTarget(
          new Ticker(isVerbose: false), uriTranslator, options.target);

      c.kernelTarget = new KernelTarget(fs, true, dillTarget, uriTranslator);

      // Load the dill file containing platform code.
      dillTarget.loader.read(Uri.parse('dart:core'), -1, fileUri: sdkSummary);
      kernel.Component sdkComponent =
          kernel.loadComponentFromBytes(sdkSummaryBytes);
      dillTarget.loader
          .appendLibraries(sdkComponent, byteCount: sdkSummaryBytes.length);
      await dillTarget.buildOutlines();
      await c.kernelTarget.buildOutlines();
      c.kernelTarget.computeCoreTypes();
      assert(c.kernelTarget.loader.coreTypes != null);

      // Initialize the typeProvider if types should be resolved.
      Map<String, Element> map = <String, Element>{};
      var coreTypes = c.kernelTarget.loader.coreTypes;
      for (var coreType in [
        coreTypes.boolClass,
        coreTypes.doubleClass,
        coreTypes.functionClass,
        coreTypes.futureClass,
        coreTypes.futureOrClass,
        coreTypes.intClass,
        coreTypes.iterableClass,
        coreTypes.iteratorClass,
        coreTypes.listClass,
        coreTypes.mapClass,
        coreTypes.nullClass,
        coreTypes.numClass,
        coreTypes.objectClass,
        coreTypes.stackTraceClass,
        coreTypes.streamClass,
        coreTypes.stringClass,
        coreTypes.symbolClass,
        coreTypes.typeClass
      ]) {
        map[coreType.name] = _buildElement(coreType);
      }
      Namespace namespace = new Namespace(map);
      c._typeProvider =
          new TypeProviderImpl.forNamespaces(namespace, namespace);

      T result;
      Completer<T> completer = new Completer<T>();
      // Since we're using `package:test_reflective_loader`, we can't rely on
      // normal async behavior, as `defineReflectiveSuite` doesn't return a
      // future. However, since it's built on top of `package:test`, we can
      // obtain a future that completes when all the tests are done using
      // `tearDownAll`. This allows this function to complete no earlier than
      // when the tests are done. This is important, as we don't want to call
      // `CompilerContext.clear` before then.
      tearDownAll(() => completer.complete(result));
      result = await action(c);
      return completer.future;
    });
  }

  static CompilerTestContext get current => CompilerContext.current;
}

/// Implementation of [AbstractParserTestCase] specialized for testing building
/// Analyzer AST using the fasta [Forest] API.
class FastaBodyBuilderTestCase extends Object
    with ParserTestHelpers
    implements AbstractParserTestCase {
  final bool resolveTypes;

  String content;

  /// The expected offset of the next token to be parsed after the parser has
  /// finished parsing, or `null` (the default) if EOF is expected.
  int expectedEndOffset;

  @override
  void set enableGenericMethodComments(_) {
    // Ignored.
  }

  FastaBodyBuilderTestCase(this.resolveTypes);

  analyzer.Parser get parser => new ParserProxy(this);

  TypeProvider get typeProvider => CompilerTestContext.current._typeProvider;

  bool get usingFastaParser => true;

  @override
  void assertNoErrors() {
    // TODO(brianwilkerson) Implement this.
  }

  void createParser(String content, {int expectedEndOffset}) {
    this.content = content;
    this.expectedEndOffset = expectedEndOffset;
  }

  @override
  void expectNotNullIfNoErrors(Object result) {
    // TODO(brianwilkerson) Implement this.
  }

  @override
  ExpectedError expectedError(ErrorCode code, int offset, int length) {
    return new ExpectedError(code, offset, length);
  }

  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);

  @override
  Expression parseAdditiveExpression(String code) {
    return parseExpression(code);
  }

  @override
  Expression parseAssignableExpression(String code, bool primaryAllowed) {
    return parseExpression(code);
  }

  @override
  Expression parseAssignableSelector(String code, bool optional,
      {bool allowConditional: true}) {
    return parseExpression(code);
  }

  @override
  AwaitExpression parseAwaitExpression(String code) {
    return parseExpression(code, inAsync: true);
  }

  @override
  Expression parseBitwiseAndExpression(String code) {
    return parseExpression(code);
  }

  @override
  Expression parseBitwiseOrExpression(String code) {
    return parseExpression(code);
  }

  @override
  Expression parseBitwiseXorExpression(String code) {
    return parseExpression(code);
  }

  @override
  Expression parseCascadeSection(String code) {
    return parseExpression(code);
  }

  @override
  CompilationUnit parseCompilationUnit(String source,
      {List<ErrorCode> codes, List<ExpectedError> errors}) {
    return _parse(source, (parser, token) => parser.parseUnit(token.next));
  }

  @override
  ConditionalExpression parseConditionalExpression(String code) {
    return parseExpression(code);
  }

  @override
  Expression parseConstExpression(String code) {
    return parseExpression(code);
  }

  @override
  ConstructorInitializer parseConstructorInitializer(String code) {
    throw new UnimplementedError();
  }

  @override
  CompilationUnit parseDirectives(String source,
      [List<ErrorCode> errorCodes = const <ErrorCode>[]]) {
    return parseCompilationUnit(content, codes: errorCodes);
  }

  @override
  BinaryExpression parseEqualityExpression(String code) {
    return parseExpression(code);
  }

  @override
  Expression parseExpression(String source,
      {List<ErrorCode> codes,
      List<ExpectedError> errors,
      int expectedEndOffset,
      bool inAsync: false,
      bool inCatchBlock: false}) {
    // TODO(brianwilkerson) Check error codes.
    Object result = _parse(
        source, (parser, token) => parser.parseExpression(token),
        inAsync: inAsync, inCatchBlock: inCatchBlock);
    if (result is Generator) {
      result = (result as Generator).buildForEffect();
    }
    if (result is! Expression) {
      throw new StateError('Expected Expression, found ${result.runtimeType}');
    }
    return result;
  }

  @override
  List<Expression> parseExpressionList(String code) {
    throw new UnimplementedError();
  }

  @override
  Expression parseExpressionWithoutCascade(String code) {
    return parseExpression(code);
  }

  @override
  FormalParameter parseFormalParameter(String code, ParameterKind kind,
      {List<ErrorCode> errorCodes: const <ErrorCode>[]}) {
    throw new UnimplementedError();
  }

  @override
  FormalParameterList parseFormalParameterList(String code,
      {bool inFunctionType: false,
      List<ErrorCode> errorCodes: const <ErrorCode>[],
      List<ExpectedError> errors}) {
    throw new UnimplementedError();
  }

  @override
  CompilationUnitMember parseFullCompilationUnitMember() {
    CompilationUnit unit = parseCompilationUnit(content);
    expect(unit.directives, hasLength(0));
    expect(unit.declarations, hasLength(1));
    return unit.declarations[0];
  }

  @override
  Directive parseFullDirective() {
    CompilationUnit unit = parseCompilationUnit(content);
    expect(unit.directives, hasLength(1));
    expect(unit.declarations, hasLength(0));
    return unit.directives[0];
  }

  @override
  FunctionExpression parseFunctionExpression(String code) {
    return parseExpression(code);
  }

  @override
  InstanceCreationExpression parseInstanceCreationExpression(
      String code, Token newToken) {
    return parseExpression(code);
  }

  @override
  ListLiteral parseListLiteral(
      Token token, String typeArgumentsCode, String code) {
    StringBuffer buffer = new StringBuffer();
    if (token != null) {
      buffer.write(token.lexeme);
      buffer.write(' ');
    }
    if (typeArgumentsCode != null) {
      buffer.write(typeArgumentsCode);
    }
    buffer.write(code);
    return parseExpression(buffer.toString());
  }

  @override
  TypedLiteral parseListOrMapLiteral(Token modifier, String code) {
    return parseExpression(code);
  }

  @override
  Expression parseLogicalAndExpression(String code) {
    return parseExpression(code);
  }

  @override
  Expression parseLogicalOrExpression(String code) {
    return parseExpression(code);
  }

  @override
  MapLiteral parseMapLiteral(
      Token token, String typeArgumentsCode, String code) {
    StringBuffer buffer = new StringBuffer();
    if (token != null) {
      buffer.write(token.lexeme);
      buffer.write(' ');
    }
    if (typeArgumentsCode != null) {
      buffer.write(typeArgumentsCode);
    }
    buffer.write(code);
    return parseExpression(buffer.toString());
  }

  @override
  MapLiteralEntry parseMapLiteralEntry(String code) {
    Expression expression = parseExpression('{$code}');
    expect(expression, new isInstanceOf<MapLiteral>());
    MapLiteral literal = expression;
    expect(literal.entries, hasLength(1));
    return literal.entries[0];
  }

  @override
  Expression parseMultiplicativeExpression(String code) {
    return parseExpression(code);
  }

  @override
  InstanceCreationExpression parseNewExpression(String code) {
    return parseExpression(code);
  }

  @override
  NormalFormalParameter parseNormalFormalParameter(String code,
      {bool inFunctionType: false,
      List<ErrorCode> errorCodes: const <ErrorCode>[]}) {
    throw new UnimplementedError();
  }

  @override
  Expression parsePostfixExpression(String code) {
    return parseExpression(code);
  }

  @override
  Identifier parsePrefixedIdentifier(String code) {
    return parseExpression(code);
  }

  @override
  Expression parsePrimaryExpression(String code,
      {int expectedEndOffset, List<ExpectedError> errors}) {
    return parseExpression(code,
        expectedEndOffset: expectedEndOffset, errors: errors);
  }

  @override
  Expression parseRelationalExpression(String code) {
    return parseExpression(code);
  }

  @override
  RethrowExpression parseRethrowExpression(String code) {
    Statement statement = parseStatement(code, inCatchBlock: true);
    expect(statement, new isInstanceOf<ExpressionStatement>());
    Expression expression = (statement as ExpressionStatement).expression;
    expect(expression, new isInstanceOf<RethrowExpression>());
    return expression;
  }

  @override
  BinaryExpression parseShiftExpression(String code) {
    return parseExpression(code);
  }

  @override
  SimpleIdentifier parseSimpleIdentifier(String code) {
    return parseExpression(code);
  }

  @override
  Statement parseStatement(String source,
      {bool enableLazyAssignmentOperators,
      int expectedEndOffset,
      bool inCatchBlock: true}) {
    // TODO(brianwilkerson) Check error codes.
    return _parse(source, (parser, token) => parser.parseStatement(token),
        inCatchBlock: inCatchBlock);
  }

  @override
  Expression parseStringLiteral(String code) {
    return parseExpression(code);
  }

  @override
  SymbolLiteral parseSymbolLiteral(String code) {
    return parseExpression(code);
  }

  @override
  Expression parseThrowExpression(String code) {
    return parseExpression(code);
  }

  @override
  Expression parseThrowExpressionWithoutCascade(String code) {
    return parseExpression(code);
  }

  @override
  PrefixExpression parseUnaryExpression(String code) {
    return parseExpression(code);
  }

  @override
  VariableDeclarationList parseVariableDeclarationList(String source) {
    CompilationUnit unit = parseCompilationUnit('''
f() {
  $source;
}
''');
    FunctionDeclaration function = unit.declarations[0];
    BlockFunctionBody body = function.functionExpression.body;
    VariableDeclarationStatement statement = body.block.statements[0];
    return statement.variables;
  }

  T _parse<T>(
      String source, void parseFunction(Parser parser, Token previousToken),
      {bool inAsync: false, bool inCatchBlock: false}) {
    ScannerResult scan = scanString(source);

    CompilerTestContext c = CompilerTestContext.current;
    KernelLibraryBuilder library = new KernelLibraryBuilder(
      c.entryPoint,
      c.entryPoint,
      c.kernelTarget.loader,
      null /* actualOrigin */,
      null /* enclosingLibrary */,
    );
    List<KernelTypeVariableBuilder> typeVariableBuilders =
        <KernelTypeVariableBuilder>[];
    List<KernelFormalParameterBuilder> formalParameterBuilders =
        <KernelFormalParameterBuilder>[];
    KernelProcedureBuilder procedureBuilder = new KernelProcedureBuilder(
        null /* metadata */,
        Modifier.staticMask /* or Modifier.varMask */,
        c.kernelTarget.dynamicType,
        "analyzerTest",
        typeVariableBuilders,
        formalParameterBuilders,
        kernel.ProcedureKind.Method,
        library,
        -1 /* charOffset */,
        -1 /* charOpenParenOffset */,
        -1 /* charEndOffset */);

    TypeInferrerDisabled typeInferrer =
        new TypeInferrerDisabled(new TypeSchemaEnvironment(
      c.kernelTarget.loader.coreTypes,
      c.kernelTarget.loader.hierarchy,
      // TODO(danrubel): Enable strong mode.
      false /* strong mode */,
    ));

    AstBodyBuilder builder = new AstBodyBuilder(
      library,
      procedureBuilder,
      new UnlinkedScope(),
      null,
      c.kernelTarget.loader.hierarchy,
      c.kernelTarget.loader.coreTypes,
      null /* classBuilder */,
      false /* isInstanceMember */,
      null /* uri */,
      typeInferrer,
      typeProvider,
    )..constantContext = ConstantContext.none; // .inferred ?

    Parser parser = new Parser(builder);
    if (inAsync) {
      parser.asyncState = AsyncModifier.Async;
    }
    if (inCatchBlock) {
      builder.inCatchBlock = inCatchBlock;
    }
    parseFunction(parser, parser.syntheticPreviousToken(scan.tokens));
    // TODO(brianwilkerson) Check `expectedEndOffset` if it is not `null`.
    return builder.pop();
  }
}

/// A parser that can be used by [FastaBodyBuilderTestCase] to support the tests
/// that still call methods on the parser directly.
class ParserProxy implements analyzer.Parser {
  final FastaBodyBuilderTestCase testCase;

  ParserProxy(this.testCase);

  @override
  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);

  @override
  Annotation parseAnnotation() {
    CompilationUnit unit =
        testCase.parseCompilationUnit('${testCase.content} var v;');
    expect(unit.directives, hasLength(0));
    expect(unit.declarations, hasLength(1));
    expect(
        unit.declarations[0], new isInstanceOf<TopLevelVariableDeclaration>());
    TopLevelVariableDeclaration declaration = unit.declarations[0];
    expect(declaration.metadata, hasLength(1));
    return declaration.metadata[0];
  }

  @override
  ArgumentList parseArgumentList() {
    Expression expression = testCase.parseExpression('f${testCase.content}');
    expect(expression, new isInstanceOf<MethodInvocation>());
    MethodInvocation invocation = expression;
    return invocation.argumentList;
  }

  @override
  ClassMember parseClassMember(String className) {
    CompilationUnit unit = testCase
        .parseCompilationUnit('class $className { ${testCase.content} }');
    expect(unit.directives, hasLength(0));
    expect(unit.declarations, hasLength(1));
    expect(unit.declarations[0], new isInstanceOf<ClassDeclaration>());
    ClassDeclaration classDeclaration = unit.declarations[0];
    expect(classDeclaration.members, hasLength(1));
    return classDeclaration.members[0];
  }

  @override
  List<Combinator> parseCombinators() {
    CompilationUnit unit = testCase
        .parseCompilationUnit('import "file.dart" ${testCase.content};');
    expect(unit.directives, hasLength(1));
    expect(unit.declarations, hasLength(0));
    expect(unit.directives[0], new isInstanceOf<LibraryDirective>());
    ImportDirective directive = unit.directives[0];
    return directive.combinators;
  }

  @override
  CommentReference parseCommentReference(
      String referenceSource, int sourceOffset) {
    // TODO(brianwilkerson) Implement this.
    throw new UnimplementedError();
  }

  @override
  CompilationUnit parseCompilationUnit2() {
    return testCase.parseCompilationUnit(testCase.content);
  }

  @override
  Configuration parseConfiguration() {
    CompilationUnit unit = testCase
        .parseCompilationUnit('import "file.dart" ${testCase.content};');
    expect(unit.directives, hasLength(1));
    expect(unit.declarations, hasLength(0));
    expect(unit.directives[0], new isInstanceOf<LibraryDirective>());
    ImportDirective directive = unit.directives[0];
    expect(directive.configurations, hasLength(1));
    return directive.configurations[0];
  }

  @override
  DottedName parseDottedName() {
    CompilationUnit unit = testCase.parseCompilationUnit(
        'import "file.dart" if (${testCase.content}) "file2.dart";');
    expect(unit.directives, hasLength(1));
    expect(unit.declarations, hasLength(0));
    expect(unit.directives[0], new isInstanceOf<LibraryDirective>());
    ImportDirective directive = unit.directives[0];
    expect(directive.configurations, hasLength(1));
    return directive.configurations[0].name;
  }

  @override
  ExtendsClause parseExtendsClause() {
    CompilationUnit unit =
        testCase.parseCompilationUnit('class C ${testCase.content} {}');
    expect(unit.directives, hasLength(0));
    expect(unit.declarations, hasLength(1));
    expect(unit.declarations[0], new isInstanceOf<ClassDeclaration>());
    ClassDeclaration classDeclaration = unit.declarations[0];
    return classDeclaration.extendsClause;
  }

  @override
  analyzer.FinalConstVarOrType parseFinalConstVarOrType(bool optional,
      {bool inFunctionType: false}) {
    // TODO(brianwilkerson) Implement this or re-write the tests.
    throw new UnimplementedError();
  }

  @override
  FormalParameterList parseFormalParameterList({bool inFunctionType: false}) {
    CompilationUnit unit =
        testCase.parseCompilationUnit('f${testCase.content} {}');
    expect(unit.directives, hasLength(0));
    expect(unit.declarations, hasLength(1));
    expect(unit.declarations[0], new isInstanceOf<FunctionDeclaration>());
    FunctionDeclaration function = unit.declarations[0];
    return function.functionExpression.parameters;
  }

  @override
  FunctionBody parseFunctionBody(bool mayBeEmpty,
      analyzer.ParserErrorCode emptyErrorCode, bool inExpression) {
    CompilationUnit unit =
        testCase.parseCompilationUnit('f() ${testCase.content}');
    expect(unit.directives, hasLength(0));
    expect(unit.declarations, hasLength(1));
    expect(unit.declarations[0], new isInstanceOf<FunctionDeclaration>());
    FunctionDeclaration declaration = unit.declarations[0];
    return declaration.functionExpression.body;
  }

  @override
  ImplementsClause parseImplementsClause() {
    CompilationUnit unit =
        testCase.parseCompilationUnit('class C ${testCase.content} {}');
    expect(unit.directives, hasLength(0));
    expect(unit.declarations, hasLength(1));
    expect(unit.declarations[0], new isInstanceOf<ClassDeclaration>());
    ClassDeclaration classDeclaration = unit.declarations[0];
    return classDeclaration.implementsClause;
  }

  @override
  analyzer.Modifiers parseModifiers() {
    // TODO(brianwilkerson) Implement this or re-write the tests (this might
    // need context to create the right kind of declaration for the modifiers).
    throw new UnimplementedError();
  }

  @override
  Expression parseMultiplicativeExpression() {
    return testCase.parseExpression(testCase.content);
  }

  @override
  Expression parsePrimaryExpression() {
    return testCase.parseExpression(testCase.content);
  }

  @override
  SimpleIdentifier parseSimpleIdentifier(
      {bool allowKeyword: false, bool isDeclaration: false}) {
    return testCase.parseExpression(testCase.content);
  }

  @override
  Statement parseStatement2() {
    return testCase.parseStatement(testCase.content);
  }

  @override
  TypeAnnotation parseTypeAnnotation(bool inExpression) {
    if (inExpression) {
      // TODO(brianwilkerson) As far as I can see, this path is not used.
      throw new UnimplementedError();
    }
    CompilationUnit unit =
        testCase.parseCompilationUnit('${testCase.content} x;');
    expect(unit.directives, hasLength(0));
    expect(unit.declarations, hasLength(1));
    expect(
        unit.declarations[0], new isInstanceOf<TopLevelVariableDeclaration>());
    TopLevelVariableDeclaration variable = unit.declarations[0];
    return variable.variables.type;
  }

  @override
  TypeArgumentList parseTypeArgumentList() {
    CompilationUnit unit =
        testCase.parseCompilationUnit('C${testCase.content} c;');
    expect(unit.directives, hasLength(0));
    expect(unit.declarations, hasLength(1));
    expect(
        unit.declarations[0], new isInstanceOf<TopLevelVariableDeclaration>());
    TopLevelVariableDeclaration variable = unit.declarations[0];
    return (variable.variables.type as TypeName).typeArguments;
  }

  @override
  TypeName parseTypeName(bool inExpression) {
    return parseTypeAnnotation(inExpression) as TypeName;
  }

  @override
  TypeParameter parseTypeParameter() {
    CompilationUnit unit =
        testCase.parseCompilationUnit('class C<${testCase.content}> {}');
    expect(unit.directives, hasLength(0));
    expect(unit.declarations, hasLength(1));
    expect(unit.declarations[0], new isInstanceOf<ClassDeclaration>());
    ClassDeclaration classDeclaration = unit.declarations[0];
    return classDeclaration.typeParameters.typeParameters[0];
  }

  @override
  Expression parseUnaryExpression() {
    return testCase.parseExpression(testCase.content);
  }

  @override
  WithClause parseWithClause() {
    CompilationUnit unit =
        testCase.parseCompilationUnit('class C ${testCase.content} {}');
    expect(unit.directives, hasLength(0));
    expect(unit.declarations, hasLength(1));
    expect(unit.declarations[0], new isInstanceOf<ClassDeclaration>());
    ClassDeclaration classDeclaration = unit.declarations[0];
    return classDeclaration.withClause;
  }
}
