Skip to content

Commit

Permalink
Ast: added FunctionNode
Browse files Browse the repository at this point in the history
  • Loading branch information
janpecha committed Jul 1, 2024
1 parent f99b450 commit 2f2e2d5
Show file tree
Hide file tree
Showing 9 changed files with 596 additions and 23 deletions.
159 changes: 159 additions & 0 deletions src/Ast/FunctionNode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<?php

declare(strict_types=1);

namespace CzProject\PhpSimpleAst\Ast;


class FunctionNode implements INode
{
/** @var PhpDocNode|NULL */
private $phpDocNode;

/** @var string */
private $indentation;

/** @var string */
private $keyword;

/** @var Name|NULL */
private $name;

/** @var Parameters */
private $parameters;

/** @var InheritedVariables|NULL */
private $inheritedVariables;

/** @var FunctionReturnType|NULL */
private $returnType;

/** @var FunctionBody */
private $body;


public function __construct(
?PhpDocNode $phpDocNode,
string $indentation,
string $keyword,
?Name $name,
Parameters $parameters,
?InheritedVariables $inheritedVariables,
?FunctionReturnType $returnType,
FunctionBody $body
)
{
$this->phpDocNode = $phpDocNode;
$this->indentation = $indentation;
$this->keyword = $keyword;
$this->name = $name;
$this->parameters = $parameters;
$this->returnType = $returnType;
$this->inheritedVariables = $inheritedVariables;
$this->body = $body;
}


public function getName(): ?string
{
return $this->name !== NULL
? $this->name->getName()
: NULL;
}


public function getDocComment(): ?string
{
return $this->phpDocNode !== NULL ? $this->phpDocNode->getContent() : NULL;
}


/**
* @return Parameter[]
*/
public function getParameters(): array
{
return $this->parameters->getParameters();
}


public function hasReturnType(): bool
{
return $this->returnType !== NULL;
}


public function toString(): string
{
$s = $this->phpDocNode !== NULL ? $this->phpDocNode->toString() : '';
$s .= $this->indentation;
$s .= $this->keyword;

if ($this->name !== NULL) {
$s .= $this->name->toString();
}

$s .= $this->parameters->toString();

if ($this->inheritedVariables !== NULL) {
$s .= $this->inheritedVariables->toString();
}

if ($this->returnType !== NULL) {
$s .= $this->returnType->toString();
}

$s .= $this->body->toString();
return $s;
}


/**
* @return self
*/
public static function parse(
?PhpDocNode $phpDocNode,
NodeParser $parser
)
{
$nodeIndentation = $parser->consumeNodeIndentation();
$keyword = $parser->consumeTokenAsText(T_FUNCTION);
$parser->consumeWhitespace();
$name = Name::tryParseFunctionName($parser->createSubParser());
$parser->tryConsumeWhitespace();
$parameters = Parameters::parse($parser->createSubParser());
$parser->tryConsumeWhitespace();
$inheritedVariables = NULL;
$returnType = NULL;
$body = NULL;

if ($name === NULL && $parser->isCurrent(T_USE)) {
$inheritedVariables = InheritedVariables::parse($parser->createSubParser());
$parser->tryConsumeWhitespace();
}

if ($parser->isCurrent(':')) {
$returnType = FunctionReturnType::parse($parser->createSubParser());
$parser->tryConsumeWhitespace();
}

if ($parser->isCurrent(T_COMMENT)) {
$parser->consumeAsIndentation(T_COMMENT);
$parser->tryConsumeWhitespace();
}

$body = FunctionBody::parse($parser->createSubParser());
$parser->close();

return new self(
$phpDocNode,
$nodeIndentation,
$keyword,
$name,
$parameters,
$inheritedVariables,
$returnType,
$body
);
}
}
59 changes: 59 additions & 0 deletions src/Ast/InheritedVariable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

namespace CzProject\PhpSimpleAst\Ast;


