Skip to content
This repository has been archived by the owner on Dec 23, 2023. It is now read-only.

Restore the ability to retrieve the filename from a Node. #229

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/NodeInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
* indicate they support the Node API.
*/
interface NodeInterface {

/**
* Get the filename of the node.
* @return string
*/
public function getFilename();

/**
* Get the line number of the node.
* @return int
Expand Down
8 changes: 8 additions & 0 deletions src/ParentNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,14 @@ public function acceptVisitor(VisitorInterface $visitor) {
$visitor->visitEnd($this);
}

public function getFilename() {
if ($this->head === NULL) {
return $this->parent->getFilename();
}
$child = $this->head;
return $child->getFilename();
}

public function getLineNumber() {
if ($this->head === NULL) {
return $this->parent->getLineNumber();
Expand Down
64 changes: 29 additions & 35 deletions src/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,6 @@ class Parser {
*/
private static $visibilityTypes = [T_PUBLIC, T_PROTECTED, T_PRIVATE];

/**
* Filename being parsed.
* @var string
*/
private $filename;

/**
* Iterator over PHP tokens.
* @var TokenIterator
Expand Down Expand Up @@ -235,8 +229,8 @@ public static function parseSource($source, $filename = NULL) {
$tokenizer = new Tokenizer();
$parser = new self();
}
$tokenizer->setFileName($filename);
$tokens = $tokenizer->getAll($source);
$parser->filename = $filename;
return $parser->buildTree(new TokenIterator($tokens));
}

Expand Down Expand Up @@ -285,7 +279,7 @@ private function templateStatementList(ParentNode $node) {
}
else {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
'expected PHP opening tag, but got ' . $this->iterator->current()->getText());
Expand Down Expand Up @@ -723,7 +717,7 @@ private function caseStatement($terminator) {
$node->addChild($this->expr(), 'matchOn');
if (!$this->tryMatch(':', $node, NULL, TRUE, TRUE) && !$this->tryMatch(';', $node, NULL, TRUE, TRUE)) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
'expected :');
Expand All @@ -739,7 +733,7 @@ private function caseStatement($terminator) {
$this->mustMatch(T_DEFAULT, $node);
if (!$this->tryMatch(':', $node, NULL, TRUE, TRUE) && !$this->tryMatch(';', $node, NULL, TRUE, TRUE)) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
'expected :');
Expand All @@ -751,7 +745,7 @@ private function caseStatement($terminator) {
return $node;
}
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"expected case or default");
Expand Down Expand Up @@ -886,7 +880,7 @@ private function globalVar() {
}
}
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
'expected a global variable (eg. T_VARIABLE)');
Expand Down Expand Up @@ -1229,13 +1223,13 @@ private function expr($static = FALSE) {
}
else {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"invalid expression");
}
}
return $this->expressionParser->parse($expression_nodes, $this->filename);
return $this->expressionParser->parse($expression_nodes, $this->iterator->getFilename());
}

/**
Expand Down Expand Up @@ -1459,7 +1453,7 @@ private function exprOperand() {
return $this->backtick();
}
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"excepted expression operand but got " . $this->current->getTypeName());
Expand Down Expand Up @@ -1721,7 +1715,7 @@ private function encapsVar() {
if ($this->tryMatch('[', $node)) {
if (!in_array($this->currentType, $offset_types)) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
'expected encaps_var_offset (T_STRING or T_NUM_STRING or T_VARIABLE)');
Expand All @@ -1735,7 +1729,7 @@ private function encapsVar() {
return $node;
}
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
'expected encaps variable');
Expand Down Expand Up @@ -1897,7 +1891,7 @@ private function variable() {
}
}
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"expected variable");
Expand Down Expand Up @@ -2272,7 +2266,7 @@ private function innerStatement() {
switch ($this->currentType) {
case T_HALT_COMPILER:
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"__halt_compiler can only be used from the outermost scope");
Expand Down Expand Up @@ -2491,7 +2485,7 @@ private function classStatement($is_abstract) {
case T_PRIVATE:
if ($modifiers->getVisibility()) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"can only have one visibility modifier on class member/method."
Expand All @@ -2502,7 +2496,7 @@ private function classStatement($is_abstract) {
case T_STATIC:
if ($modifiers->getStatic()) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"duplicate modifier");
Expand All @@ -2512,14 +2506,14 @@ private function classStatement($is_abstract) {
case T_FINAL:
if ($modifiers->getFinal()) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"duplicate modifier");
}
if ($modifiers->getAbstract()) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"can not use final modifier on abstract method");
Expand All @@ -2529,21 +2523,21 @@ private function classStatement($is_abstract) {
case T_ABSTRACT:
if ($modifiers->getAbstract()) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"duplicate modifier");
}
if ($modifiers->getFinal()) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"can not use abstract modifier on final method");
}
if (!$is_abstract) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"can not use abstract modifier in non-abstract class");
Expand All @@ -2556,14 +2550,14 @@ private function classStatement($is_abstract) {
return $this->classMemberList($doc_comment, $modifiers);
default:
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"invalid class statement");
}
}
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"invalid class statement");
Expand All @@ -2580,14 +2574,14 @@ private function classMemberList($doc_comment, ModifiersNode $modifiers) {
// Modifier checks
if ($modifiers->getAbstract()) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"members can not be declared abstract");
}
if ($modifiers->getFinal()) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"members can not be declared final");
Expand Down Expand Up @@ -2766,7 +2760,7 @@ private function interfaceMethod() {
while (in_array($this->currentType, $visibility_keyword_types)) {
if ($node->getVisibility()) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
"can only have one visibility modifier on interface method."
Expand Down Expand Up @@ -2797,15 +2791,15 @@ private function traitDeclaration() {
$node->addChild($name_node, 'name');
if ($this->currentType === T_EXTENDS) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
'Traits can only be composed from other traits with the \'use\' keyword.'
);
}
if ($this->currentType === T_IMPLEMENTS) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
'Traits can not implement interfaces.'
Expand Down Expand Up @@ -2947,7 +2941,7 @@ private function matchDocComment(ParentNode $parent, $property_name = 'docCommen
private function mustMatch($expected_type, ParentNode $parent, $property_name = NULL, $maybe_last = FALSE, $capture_doc_comment = FALSE) {
if ($this->currentType !== $expected_type) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
'expected ' . TokenNode::typeName($expected_type));
Expand Down Expand Up @@ -3022,7 +3016,7 @@ private function tryMatchToken($expected_types) {
private function mustMatchToken($expected_type) {
if ($this->currentType !== $expected_type) {
throw new ParserException(
$this->filename,
$this->iterator->getFilename(),
$this->iterator->getLineNumber(),
$this->iterator->getColumnNumber(),
'expected ' . TokenNode::typeName($expected_type));
Expand Down
11 changes: 11 additions & 0 deletions src/TokenIterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ public function hasNext() {
return $this->position + 1 < $this->length;
}

/**
* @return string
*/
public function getFilename() {
$token = $this->current();
if ($token === NULL) {
$token = $this->tokens[$this->length - 1];
}
return $token->getFilename();
}

/**
* @return int
*/
Expand Down
16 changes: 15 additions & 1 deletion src/TokenNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ class TokenNode extends Node {
*/
protected $lineNo;

/**
* @var string
*/
protected $filename;

/**
* @var int
*/
Expand All @@ -39,20 +44,29 @@ class TokenNode extends Node {
* Construct token.
* @param int $type
* @param string $text
* @param string $filename
* @param int $lineNo
* @param int $newlineCount
* @param int $colNo
* @param int $byteOffset
*/
public function __construct($type, $text, $lineNo = -1, $newlineCount = -1, $colNo = -1, $byteOffset = -1) {
public function __construct($type, $text, $filename = '', $lineNo = -1, $newlineCount = -1, $colNo = -1, $byteOffset = -1) {
$this->type = $type;
$this->text = $text;
$this->filename = $filename;
$this->lineNo = $lineNo;
$this->newlineCount = $newlineCount;
$this->colNo = $colNo;
$this->byteOffset = $byteOffset;
}

/**
* @return string
*/
public function getFilename() {
return $this->filename;
}

/**
* @return int
*/
Expand Down
Loading