// Copyright (c) 2016, 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:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:front_end/src/scanner/token.dart';
import 'package:meta/meta.dart';

/**
 * Concrete implementation of [AstFactory] based on the standard AST
 * implementation.
 */
class AstFactoryImpl extends AstFactory {
  @override
  AdjacentStrings adjacentStrings(List<StringLiteral> strings) =>
      new AdjacentStringsImpl(strings);

  @override
  Annotation annotation(Token atSign, Identifier name, Token period,
          SimpleIdentifier constructorName, ArgumentList arguments) =>
      new AnnotationImpl(atSign, name, period, constructorName, arguments);

  @override
  ArgumentList argumentList(Token leftParenthesis, List<Expression> arguments,
          Token rightParenthesis) =>
      new ArgumentListImpl(leftParenthesis, arguments, rightParenthesis);

  @override
  AsExpression asExpression(
          Expression expression, Token asOperator, TypeAnnotation type) =>
      new AsExpressionImpl(expression, asOperator, type);

  @override
  AssertInitializer assertInitializer(
          Token assertKeyword,
          Token leftParenthesis,
          Expression condition,
          Token comma,
          Expression message,
          Token rightParenthesis) =>
      new AssertInitializerImpl(assertKeyword, leftParenthesis, condition,
          comma, message, rightParenthesis);

  @override
  AssertStatement assertStatement(
          Token assertKeyword,
          Token leftParenthesis,
          Expression condition,
          Token comma,
          Expression message,
          Token rightParenthesis,
          Token semicolon) =>
      new AssertStatementImpl(assertKeyword, leftParenthesis, condition, comma,
          message, rightParenthesis, semicolon);

  @override
  AssignmentExpression assignmentExpression(
          Expression leftHandSide, Token operator, Expression rightHandSide) =>
      new AssignmentExpressionImpl(leftHandSide, operator, rightHandSide);

  @override
  AwaitExpression awaitExpression(Token awaitKeyword, Expression expression) =>
      new AwaitExpressionImpl(awaitKeyword, expression);

  @override
  BinaryExpression binaryExpression(
          Expression leftOperand, Token operator, Expression rightOperand) =>
      new BinaryExpressionImpl(leftOperand, operator, rightOperand);

  @override
  Block block(
          Token leftBracket, List<Statement> statements, Token rightBracket) =>
      new BlockImpl(leftBracket, statements, rightBracket);

  @override
  Comment blockComment(List<Token> tokens) =>
      CommentImpl.createBlockComment(tokens);

  @override
  BlockFunctionBody blockFunctionBody(Token keyword, Token star, Block block) =>
      new BlockFunctionBodyImpl(keyword, star, block);

  @override
  BooleanLiteral booleanLiteral(Token literal, bool value) =>
      new BooleanLiteralImpl(literal, value);

  @override
  BreakStatement breakStatement(
          Token breakKeyword, SimpleIdentifier label, Token semicolon) =>
      new BreakStatementImpl(breakKeyword, label, semicolon);

  @override
  CascadeExpression cascadeExpression(
          Expression target, List<Expression> cascadeSections) =>
      new CascadeExpressionImpl(target, cascadeSections);

  @override
  CatchClause catchClause(
          Token onKeyword,
          TypeAnnotation exceptionType,
          Token catchKeyword,
          Token leftParenthesis,
          SimpleIdentifier exceptionParameter,
          Token comma,
          SimpleIdentifier stackTraceParameter,
          Token rightParenthesis,
          Block body) =>
      new CatchClauseImpl(
          onKeyword,
          exceptionType,
          catchKeyword,
          leftParenthesis,
          exceptionParameter,
          comma,
          stackTraceParameter,
          rightParenthesis,
          body);

  @override
  ClassDeclaration classDeclaration(
          Comment comment,
          List<Annotation> metadata,
          Token abstractKeyword,
          Token classKeyword,
          SimpleIdentifier name,
          TypeParameterList typeParameters,
          ExtendsClause extendsClause,
          WithClause withClause,
          ImplementsClause implementsClause,
          Token leftBracket,
          List<ClassMember> members,
          Token rightBracket) =>
      new ClassDeclarationImpl(
          comment,
          metadata,
          abstractKeyword,
          classKeyword,
          name,
          typeParameters,
          extendsClause,
          withClause,
          implementsClause,
          leftBracket,
          members,
          rightBracket);