class InheritedVariable
{
/** @var VariableName */
private $variable;

/** @var Literal|NULL */
private $suffix;


public function __construct(
VariableName $variable,
?Literal $suffix
)
{
$this->variable = $variable;
$this->suffix = $suffix;
}


public function toString(): string
{
$s = $this->variable->toString();

if ($this->suffix !== NULL) {
$s .= $this->suffix->toString();
}

return $s;
}


/**
* @return self
*/
public static function parse(NodeParser $parser)
{
$variable = VariableName::parse($parser->createSubParser());
$parser->tryConsumeWhitespace();
$suffix = NULL;

if ($parser->isCurrent(',')) {
$suffix = Literal::parseToken($parser->createSubParser(), ',');
}

$parser->close();

return new self(
$variable,
$suffix
);
}
}
81 changes: 81 additions & 0 deletions src/Ast/InheritedVariables.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

declare(strict_types=1);

namespace CzProject\PhpSimpleAst\Ast;


class InheritedVariables
{
/** @var Literal */
private $keyword;

/** @var Literal */
private $opener;

/** @var InheritedVariable[] */
private $variables;

/** @var Literal */
private $closer;


/**
* @param InheritedVariable[] $variables
*/
public function __construct(
Literal $keyword,
Literal $opener,
array $variables,
Literal $closer
)
{
$this->keyword = $keyword;
$this->opener = $opener;
$this->variables = $variables;
$this->closer = $closer;
}


public function toString(): string
{
$s = $this->keyword->toString();
$s .= $this->opener->toString();

foreach ($this->variables as $variable) {
$s .= $variable->toString();
}

$s .= $this->closer->toString();
return $s;
}


/**
* @return self
*/
public static function parse(NodeParser $parser)
{
$keyword = Literal::parseToken($parser->createSubParser(), T_USE);
$parser->tryConsumeWhitespace();
$opener = Literal::parseToken($parser->createSubParser(), '(');
$inheritedVariables = [];

do {
$parser->tryConsumeWhitespace();
$inheritedVariables[] = InheritedVariable::parse($parser->createSubParser());
$parser->tryConsumeWhitespace();

} while (!$parser->isCurrent(')'));

$closer = Literal::parseToken($parser->createSubParser(), ')');
$parser->close();

return new self(
$keyword,
$opener,
$inheritedVariables,
$closer
);
}
}
18 changes: 18 additions & 0 deletions src/Ast/Name.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,22 @@ public static function tryParseClassName(NodeParser $parser)
$parser->close();
return $name !== '' ? new self($nodeIndentation, $name) : NULL;
}


/**
* @return self|NULL
*/
public static function tryParseFunctionName(NodeParser $parser)
{
$nodeIndentation = '';
$name = '';

if ($parser->isCurrent(T_STRING)) {
$nodeIndentation = $parser->consumeNodeIndentation();
$name = $parser->consumeTokenAsText(T_STRING);
}

$parser->close();
return $name !== '' ? new self($nodeIndentation, $name) : NULL;
}
}
3 changes: 3 additions & 0 deletions src/Ast/NamespaceNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ public static function parse(NodeParser $parser)
$parser->consumeAsUnknowContent(T_DOUBLE_COLON);
$parser->tryConsumeAsUnknowContent(T_CLASS);

} elseif ($parser->isCurrent(T_FUNCTION)) {
$child = FunctionNode::parse(NULL, $parser->createSubParser());

} elseif ($parser->isCurrent(T_USE)) {
$child = UseNode::parse($parser->createSubParser());

Expand Down
3 changes: 3 additions & 0 deletions src/Ast/PhpNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ public static function parse(NodeParser $parser)
$parser->consumeAsUnknowContent(T_DOUBLE_COLON);
$parser->tryConsumeAsUnknowContent(T_CLASS);

} elseif ($parser->isCurrent(T_FUNCTION)) {
$child = FunctionNode::parse(NULL, $parser->createSubParser());

} elseif ($parser->isCurrent(T_USE)) {
$child = UseNode::parse($parser->createSubParser());

Expand Down
Loading

0 comments on commit 2f2e2d5

Please sign in to comment.