/**
  * @param RuntimeConfiguration $configuration
  *
  * @return NewOperator
  */
 public function generate(RuntimeConfiguration $configuration)
 {
     $this->typeCheck->generate(func_get_args());
     $validatorNamespaceCall = new Call(new StaticMember(QualifiedIdentifier::fromString('\\Eloquent\\Cosmos\\ClassName'), new Constant(new Identifier('fromString'))));
     $validatorNamespaceCall->add(new Literal($configuration->validatorNamespace()->string()));
     $newConfigurationCall = new Call(QualifiedIdentifier::fromString('\\Eloquent\\Typhoon\\Configuration\\RuntimeConfiguration'));
     $newConfigurationCall->add($validatorNamespaceCall);
     $newConfigurationCall->add(new Literal($configuration->useNativeCallable()));
     return new NewOperator($newConfigurationCall);
 }
 /**
  * @param RuntimeConfiguration $configuration
  * @param null                 &$className
  *
  * @return SyntaxTree
  */
 public function generateSyntaxTree(RuntimeConfiguration $configuration, &$className = null)
 {
     $this->typeCheck->generateSyntaxTree(func_get_args());
     $className = $configuration->validatorNamespace()->joinAtoms('DummyValidator');
     $classDefinition = new ClassDefinition(new Identifier($className->shortName()->string()));
     $classDefinition->setParentName(QualifiedIdentifier::fromString('AbstractValidator'));
     $classDefinition->add($this->generateCallMethod());
     $primaryBlock = new PhpBlock();
     $primaryBlock->add(new NamespaceStatement(QualifiedIdentifier::fromString($className->parent()->toRelative()->string())));
     $primaryBlock->add($classDefinition);
     $syntaxTree = new SyntaxTree();
     $syntaxTree->add($primaryBlock);
     return $syntaxTree;
 }
 /**
  * @return ConcreteMethod
  */
 protected function generateConstructor()
 {
     $this->typeCheck->generateConstructor(func_get_args());
     $parameterNameIdentifier = new Identifier('parameterName');
     $parameterNameVariable = new Variable($parameterNameIdentifier);
     $indexIdentifier = new Identifier('index');
     $indexVariable = new Variable($indexIdentifier);
     $expectedTypeIdentifier = new Identifier('expectedType');
     $expectedTypeVariable = new Variable($expectedTypeIdentifier);
     $previousIdentifier = new Identifier('previous');
     $thisVariable = new Variable(new Identifier('this'));
     $thisParameterNameMember = new Member($thisVariable, new Constant($parameterNameIdentifier));
     $thisIndexMember = new Member($thisVariable, new Constant($indexIdentifier));
     $thisExpectedTypeMember = new Member($thisVariable, new Constant($expectedTypeIdentifier));
     $method = new ConcreteMethod(new Identifier('__construct'), AccessModifier::PUBLIC_());
     $method->addParameter(new Parameter($parameterNameIdentifier));
     $method->addParameter(new Parameter($indexIdentifier));
     $method->addParameter(new Parameter($expectedTypeIdentifier));
     $previousParameter = new Parameter($previousIdentifier, new ObjectTypeHint(QualifiedIdentifier::fromString('\\Exception')));
     $previousParameter->setDefaultValue(new Literal(null));
     $method->addParameter($previousParameter);
     $method->statementBlock()->add(new ExpressionStatement(new Assign($thisParameterNameMember, $parameterNameVariable)));
     $method->statementBlock()->add(new ExpressionStatement(new Assign($thisIndexMember, $indexVariable)));
     $method->statementBlock()->add(new ExpressionStatement(new Assign($thisExpectedTypeMember, $expectedTypeVariable)));
     $sprintfCall = new Call(QualifiedIdentifier::fromString('\\sprintf'));
     $sprintfCall->add(new Literal("Missing argument for parameter '%s' at index %d. Expected '%s'."));
     $sprintfCall->add($parameterNameVariable);
     $sprintfCall->add($indexVariable);
     $sprintfCall->add($expectedTypeVariable);
     $parentConstructCall = new Call(new StaticMember(new Constant(new Identifier('parent')), new Constant(new Identifier('__construct'))));
     $parentConstructCall->add($sprintfCall);
     $parentConstructCall->add(new Variable($previousIdentifier));
     $method->statementBlock()->add(new ExpressionStatement($parentConstructCall));
     return $method;
 }
 /**
  * @return ConcreteMethod
  */
 protected function generateStreamTypeMethod()
 {
     $this->typeCheck->generateStreamTypeMethod(func_get_args());
     $valueIdentifier = new Identifier('value');
     $valueVariable = new Variable($valueIdentifier);
     $metaDataVariable = new Variable(new Identifier('metaData'));
     $metaDataModeSubscript = new Subscript($metaDataVariable, new Literal('mode'));
     $readableVariable = new Variable(new Identifier('readable'));
     $writableVariable = new Variable(new Identifier('writable'));
     $method = new ConcreteMethod(new Identifier('streamType'), AccessModifier::PROTECTED_());
     $method->addParameter(new Parameter($valueIdentifier));
     $streamGetMetaDataCall = new Call(QualifiedIdentifier::fromString('\\stream_get_meta_data'));
     $streamGetMetaDataCall->add($valueVariable);
     $method->statementBlock()->add(new ExpressionStatement(new Assign($metaDataVariable, $streamGetMetaDataCall)));
     $readablePregMatchCall = new Call(QualifiedIdentifier::fromString('\\preg_match'));
     $readablePregMatchCall->add(new Literal('/[r+]/'));
     $readablePregMatchCall->add($metaDataModeSubscript);
     $readableIf = new IfStatement($readablePregMatchCall, new StatementBlock(), new StatementBlock());
     $readableIf->trueBranch()->add(new ExpressionStatement(new Assign($readableVariable, new Literal('true'))));
     $readableIf->falseBranch()->add(new ExpressionStatement(new Assign($readableVariable, new Literal('false'))));
     $method->statementBlock()->add($readableIf);
     $writablePregMatchCall = new Call(QualifiedIdentifier::fromString('\\preg_match'));
     $writablePregMatchCall->add(new Literal('/[waxc+]/'));
     $writablePregMatchCall->add($metaDataModeSubscript);
     $writableIf = new IfStatement($writablePregMatchCall, new StatementBlock(), new StatementBlock());
     $writableIf->trueBranch()->add(new ExpressionStatement(new Assign($writableVariable, new Literal('true'))));
     $writableIf->falseBranch()->add(new ExpressionStatement(new Assign($writableVariable, new Literal('false'))));
     $method->statementBlock()->add($writableIf);
     $sprintfCall = new Call(QualifiedIdentifier::fromString('\\sprintf'));
     $sprintfCall->add(new Literal('stream {readable: %s, writable: %s}'));
     $sprintfCall->add($readableVariable);
     $sprintfCall->add($writableVariable);
     $method->statementBlock()->add(new ReturnStatement($sprintfCall));
     return $method;
 }
 /**
  * @param TupleType $type
  *
  * @return LogicalAnd|Closure
  */
 public function visitTupleType(TupleType $type)
 {
     $this->typeCheck->visitTupleType(func_get_args());
     $tupleSize = count($type->types());
     $isArrayCall = new Call(QualifiedIdentifier::fromString('\\is_array'));
     $isArrayCall->add($this->valueExpression());
     $arrayKeysCall = new Call(QualifiedIdentifier::fromString('\\array_keys'));
     $arrayKeysCall->add($this->valueExpression());
     $rangeCall = new Call(QualifiedIdentifier::fromString('\\range'));
     $rangeCall->add(new Literal(0));
     $rangeCall->add(new Literal($tupleSize - 1));
     $sequentialKeyExpression = new StrictEquals($arrayKeysCall, $rangeCall);
     $expressions = array($isArrayCall, $sequentialKeyExpression);
     $closures = array();
     $closureCalls = array();
     $checkVariable = new Variable(new Identifier('check'));
     foreach ($type->types() as $index => $subType) {
         $this->valueIndex = $index;
         $expression = $subType->accept($this);
         if ($expression instanceof Closure) {
             $closures[] = $expression;
             $checkCall = new Call($checkVariable);
             $checkCall->add($this->valueExpression());
             $closureCalls[] = $checkCall;
         } else {
             $expressions[] = $expression;
         }
     }
     $this->valueIndex = null;
     $tupleExpression = null;
     foreach ($expressions as $expression) {
         if ($tupleExpression) {
             $tupleExpression->add($expression);
         } else {
             $tupleExpression = new LogicalAnd($expression);
         }
     }
     $numClosures = count($closures);
     if ($numClosures < 1) {
         return $tupleExpression;
     }
     $closure = new Closure();
     $closure->addParameter(new Parameter($this->valueIdentifier));
     $ifStatement = new IfStatement(new LogicalNot($tupleExpression));
     $ifStatement->trueBranch()->add(new ReturnStatement(new Literal(false)));
     $closure->statementBlock()->add($ifStatement);
     $lastClosureIndex = $numClosures - 1;
     for ($i = 0; $i < $lastClosureIndex; $i++) {
         $closure->statementBlock()->add(new ExpressionStatement(new Assign($checkVariable, $closures[$i])));
         $ifStatement = new IfStatement(new LogicalNot($closureCalls[$i]));
         $ifStatement->trueBranch()->add(new ReturnStatement(new Literal(false)));
         $closure->statementBlock()->add($ifStatement);
     }
     $closure->statementBlock()->add(new ExpressionStatement(new Assign($checkVariable, $closures[$lastClosureIndex])));
     $closure->statementBlock()->add(new ReturnStatement($closureCalls[$lastClosureIndex]));
     return $closure;
 }
 /**
  * @return ConcreteMethod
  */
 protected function generateCallMethod()
 {
     $this->typeCheck->generateCallMethod(func_get_args());
     $nameIdentifier = new Identifier('name');
     $nameVariable = new Variable($nameIdentifier);
     $argumentsIdentifier = new Identifier('arguments');
     $validatorMethodNameVariable = new Variable(new Identifier('validatorMethodName'));
     $thisVariable = new Variable(new Identifier('this'));
     $reflectorMember = new Member($thisVariable, new Constant(new Identifier('reflector')));
     $method = new ConcreteMethod(new Identifier('__call'), AccessModifier::PUBLIC_());
     $method->addParameter(new Parameter($nameIdentifier));
     $method->addParameter(new Parameter($argumentsIdentifier, new ArrayTypeHint()));
     $ltrimCall = new Call(QualifiedIdentifier::fromString('\\ltrim'));
     $ltrimCall->add($nameVariable);
     $ltrimCall->add(new Literal('_'));
     $ucfirstCall = new Call(QualifiedIdentifier::fromString('\\ucfirst'));
     $ucfirstCall->add($ltrimCall);
     $validatorMethodNameSprintfCall = new Call(QualifiedIdentifier::fromString('\\sprintf'));
     $validatorMethodNameSprintfCall->add(new Literal('validate%s'));
     $validatorMethodNameSprintfCall->add($ucfirstCall);
     $method->statementBlock()->add(new ExpressionStatement(new Assign($validatorMethodNameVariable, $validatorMethodNameSprintfCall)));
     $reflectorHasMethodCall = new Call(new Member($reflectorMember, new Constant(new Identifier('hasMethod'))));
     $reflectorHasMethodCall->add($validatorMethodNameVariable);
     $undefinedMethodIf = new IfStatement(new LogicalNot($reflectorHasMethodCall));
     $exceptionMessageSprintfCall = new Call(QualifiedIdentifier::fromString('\\sprintf'));
     $exceptionMessageSprintfCall->add(new Literal('Call to undefined method %s::%s().'));
     $exceptionMessageSprintfCall->add(new Constant(new Identifier('__CLASS__')));
     $exceptionMessageSprintfCall->add($nameVariable);
     $newBadMethodCallExceptionCall = new Call(QualifiedIdentifier::fromString('\\BadMethodCallException'));
     $newBadMethodCallExceptionCall->add($exceptionMessageSprintfCall);
     $undefinedMethodIf->trueBranch()->add(new ThrowStatement(new NewOperator($newBadMethodCallExceptionCall)));
     $method->statementBlock()->add($undefinedMethodIf);
     $getMethodCall = new Call(new Member($reflectorMember, new Constant(new Identifier('getMethod'))));
     $getMethodCall->add($validatorMethodNameVariable);
     $invokeArgsCall = new Call(new Member($getMethodCall, new Constant(new Identifier('invokeArgs'))));
     $invokeArgsCall->add($thisVariable);
     $invokeArgsCall->add(new Variable($argumentsIdentifier));
     $method->statementBlock()->add(new ReturnStatement($invokeArgsCall));
     return $method;
 }