  @override
  ClassTypeAlias classTypeAlias(
          Comment comment,
          List<Annotation> metadata,
          Token keyword,
          SimpleIdentifier name,
          TypeParameterList typeParameters,
          Token equals,
          Token abstractKeyword,
          TypeName superclass,
          WithClause withClause,
          ImplementsClause implementsClause,
          Token semicolon) =>
      new ClassTypeAliasImpl(
          comment,
          metadata,
          keyword,
          name,
          typeParameters,
          equals,
          abstractKeyword,
          superclass,
          withClause,
          implementsClause,
          semicolon);

  @override
  CommentReference commentReference(Token newKeyword, Identifier identifier) =>
      new CommentReferenceImpl(newKeyword, identifier);

  @override
  CompilationUnit compilationUnit(
          {Token beginToken,
          ScriptTag scriptTag,
          List<Directive> directives,
          List<CompilationUnitMember> declarations,
          Token endToken,
          FeatureSet featureSet}) =>
      new CompilationUnitImpl(beginToken, scriptTag, directives, declarations,
          endToken, featureSet);

  @override
  @deprecated
  CompilationUnit compilationUnit2(
          {Token beginToken,
          ScriptTag scriptTag,
          List<Directive> directives,
          List<CompilationUnitMember> declarations,
          Token endToken,
          FeatureSet featureSet}) =>
      new CompilationUnitImpl(beginToken, scriptTag, directives, declarations,
          endToken, featureSet);

  @override
  ConditionalExpression conditionalExpression(
          Expression condition,
          Token question,
          Expression thenExpression,
          Token colon,
          Expression elseExpression) =>
      new ConditionalExpressionImpl(
          condition, question, thenExpression, colon, elseExpression);

  @override
  Configuration configuration(
          Token ifKeyword,
          Token leftParenthesis,
          DottedName name,
          Token equalToken,
          StringLiteral value,
          Token rightParenthesis,
          StringLiteral libraryUri) =>
      new ConfigurationImpl(ifKeyword, leftParenthesis, name, equalToken, value,
          rightParenthesis, libraryUri);

  @override
  ConstructorDeclaration constructorDeclaration(
          Comment comment,
          List<Annotation> metadata,
          Token externalKeyword,
          Token constKeyword,
          Token factoryKeyword,
          Identifier returnType,
          Token period,
          SimpleIdentifier name,
          FormalParameterList parameters,
          Token separator,
          List<ConstructorInitializer> initializers,
          ConstructorName redirectedConstructor,
          FunctionBody body) =>
      new ConstructorDeclarationImpl(
          comment,
          metadata,
          externalKeyword,
          constKeyword,
          factoryKeyword,
          returnType,
          period,
          name,
          parameters,
          separator,
          initializers,
          redirectedConstructor,
          body);

  @override
  ConstructorFieldInitializer constructorFieldInitializer(
          Token thisKeyword,
          Token period,
          SimpleIdentifier fieldName,
          Token equals,
          Expression expression) =>
      new ConstructorFieldInitializerImpl(
          thisKeyword, period, fieldName, equals, expression);

  @override
  ConstructorName constructorName(
          TypeName type, Token period, SimpleIdentifier name) =>
      new ConstructorNameImpl(type, period, name);

  @override
  ContinueStatement continueStatement(
          Token continueKeyword, SimpleIdentifier label, Token semicolon) =>
      new ContinueStatementImpl(continueKeyword, label, semicolon);

  @override
  DeclaredIdentifier declaredIdentifier(
          Comment comment,
          List<Annotation> metadata,
          Token keyword,
          TypeAnnotation type,
          SimpleIdentifier identifier) =>
      new DeclaredIdentifierImpl(comment, metadata, keyword, type, identifier);

  @override
  DefaultFormalParameter defaultFormalParameter(NormalFormalParameter parameter,
          ParameterKind kind, Token separator, Expression defaultValue) =>
      new DefaultFormalParameterImpl(parameter, kind, separator, defaultValue);

  @override
  Comment documentationComment(List<Token> tokens,
          [List<CommentReference> references]) =>
      CommentImpl.createDocumentationCommentWithReferences(
          tokens, references ?? <CommentReference>[]);

  @override
  DoStatement doStatement(
          Token doKeyword,
          Statement body,
          Token whileKeyword,
          Token leftParenthesis,
          Expression condition,
          Token rightParenthesis,
          Token semicolon) =>
      new DoStatementImpl(doKeyword, body, whileKeyword, leftParenthesis,
          condition, rightParenthesis, semicolon);

