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