Beispiel #7
0
 /**
  * @param RuntimeConfiguration $configuration
  *
  * @return ConcreteMethod
  */
 protected function generateDefineValidatorMethod(RuntimeConfiguration $configuration)
 {
     $this->typeCheck->generateDefineValidatorMethod(func_get_args());
     $classNameIdentifier = new Identifier('className');
     $classNameVariable = new Variable($classNameIdentifier);
     $classGeneratorIdentifier = new Identifier('classGenerator');
     $classGeneratorVariable = new Variable($classGeneratorIdentifier);
     $classGeneratorClassIdentifier = QualifiedIdentifier::fromString('\\Eloquent\\Typhoon\\Generator\\ValidatorClassGenerator');
     $method = new ConcreteMethod(new Identifier('defineValidator'), AccessModifier::PROTECTED_(), true);
     $method->addParameter(new Parameter($classNameIdentifier));
     $classGeneratorParameter = new Parameter($classGeneratorIdentifier, new ObjectTypeHint($classGeneratorClassIdentifier));
     $classGeneratorParameter->setDefaultValue(new Literal(null));
     $method->addParameter($classGeneratorParameter);
     $nullClassGeneratorIf = new IfStatement(new StrictEquals(new Literal(null), $classGeneratorVariable));
     $nullClassGeneratorIf->trueBranch()->add(new ExpressionStatement(new Assign($classGeneratorVariable, new NewOperator($classGeneratorClassIdentifier))));
     $method->statementBlock()->add($nullClassGeneratorIf);
     $evalCall = new Call(QualifiedIdentifier::fromString('eval'));
     $generateFromClassCall = new Call(new Member($classGeneratorVariable, new Constant(new Identifier('generateFromClass'))));
     $generateFromClassCall->add(new Call(new StaticMember(new Constant(new Identifier('static')), new Constant(new Identifier('configuration')))));
     $newReflectorCall = new Call(QualifiedIdentifier::fromString('\\ReflectionClass'));
     $newReflectorCall->add($classNameVariable);
     $newReflector = new NewOperator($newReflectorCall);
     $generateFromClassCall->add($newReflector);
     $evalCall->add(new Concat(new Literal('?>'), $generateFromClassCall));
     $method->statementBlock()->add(new ExpressionStatement($evalCall));
     return $method;
 }
 /**
  * @param RuntimeConfiguration $configuration
  *
  * @return ConcreteMethod
  */
 protected function generateConstructor(RuntimeConfiguration $configuration)
 {
     $this->typeCheck->generateConstructor(func_get_args());
     $indexIdentifier = new Identifier('index');
     $indexVariable = new Variable($indexIdentifier);
     $valueIdentifier = new Identifier('value');
     $valueVariable = new Variable($valueIdentifier);
     $previousIdentifier = new Identifier('previous');
     $previousVariable = new Variable($previousIdentifier);
     $typeInspectorIdentifier = new Identifier('typeInspector');
     $typeInspectorVariable = new Variable($typeInspectorIdentifier);
     $thisVariable = new Variable(new Identifier('this'));
     $thisIndexMember = new Member($thisVariable, new Constant($indexIdentifier));
     $thisValueMember = new Member($thisVariable, new Constant($valueIdentifier));
     $thisTypeInspectorMember = new Member($thisVariable, new Constant($typeInspectorIdentifier));
     $thisUnexpectedTypeMember = new Member($thisVariable, new Constant(new Identifier('unexpectedType')));
     $typeInspectorClassName = QualifiedIdentifier::fromString($configuration->validatorNamespace()->joinAtoms('TypeInspector')->string());
     $method = new ConcreteMethod(new Identifier('__construct'), AccessModifier::PUBLIC_());
     $method->addParameter(new Parameter($indexIdentifier));
     $method->addParameter(new Parameter($valueIdentifier));
     $previousParameter = new Parameter($previousIdentifier, new ObjectTypeHint(QualifiedIdentifier::fromString('\\Exception')));
     $previousParameter->setDefaultValue(new Literal(null));
     $method->addParameter($previousParameter);
     $typeInspectorParameter = new Parameter($typeInspectorIdentifier, new ObjectTypeHint($typeInspectorClassName));
     $typeInspectorParameter->setDefaultValue(new Literal(null));
     $method->addParameter($typeInspectorParameter);
     $nullTypeInspectorIf = new IfStatement(new StrictEquals(new Literal(null), $typeInspectorVariable));
     $nullTypeInspectorIf->trueBranch()->add(new ExpressionStatement(new Assign($typeInspectorVariable, new NewOperator(new Call($typeInspectorClassName)))));
     $method->statementBlock()->add($nullTypeInspectorIf);
     $method->statementBlock()->add(new ExpressionStatement(new Assign($thisIndexMember, $indexVariable)));
     $method->statementBlock()->add(new ExpressionStatement(new Assign($thisValueMember, $valueVariable)));
     $method->statementBlock()->add(new ExpressionStatement(new Assign($thisTypeInspectorMember, $typeInspectorVariable)));
     $typeInspectorTypeCall = new Call(new Member($typeInspectorVariable, new Constant(new Identifier('type'))));
     $typeInspectorTypeCall->add($thisValueMember);
     $method->statementBlock()->add(new ExpressionStatement(new Assign($thisUnexpectedTypeMember, $typeInspectorTypeCall)));
     $sprintfCall = new Call(QualifiedIdentifier::fromString('\\sprintf'));
     $sprintfCall->add(new Literal("Unexpected argument of type '%s' at index %d."));
     $sprintfCall->add($thisUnexpectedTypeMember);
     $sprintfCall->add($indexVariable);
     $parentConstructCall = new Call(new StaticMember(new Constant(new Identifier('parent')), new Constant(new Identifier('__construct'))));
     $parentConstructCall->add($sprintfCall);
     $parentConstructCall->add(new Variable($previousIdentifier));
     $method->statementBlock()->add(new ExpressionStatement($parentConstructCall));
     return $method;
 }
 /**
  * @param ParameterList $parameterList
  *
  * @return array<integer,IStatement>
  */
 public function visitParameterList(ParameterList $parameterList)
 {
     $this->typeCheck->visitParameterList(func_get_args());
     $expressions = array();
     $parameters = $parameterList->parameters();
     $parameterCount = count($parameters);
     $argumentsVariable = new Variable(new Identifier('arguments'));
     // empty parameter list
     if ($parameterCount < 1) {
         $zeroLiteral = new Literal(0);
         $countCall = new Call(QualifiedIdentifier::fromString('\\count'));
         $countCall->add($argumentsVariable);
         $newExceptionCall = new Call(QualifiedIdentifier::fromString($this->validatorNamespace()->joinAtoms('Exception', 'UnexpectedArgumentException')->string()));
         $newExceptionCall->add($zeroLiteral);
         $newExceptionCall->add(new Subscript($argumentsVariable, $zeroLiteral));
         $ifStatement = new IfStatement(new Greater($countCall, $zeroLiteral));
         $ifStatement->trueBranch()->add(new ThrowStatement(new NewOperator($newExceptionCall)));
         $expressions[] = $ifStatement;
         return $this->wrapExpressions($expressions);
     }
     $argumentCountVariable = new Variable(new Identifier('argumentCount'));
     $argumentCountCall = new Call(QualifiedIdentifier::fromString('\\count'));
     $argumentCountCall->add($argumentsVariable);
     $expressions[] = new Assign($argumentCountVariable, $argumentCountCall);
     // missing parameter checks
     $requiredParameterCount = count($parameterList->requiredParameters());
     $lastRequiredParameterIndex = $requiredParameterCount - 1;
     $missingParametersStatement = null;
     if ($requiredParameterCount > 0) {
         $missingParametersStatement = new IfStatement(new Less($argumentCountVariable, new Literal($requiredParameterCount)));
         for ($i = 0; $i < $lastRequiredParameterIndex; $i++) {
             $newExceptionCall = new Call(QualifiedIdentifier::fromString($this->validatorNamespace()->joinAtoms('Exception', 'MissingArgumentException')->string()));
             $newExceptionCall->add(new Literal($parameters[$i]->name()));
             $newExceptionCall->add(new Literal($i));
             $newExceptionCall->add(new Literal($this->renderTypeName($parameters[$i]->type())));
             $ifStatement = new IfStatement(new Less($argumentCountVariable, new Literal($i + 1)));
             $ifStatement->trueBranch()->add(new ThrowStatement(new NewOperator($newExceptionCall)));
             $missingParametersStatement->trueBranch()->add($ifStatement);
         }
         $newExceptionCall = new Call(QualifiedIdentifier::fromString($this->validatorNamespace()->joinAtoms('Exception', 'MissingArgumentException')->string()));
         $newExceptionCall->add(new Literal($parameters[$lastRequiredParameterIndex]->name()));
         $newExceptionCall->add(new Literal($lastRequiredParameterIndex));
         $newExceptionCall->add(new Literal($this->renderTypeName($parameters[$lastRequiredParameterIndex]->type())));
         $missingParametersStatement->trueBranch()->add(new ThrowStatement(new NewOperator($newExceptionCall)));
     }
     // unexpected arguments check
     if (!$parameterList->isVariableLength()) {
         $parameterCountLiteral = new Literal($parameterCount);
         $newExceptionCall = new Call(QualifiedIdentifier::fromString($this->validatorNamespace()->joinAtoms('Exception', 'UnexpectedArgumentException')->string()));
         $newExceptionCall->add($parameterCountLiteral);
         $newExceptionCall->add(new Subscript($argumentsVariable, $parameterCountLiteral));
         $tooManyParametersStatement = new IfStatement(new Greater($argumentCountVariable, $parameterCountLiteral));
         $tooManyParametersStatement->trueBranch()->add(new ThrowStatement(new NewOperator($newExceptionCall)));
         if ($missingParametersStatement) {
             $missingParametersStatement->setFalseBranch($tooManyParametersStatement);
         } else {
             $expressions[] = $tooManyParametersStatement;
         }
     }
     if ($missingParametersStatement) {
         $expressions[] = $missingParametersStatement;
     }
     // type checks
     foreach ($parameters as $index => $parameter) {
         $isVariableLength = $parameterList->isVariableLength() && $index === $parameterCount - 1;
         $indexLiteral = new Literal($index);
         $oldArgumentExpression = $this->argumentExpression;
         $oldIndexExpression = $this->indexExpression;
         if (!$isVariableLength) {
             $this->indexExpression = $indexLiteral;
             $this->argumentExpression = new Subscript($argumentsVariable, $this->indexExpression);
         }
         $parameterExpressions = $parameter->accept($this);
         if (count($parameterExpressions) < 1) {
             $this->argumentExpression = $oldArgumentExpression;
             $this->indexExpression = $oldIndexExpression;
             continue;
         }
         array_unshift($parameterExpressions, new ExpressionStatement(new Assign(new Variable(new Identifier('value')), $this->argumentExpression)));
         $parameterExpressions = $this->wrapExpressions($parameterExpressions);
         // wrap variable length in loop
         if ($isVariableLength) {
             $closure = new Closure();
             $closure->addParameter(new ParameterASTNode(new Identifier('argument')));
             $closure->addParameter(new ParameterASTNode(new Identifier('index')));
             foreach ($parameterExpressions as $expression) {
                 $closure->statementBlock()->add($expression);
             }
             $checkVariable = new Variable(new Identifier('check'));
             $indexVariable = new Variable(new Identifier('index'));
             $checkCall = new Call($checkVariable);
             $checkCall->add(new Subscript($argumentsVariable, $indexVariable));
             $checkCall->add($indexVariable);
             $loopContents = new StatementBlock();
             $loopContents->add(new ExpressionStatement($checkCall));
             $parameterExpressions = array(new ExpressionStatement(new Assign($checkVariable, $closure)), new ForStatement(new Assign($indexVariable, $indexLiteral), new Less($indexVariable, $argumentCountVariable), new PostfixIncrement($indexVariable), $loopContents));
         }
         // wrap optional in if statement
         if ($parameter->isOptional()) {
             $if = new IfStatement(new Greater($argumentCountVariable, $indexLiteral));
             foreach ($parameterExpressions as $expression) {
                 $if->trueBranch()->add($expression);
             }
             $parameterExpressions = array($if);
         }
         foreach ($parameterExpressions as $expression) {
             $expressions[] = $expression;
         }
         $this->argumentExpression = $oldArgumentExpression;
         $this->indexExpression = $oldIndexExpression;
     }
     return $this->wrapExpressions($expressions);
 }
 /**
  * @return ConcreteMethod
  */
 protected function generateConstructor()
 {
     $this->typeCheck->generateConstructor(func_get_args());
     $messageIdentifier = new Identifier('message');
     $previousIdentifier = new Identifier('previous');
     $method = new ConcreteMethod(new Identifier('__construct'), AccessModifier::PUBLIC_());
     $method->addParameter(new Parameter($messageIdentifier));
     $previousParameter = new Parameter($previousIdentifier, new ObjectTypeHint(QualifiedIdentifier::fromString('\\Exception')));
     $previousParameter->setDefaultValue(new Literal(null));
     $method->addParameter($previousParameter);
     $parentConstructCall = new Call(new StaticMember(new Constant(new Identifier('parent')), new Constant(new Identifier('__construct'))));
     $parentConstructCall->add(new Variable($messageIdentifier));
     $parentConstructCall->add(new Literal(0));
     $parentConstructCall->add(new Variable($previousIdentifier));
     $method->statementBlock()->add(new ExpressionStatement($parentConstructCall));
     return $method;
 }