  @override
  DottedName dottedName(List<SimpleIdentifier> components) =>
      new DottedNameImpl(components);

  @override
  DoubleLiteral doubleLiteral(Token literal, double value) =>
      new DoubleLiteralImpl(literal, value);

  @override
  EmptyFunctionBody emptyFunctionBody(Token semicolon) =>
      new EmptyFunctionBodyImpl(semicolon);

  @override
  EmptyStatement emptyStatement(Token semicolon) =>
      new EmptyStatementImpl(semicolon);

  @override
  Comment endOfLineComment(List<Token> tokens) =>
      CommentImpl.createEndOfLineComment(tokens);

  @override
  EnumConstantDeclaration enumConstantDeclaration(
          Comment comment, List<Annotation> metadata, SimpleIdentifier name) =>
      new EnumConstantDeclarationImpl(comment, metadata, name);

  @override
  EnumDeclaration enumDeclaration(
          Comment comment,
          List<Annotation> metadata,
          Token enumKeyword,
          SimpleIdentifier name,
          Token leftBracket,
          List<EnumConstantDeclaration> constants,
          Token rightBracket) =>
      new EnumDeclarationImpl(comment, metadata, enumKeyword, name, leftBracket,
          constants, rightBracket);

  @override
  ExportDirective exportDirective(
          Comment comment,
          List<Annotation> metadata,
          Token keyword,
          StringLiteral libraryUri,
          List<Configuration> configurations,
          List<Combinator> combinators,
          Token semicolon) =>
      new ExportDirectiveImpl(comment, metadata, keyword, libraryUri,
          configurations, combinators, semicolon);

  @override
  ExpressionFunctionBody expressionFunctionBody(Token keyword,
          Token functionDefinition, Expression expression, Token semicolon) =>
      new ExpressionFunctionBodyImpl(
          keyword, functionDefinition, expression, semicolon);

  @override
  ExpressionStatement expressionStatement(
          Expression expression, Token semicolon) =>
      new ExpressionStatementImpl(expression, semicolon);

  @override
  ExtendsClause extendsClause(Token extendsKeyword, TypeName superclass) =>
      new ExtendsClauseImpl(extendsKeyword, superclass);

  @override
  ExtensionDeclaration extensionDeclaration(
          {Comment comment,
          List<Annotation> metadata,
          Token extensionKeyword,
          @required SimpleIdentifier name,
          TypeParameterList typeParameters,
          Token onKeyword,
          @required TypeAnnotation extendedType,
          Token leftBracket,
          List<ClassMember> members,
          Token rightBracket}) =>
      new ExtensionDeclarationImpl(
          comment,
          metadata,
          extensionKeyword,
          name,
          typeParameters,
          onKeyword,
          extendedType,
          leftBracket,
          members,
          rightBracket);

  @override
  ExtensionOverride extensionOverride(
          {@required Identifier extensionName,
          TypeArgumentList typeArguments,
          @required ArgumentList argumentList}) =>
      ExtensionOverrideImpl(extensionName, typeArguments, argumentList);

  @override
  FieldDeclaration fieldDeclaration(
          Comment comment,
          List<Annotation> metadata,
          Token staticKeyword,
          VariableDeclarationList fieldList,
          Token semicolon) =>
      new FieldDeclarationImpl(
          comment, metadata, null, staticKeyword, fieldList, semicolon);

  @override
  FieldDeclaration fieldDeclaration2(
          {Comment comment,
          List<Annotation> metadata,
          Token covariantKeyword,
          Token staticKeyword,
          @required VariableDeclarationList fieldList,
          @required Token semicolon}) =>
      new FieldDeclarationImpl(comment, metadata, covariantKeyword,
          staticKeyword, fieldList, semicolon);

  @override
  FieldFormalParameter fieldFormalParameter(
          Comment comment,
          List<Annotation> metadata,
          Token keyword,
          TypeAnnotation type,
          Token thisKeyword,
          Token period,
          SimpleIdentifier identifier,
          TypeParameterList typeParameters,
          FormalParameterList parameters) =>
      new FieldFormalParameterImpl(comment, metadata, null, null, keyword, type,
          thisKeyword, period, identifier, typeParameters, parameters);

  @override
  FieldFormalParameter fieldFormalParameter2(
          {Comment comment,
          List<Annotation> metadata,
          Token covariantKeyword,
          Token requiredKeyword,
          Token keyword,
          TypeAnnotation type,
          @required Token thisKeyword,
          @required Token period,
          @required SimpleIdentifier identifier,
          TypeParameterList typeParameters,
          FormalParameterList parameters}) =>
      new FieldFormalParameterImpl(
          comment,
          metadata,
          covariantKeyword,
          requiredKeyword,
          keyword,
          type,
          thisKeyword,
          period,
          identifier,
          typeParameters,
          parameters);

  @override
  ForEachPartsWithDeclaration forEachPartsWithDeclaration(
          {DeclaredIdentifier loopVariable,
          Token inKeyword,
          Expression iterable}) =>
      new ForEachPartsWithDeclarationImpl(loopVariable, inKeyword, iterable);

  @override
  ForEachPartsWithIdentifier forEachPartsWithIdentifier(
          {SimpleIdentifier identifier,
          Token inKeyword,
          Expression iterable}) =>
      new ForEachPartsWithIdentifierImpl(identifier, inKeyword, iterable);

  @override
  ForElement forElement(
          {Token awaitKeyword,
          Token forKeyword,
          Token leftParenthesis,
          ForLoopParts forLoopParts,
          Token rightParenthesis,
          CollectionElement body}) =>
      new ForElementImpl(awaitKeyword, forKeyword, leftParenthesis,
          forLoopParts, rightParenthesis, body);

  @override
  FormalParameterList formalParameterList(
          Token leftParenthesis,
          List<FormalParameter> parameters,
          Token leftDelimiter,
          Token rightDelimiter,
          Token rightParenthesis) =>
      new FormalParameterListImpl(leftParenthesis, parameters, leftDelimiter,
          rightDelimiter, rightParenthesis);

  @override
  ForPartsWithDeclarations forPartsWithDeclarations(
          {VariableDeclarationList variables,
          Token leftSeparator,
          Expression condition,
          Token rightSeparator,
          List<Expression> updaters}) =>
      new ForPartsWithDeclarationsImpl(
          variables, leftSeparator, condition, rightSeparator, updaters);

  @override
  ForPartsWithExpression forPartsWithExpression(
          {Expression initialization,
          Token leftSeparator,
          Expression condition,
          Token rightSeparator,
          List<Expression> updaters}) =>
      new ForPartsWithExpressionImpl(
          initialization, leftSeparator, condition, rightSeparator, updaters);

  @override
  ForStatement forStatement(
      {Token awaitKeyword,
      Token forKeyword,
      Token leftParenthesis,
      ForLoopParts forLoopParts,
      Token rightParenthesis,
      Statement body}) {
    return ForStatementImpl(awaitKeyword, forKeyword, leftParenthesis,
        forLoopParts, rightParenthesis, body);
  }

  @override
  FunctionDeclaration functionDeclaration(
          Comment comment,
          List<Annotation> metadata,
          Token externalKeyword,
          TypeAnnotation returnType,
          Token propertyKeyword,
          SimpleIdentifier name,
          FunctionExpression functionExpression) =>
      new FunctionDeclarationImpl(comment, metadata, externalKeyword,
          returnType, propertyKeyword, name, functionExpression);

  @override
  FunctionDeclarationStatement functionDeclarationStatement(
          FunctionDeclaration functionDeclaration) =>
      new FunctionDeclarationStatementImpl(functionDeclaration);

  @override
  FunctionExpression functionExpression(TypeParameterList typeParameters,
          FormalParameterList parameters, FunctionBody body) =>
      new FunctionExpressionImpl(typeParameters, parameters, body);

  @override
  FunctionExpressionInvocation functionExpressionInvocation(Expression function,
          TypeArgumentList typeArguments, ArgumentList argumentList) =>
      new FunctionExpressionInvocationImpl(
          function, typeArguments, argumentList);

  @override
  FunctionTypeAlias functionTypeAlias(
          Comment comment,
          List<Annotation> metadata,
          Token keyword,
          TypeAnnotation returnType,
          SimpleIdentifier name,
          TypeParameterList typeParameters,
          FormalParameterList parameters,
          Token semicolon) =>
      new FunctionTypeAliasImpl(comment, metadata, keyword, returnType, name,
          typeParameters, parameters, semicolon);

  @override
  FunctionTypedFormalParameter functionTypedFormalParameter(
          Comment comment,
          List<Annotation> metadata,
          TypeAnnotation returnType,
          SimpleIdentifier identifier,
          TypeParameterList typeParameters,
          FormalParameterList parameters) =>
      new FunctionTypedFormalParameterImpl(comment, metadata, null, null,
          returnType, identifier, typeParameters, parameters, null);

  @override
  FunctionTypedFormalParameter functionTypedFormalParameter2(
          {Comment comment,
          List<Annotation> metadata,
          Token covariantKeyword,
          Token requiredKeyword,
          TypeAnnotation returnType,
          @required SimpleIdentifier identifier,
          TypeParameterList typeParameters,
          @required FormalParameterList parameters,
          Token question}) =>
      new FunctionTypedFormalParameterImpl(
          comment,
          metadata,
          covariantKeyword,
          requiredKeyword,
          returnType,
          identifier,
          typeParameters,
          parameters,
          question);

  @override
  GenericFunctionType genericFunctionType(
          TypeAnnotation returnType,
          Token functionKeyword,
          TypeParameterList typeParameters,
          FormalParameterList parameters,
          {Token question}) =>
      new GenericFunctionTypeImpl(
          returnType, functionKeyword, typeParameters, parameters,
          question: question);

  @override
  GenericTypeAlias genericTypeAlias(
          Comment comment,
          List<Annotation> metadata,
          Token typedefKeyword,
          SimpleIdentifier name,
          TypeParameterList typeParameters,
          Token equals,
          GenericFunctionType functionType,
          Token semicolon) =>
      new GenericTypeAliasImpl(comment, metadata, typedefKeyword, name,
          typeParameters, equals, functionType, semicolon);

  @override
  HideCombinator hideCombinator(
          Token keyword, List<SimpleIdentifier> hiddenNames) =>
      new HideCombinatorImpl(keyword, hiddenNames);

  @override
  IfElement ifElement(
          {Token ifKeyword,
          Token leftParenthesis,
          Expression condition,
          Token rightParenthesis,
          CollectionElement thenElement,
          Token elseKeyword,
          CollectionElement elseElement}) =>
      new IfElementImpl(ifKeyword, leftParenthesis, condition, rightParenthesis,
          thenElement, elseKeyword, elseElement);

  @override
  IfStatement ifStatement(
          Token ifKeyword,
          Token leftParenthesis,
          Expression condition,
          Token rightParenthesis,
          Statement thenStatement,
          Token elseKeyword,
          Statement elseStatement) =>
      new IfStatementImpl(ifKeyword, leftParenthesis, condition,
          rightParenthesis, thenStatement, elseKeyword, elseStatement);

  @override
  ImplementsClause implementsClause(
          Token implementsKeyword, List<TypeName> interfaces) =>
      new ImplementsClauseImpl(implementsKeyword, interfaces);

  @override
  ImportDirective importDirective(
          Comment comment,
          List<Annotation> metadata,
          Token keyword,
          StringLiteral libraryUri,
          List<Configuration> configurations,
          Token deferredKeyword,
          Token asKeyword,
          SimpleIdentifier prefix,
          List<Combinator> combinators,
          Token semicolon) =>
      new ImportDirectiveImpl(
          comment,
          metadata,
          keyword,
          libraryUri,
          configurations,
          deferredKeyword,
          asKeyword,
          prefix,
          combinators,
          semicolon);

  @override
  IndexExpression indexExpressionForCascade(Token period, Token leftBracket,
          Expression index, Token rightBracket) =>
      new IndexExpressionImpl.forCascade(
          period, leftBracket, index, rightBracket);

  @override
  IndexExpression indexExpressionForTarget(Expression target, Token leftBracket,
          Expression index, Token rightBracket) =>
      new IndexExpressionImpl.forTarget(
          target, leftBracket, index, rightBracket);

  @override
  InstanceCreationExpression instanceCreationExpression(Token keyword,
          ConstructorName constructorName, ArgumentList argumentList,
          {TypeArgumentList typeArguments}) =>
      new InstanceCreationExpressionImpl(keyword, constructorName, argumentList,
          typeArguments: typeArguments);

  @override
  IntegerLiteral integerLiteral(Token literal, int value) =>
      new IntegerLiteralImpl(literal, value);

  @override
  InterpolationExpression interpolationExpression(
          Token leftBracket, Expression expression, Token rightBracket) =>
      new InterpolationExpressionImpl(leftBracket, expression, rightBracket);

  @override
  InterpolationString interpolationString(Token contents, String value) =>
      new InterpolationStringImpl(contents, value);

  @override
  IsExpression isExpression(Expression expression, Token isOperator,
          Token notOperator, TypeAnnotation type) =>
      new IsExpressionImpl(expression, isOperator, notOperator, type);

  @override
  Label label(SimpleIdentifier label, Token colon) =>
      new LabelImpl(label, colon);

  @override
  LabeledStatement labeledStatement(List<Label> labels, Statement statement) =>
      new LabeledStatementImpl(labels, statement);

  @override
  LibraryDirective libraryDirective(Comment comment, List<Annotation> metadata,
          Token libraryKeyword, LibraryIdentifier name, Token semicolon) =>
      new LibraryDirectiveImpl(
          comment, metadata, libraryKeyword, name, semicolon);

  @override
  LibraryIdentifier libraryIdentifier(List<SimpleIdentifier> components) =>
      new LibraryIdentifierImpl(components);

  @override
  ListLiteral listLiteral(Token constKeyword, TypeArgumentList typeArguments,
      Token leftBracket, List<CollectionElement> elements, Token rightBracket) {
    if (elements == null || elements is List<Expression>) {
      return new ListLiteralImpl(
          constKeyword, typeArguments, leftBracket, elements, rightBracket);
    }
    return new ListLiteralImpl.experimental(
        constKeyword, typeArguments, leftBracket, elements, rightBracket);
  }

  @override
  MapLiteralEntry mapLiteralEntry(
          Expression key, Token separator, Expression value) =>
      new MapLiteralEntryImpl(key, separator, value);

  @override
  MethodDeclaration methodDeclaration(
          Comment comment,
          List<Annotation> metadata,
          Token externalKeyword,
          Token modifierKeyword,
          TypeAnnotation returnType,
          Token propertyKeyword,
          Token operatorKeyword,
          SimpleIdentifier name,
          TypeParameterList typeParameters,
          FormalParameterList parameters,
          FunctionBody body) =>
      new MethodDeclarationImpl(
          comment,
          metadata,
          externalKeyword,
          modifierKeyword,
          returnType,
          propertyKeyword,
          operatorKeyword,
          name,
          typeParameters,
          parameters,
          body);

  @override
  MethodInvocation methodInvocation(
          Expression target,
          Token operator,
          SimpleIdentifier methodName,
          TypeArgumentList typeArguments,
          ArgumentList argumentList) =>
      new MethodInvocationImpl(
          target, operator, methodName, typeArguments, argumentList);

  @override
  MixinDeclaration mixinDeclaration(
          Comment comment,
          List<Annotation> metadata,
          Token mixinKeyword,
          SimpleIdentifier name,
          TypeParameterList typeParameters,
          OnClause onClause,
          ImplementsClause implementsClause,
          Token leftBracket,
          List<ClassMember> members,
          Token rightBracket) =>
      new MixinDeclarationImpl(
          comment,
          metadata,
          mixinKeyword,
          name,
          typeParameters,
          onClause,
          implementsClause,
          leftBracket,
          members,
          rightBracket);

  @override
  NamedExpression namedExpression(Label name, Expression expression) =>
      new NamedExpressionImpl(name, expression);

  @override
  NativeClause nativeClause(Token nativeKeyword, StringLiteral name) =>
      new NativeClauseImpl(nativeKeyword, name);

  @override
  NativeFunctionBody nativeFunctionBody(
          Token nativeKeyword, StringLiteral stringLiteral, Token semicolon) =>
      new NativeFunctionBodyImpl(nativeKeyword, stringLiteral, semicolon);

  @override
  NodeList<E> nodeList<E extends AstNode>(AstNode owner, [List<E> elements]) =>
      new NodeListImpl<E>(owner as AstNodeImpl, elements);

  @override
  NullLiteral nullLiteral(Token literal) => new NullLiteralImpl(literal);

  @override
  OnClause onClause(Token onKeyword, List<TypeName> superclassConstraints) =>
      new OnClauseImpl(onKeyword, superclassConstraints);

  @override
  ParenthesizedExpression parenthesizedExpression(Token leftParenthesis,
          Expression expression, Token rightParenthesis) =>
      new ParenthesizedExpressionImpl(
          leftParenthesis, expression, rightParenthesis);

  @override
  PartDirective partDirective(Comment comment, List<Annotation> metadata,
          Token partKeyword, StringLiteral partUri, Token semicolon) =>
      new PartDirectiveImpl(comment, metadata, partKeyword, partUri, semicolon);

  @override
  PartOfDirective partOfDirective(
          Comment comment,
          List<Annotation> metadata,
          Token partKeyword,
          Token ofKeyword,
          StringLiteral uri,
          LibraryIdentifier libraryName,
          Token semicolon) =>
      new PartOfDirectiveImpl(comment, metadata, partKeyword, ofKeyword, uri,
          libraryName, semicolon);

  @override
  PostfixExpression postfixExpression(Expression operand, Token operator) =>
      new PostfixExpressionImpl(operand, operator);

  @override
  PrefixedIdentifier prefixedIdentifier(
          SimpleIdentifier prefix, Token period, SimpleIdentifier identifier) =>
      new PrefixedIdentifierImpl(prefix, period, identifier);

  @override
  PrefixExpression prefixExpression(Token operator, Expression operand) =>
      new PrefixExpressionImpl(operator, operand);

  @override
  PropertyAccess propertyAccess(
          Expression target, Token operator, SimpleIdentifier propertyName) =>
      new PropertyAccessImpl(target, operator, propertyName);

  @override
  RedirectingConstructorInvocation redirectingConstructorInvocation(
          Token thisKeyword,
          Token period,
          SimpleIdentifier constructorName,
          ArgumentList argumentList) =>
      new RedirectingConstructorInvocationImpl(
          thisKeyword, period, constructorName, argumentList);

  @override
  RethrowExpression rethrowExpression(Token rethrowKeyword) =>
      new RethrowExpressionImpl(rethrowKeyword);

  @override
  ReturnStatement returnStatement(
          Token returnKeyword, Expression expression, Token semicolon) =>
      new ReturnStatementImpl(returnKeyword, expression, semicolon);

  @override
  ScriptTag scriptTag(Token scriptTag) => new ScriptTagImpl(scriptTag);

  @override
  SetOrMapLiteral setOrMapLiteral(
          {Token constKeyword,
          TypeArgumentList typeArguments,
          Token leftBracket,
          List<CollectionElement> elements,
          Token rightBracket}) =>
      new SetOrMapLiteralImpl(
          constKeyword, typeArguments, leftBracket, elements, rightBracket);

  @override
  ShowCombinator showCombinator(
          Token keyword, List<SimpleIdentifier> shownNames) =>
      new ShowCombinatorImpl(keyword, shownNames);

  @override
  SimpleFormalParameter simpleFormalParameter(
          Comment comment,
          List<Annotation> metadata,
          Token keyword,
          TypeAnnotation type,
          SimpleIdentifier identifier) =>
      new SimpleFormalParameterImpl(
          comment, metadata, null, null, keyword, type, identifier);

  @override
  SimpleFormalParameter simpleFormalParameter2(
          {Comment comment,
          List<Annotation> metadata,
          Token covariantKeyword,
          Token requiredKeyword,
          Token keyword,
          TypeAnnotation type,
          @required SimpleIdentifier identifier}) =>
      new SimpleFormalParameterImpl(comment, metadata, covariantKeyword,
          requiredKeyword, keyword, type, identifier);

  @override
  SimpleIdentifier simpleIdentifier(Token token, {bool isDeclaration: false}) {
    if (isDeclaration) {
      return new DeclaredSimpleIdentifier(token);
    }
    return new SimpleIdentifierImpl(token);
  }

  @override
  SimpleStringLiteral simpleStringLiteral(Token literal, String value) =>
      new SimpleStringLiteralImpl(literal, value);

  @override
  SpreadElement spreadElement({Token spreadOperator, Expression expression}) =>
      new SpreadElementImpl(spreadOperator, expression);

  @override
  StringInterpolation stringInterpolation(
          List<InterpolationElement> elements) =>
      new StringInterpolationImpl(elements);

  @override
  SuperConstructorInvocation superConstructorInvocation(
          Token superKeyword,
          Token period,
          SimpleIdentifier constructorName,
          ArgumentList argumentList) =>
      new SuperConstructorInvocationImpl(
          superKeyword, period, constructorName, argumentList);

  @override
  SuperExpression superExpression(Token superKeyword) =>
      new SuperExpressionImpl(superKeyword);

  @override
  SwitchCase switchCase(List<Label> labels, Token keyword,
          Expression expression, Token colon, List<Statement> statements) =>
      new SwitchCaseImpl(labels, keyword, expression, colon, statements);

  @override
  SwitchDefault switchDefault(List<Label> labels, Token keyword, Token colon,
          List<Statement> statements) =>
      new SwitchDefaultImpl(labels, keyword, colon, statements);

  @override
  SwitchStatement switchStatement(
          Token switchKeyword,
          Token leftParenthesis,
          Expression expression,
          Token rightParenthesis,
          Token leftBracket,
          List<SwitchMember> members,
          Token rightBracket) =>
      new SwitchStatementImpl(switchKeyword, leftParenthesis, expression,
          rightParenthesis, leftBracket, members, rightBracket);

  @override
  SymbolLiteral symbolLiteral(Token poundSign, List<Token> components) =>
      new SymbolLiteralImpl(poundSign, components);

  @override
  ThisExpression thisExpression(Token thisKeyword) =>
      new ThisExpressionImpl(thisKeyword);

  @override
  ThrowExpression throwExpression(Token throwKeyword, Expression expression) =>
      new ThrowExpressionImpl(throwKeyword, expression);

  @override
  TopLevelVariableDeclaration topLevelVariableDeclaration(
          Comment comment,
          List<Annotation> metadata,
          VariableDeclarationList variableList,
          Token semicolon) =>
      new TopLevelVariableDeclarationImpl(
          comment, metadata, variableList, semicolon);

  @override
  TryStatement tryStatement(
          Token tryKeyword,
          Block body,
          List<CatchClause> catchClauses,
          Token finallyKeyword,
          Block finallyBlock) =>
      new TryStatementImpl(
          tryKeyword, body, catchClauses, finallyKeyword, finallyBlock);

  @override
  TypeArgumentList typeArgumentList(Token leftBracket,
          List<TypeAnnotation> arguments, Token rightBracket) =>
      new TypeArgumentListImpl(leftBracket, arguments, rightBracket);

  @override
  TypeName typeName(Identifier name, TypeArgumentList typeArguments,
          {Token question}) =>
      new TypeNameImpl(name, typeArguments, question: question);

  @override
  TypeParameter typeParameter(Comment comment, List<Annotation> metadata,
          SimpleIdentifier name, Token extendsKeyword, TypeAnnotation bound) =>
      new TypeParameterImpl(comment, metadata, name, extendsKeyword, bound);

  @override
  TypeParameterList typeParameterList(Token leftBracket,
          List<TypeParameter> typeParameters, Token rightBracket) =>
      new TypeParameterListImpl(leftBracket, typeParameters, rightBracket);

  @override
  VariableDeclaration variableDeclaration(
          SimpleIdentifier name, Token equals, Expression initializer) =>
      new VariableDeclarationImpl(name, equals, initializer);

  @override
  VariableDeclarationList variableDeclarationList(
          Comment comment,
          List<Annotation> metadata,
          Token keyword,
          TypeAnnotation type,
          List<VariableDeclaration> variables) =>
      new VariableDeclarationListImpl(
          comment, metadata, null, keyword, type, variables);

  @override
  VariableDeclarationList variableDeclarationList2(
      {Comment comment,
      List<Annotation> metadata,
      Token lateKeyword,
      Token keyword,
      TypeAnnotation type,
      List<VariableDeclaration> variables}) {
    return new VariableDeclarationListImpl(
        comment, metadata, lateKeyword, keyword, type, variables);
  }

  @override
  VariableDeclarationStatement variableDeclarationStatement(
          VariableDeclarationList variableList, Token semicolon) =>
      new VariableDeclarationStatementImpl(variableList, semicolon);

  @override
  WhileStatement whileStatement(Token whileKeyword, Token leftParenthesis,
          Expression condition, Token rightParenthesis, Statement body) =>
      new WhileStatementImpl(
          whileKeyword, leftParenthesis, condition, rightParenthesis, body);

  @override
  WithClause withClause(Token withKeyword, List<TypeName> mixinTypes) =>
      new WithClauseImpl(withKeyword, mixinTypes);

  @override
  YieldStatement yieldStatement(Token yieldKeyword, Token star,
          Expression expression, Token semicolon) =>
      new YieldStatementImpl(yieldKeyword, star, expression, semicolon);
}
