Skip to content

Commit 8bb0959

Browse files
authored
Merge pull request microsoft#333 from PythooonUser/issue-178
Issue 178 - Declare Statement Directive List
2 parents 3fdca6b + ec691a0 commit 8bb0959

26 files changed

+357
-22
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
/*---------------------------------------------------------------------------------------------
3+
* Copyright (c) Microsoft Corporation. All rights reserved.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
namespace Microsoft\PhpParser\Node\DelimitedList;
8+
9+
use Microsoft\PhpParser\Node\DelimitedList;
10+
11+
class DeclareDirectiveList extends DelimitedList {
12+
}

src/Node/Statement/DeclareStatement.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace Microsoft\PhpParser\Node\Statement;
88

99
use Microsoft\PhpParser\Node;
10+
use Microsoft\PhpParser\Node\DelimitedList;
1011
use Microsoft\PhpParser\Node\StatementNode;
1112
use Microsoft\PhpParser\Token;
1213

@@ -17,6 +18,8 @@ class DeclareStatement extends StatementNode {
1718
public $openParen;
1819
/** @var Node */
1920
public $declareDirective;
21+
/** @var DelimitedList\DeclareDirectiveList|null TODO: Merge with $declareDirective in a future backwards incompatible release. */
22+
public $otherDeclareDirectives;
2023
/** @var Token */
2124
public $closeParen;
2225
/** @var Token|null */
@@ -32,6 +35,7 @@ class DeclareStatement extends StatementNode {
3235
'declareKeyword',
3336
'openParen',
3437
'declareDirective',
38+
'otherDeclareDirectives',
3539
'closeParen',
3640
'colon',
3741
'statements',

src/Parser.php

Lines changed: 70 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2312,7 +2312,7 @@ private function parseDeclareStatement($parentNode) {
23122312
$declareStatement->parent = $parentNode;
23132313
$declareStatement->declareKeyword = $this->eat1(TokenKind::DeclareKeyword);
23142314
$declareStatement->openParen = $this->eat1(TokenKind::OpenParenToken);
2315-
$declareStatement->declareDirective = $this->parseDeclareDirective($declareStatement);
2315+
$this->parseAndSetDeclareDirectiveList($declareStatement);
23162316
$declareStatement->closeParen = $this->eat1(TokenKind::CloseParenToken);
23172317

23182318
if ($this->checkToken(TokenKind::SemicolonToken)) {
@@ -2329,26 +2329,76 @@ private function parseDeclareStatement($parentNode) {
23292329
return $declareStatement;
23302330
}
23312331

2332-
private function parseDeclareDirective($parentNode) {
2333-
$declareDirective = new DeclareDirective();
2332+
/**
2333+
* @param DeclareStatement $parentNode
2334+
*/
2335+
private function parseAndSetDeclareDirectiveList($parentNode) {
2336+
$declareDirectiveList = $this->parseDeclareDirectiveList($parentNode);
2337+
2338+
if (!$declareDirectiveList) {
2339+
$declareDirective = new DeclareDirective();
2340+
$declareDirective->parent = $parentNode;
2341+
2342+
$declareDirective->name = new MissingToken(TokenKind::Name, $this->token->fullStart);
2343+
$declareDirective->equals = new MissingToken(TokenKind::EqualsToken, $this->token->fullStart);
2344+
// TODO: This is matching the first token in $this::parseDeclareDirectiveFn.
2345+
// Probably best to emit a more general "literal error".
2346+
$declareDirective->literal = new MissingToken(TokenKind::FloatingLiteralToken, $this->token->fullStart);
2347+
2348+
$parentNode->declareDirective = $declareDirective;
2349+
return;
2350+
}
2351+
2352+
$declareDirective = array_shift($declareDirectiveList->children);
2353+
$parentNode->declareDirective = $declareDirective;
23342354
$declareDirective->parent = $parentNode;
2335-
$declareDirective->name = $this->eat1(TokenKind::Name);
2336-
$declareDirective->equals = $this->eat1(TokenKind::EqualsToken);
2337-
$declareDirective->literal =
2338-
$this->eat(
2339-
TokenKind::FloatingLiteralToken,
2340-
TokenKind::IntegerLiteralToken,
2341-
TokenKind::DecimalLiteralToken,
2342-
TokenKind::OctalLiteralToken,
2343-
TokenKind::HexadecimalLiteralToken,
2344-
TokenKind::BinaryLiteralToken,
2345-
TokenKind::InvalidOctalLiteralToken,
2346-
TokenKind::InvalidHexadecimalLiteral,
2347-
TokenKind::InvalidBinaryLiteral,
2348-
TokenKind::StringLiteralToken
2349-
); // TODO simplify
2350-
2351-
return $declareDirective;
2355+
2356+
if ($declareDirectiveList->children) {
2357+
$parentNode->otherDeclareDirectives = $declareDirectiveList;
2358+
}
2359+
}
2360+
2361+
/**
2362+
* @param DeclareStatement $parentNode
2363+
* @return DelimitedList\DeclareDirectiveList|null
2364+
*/
2365+
private function parseDeclareDirectiveList($parentNode) {
2366+
$declareDirectiveList = $this->parseDelimitedList(
2367+
DelimitedList\DeclareDirectiveList::class,
2368+
TokenKind::CommaToken,
2369+
function ($token) {
2370+
return $token->kind === TokenKind::Name;
2371+
},
2372+
$this->parseDeclareDirectiveFn(),
2373+
$parentNode,
2374+
false
2375+
);
2376+
2377+
return $declareDirectiveList;
2378+
}
2379+
2380+
private function parseDeclareDirectiveFn() {
2381+
return function ($parentNode) {
2382+
$declareDirective = new DeclareDirective();
2383+
$declareDirective->parent = $parentNode;
2384+
$declareDirective->name = $this->eat1(TokenKind::Name);
2385+
$declareDirective->equals = $this->eat1(TokenKind::EqualsToken);
2386+
$declareDirective->literal =
2387+
$this->eat(
2388+
TokenKind::FloatingLiteralToken,
2389+
TokenKind::IntegerLiteralToken,
2390+
TokenKind::DecimalLiteralToken,
2391+
TokenKind::OctalLiteralToken,
2392+
TokenKind::HexadecimalLiteralToken,
2393+
TokenKind::BinaryLiteralToken,
2394+
TokenKind::InvalidOctalLiteralToken,
2395+
TokenKind::InvalidHexadecimalLiteral,
2396+
TokenKind::InvalidBinaryLiteral,
2397+
TokenKind::StringLiteralToken
2398+
); // TODO simplify
2399+
2400+
return $declareDirective;
2401+
};
23522402
}
23532403

23542404
private function parseSimpleVariable($parentNode) {

tests/ParserGrammarTest.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
* Licensed under the MIT License. See License.txt in the project root for license information.
55
*--------------------------------------------------------------------------------------------*/
66

7-
use Microsoft\PhpParser\Token;
87
use Microsoft\PhpParser\DiagnosticsProvider;
98
use PHPUnit\Framework\Test;
109
use PHPUnit\Framework\TestCase;
@@ -123,7 +122,7 @@ public function testSpecOutputTreeClassificationAndLength($testCaseFile, $expect
123122
}
124123

125124
public function outTreeProvider() {
126-
$testCases = glob(__dir__ . "/cases/php-langspec/**/*.php");
125+
$testCases = glob(__DIR__ . "/cases/php-langspec/**/*.php");
127126
$skipped = json_decode(file_get_contents(__DIR__ . "/skipped.json"));
128127

129128
$testProviderArray = array();

tests/cases/parser/declareStatement1.php.tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
}
3838
}
3939
},
40+
"otherDeclareDirectives": null,
4041
"closeParen": {
4142
"kind": "CloseParenToken",
4243
"textLength": 1

tests/cases/parser/declareStatement10.php.tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
}
3838
}
3939
},
40+
"otherDeclareDirectives": null,
4041
"closeParen": {
4142
"kind": "CloseParenToken",
4243
"textLength": 1

tests/cases/parser/declareStatement11.php.tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
}
3838
}
3939
},
40+
"otherDeclareDirectives": null,
4041
"closeParen": {
4142
"kind": "CloseParenToken",
4243
"textLength": 1

tests/cases/parser/declareStatement12.php.tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
}
4141
}
4242
},
43+
"otherDeclareDirectives": null,
4344
"closeParen": {
4445
"kind": "CloseParenToken",
4546
"textLength": 1

tests/cases/parser/declareStatement13.php.tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
}
3838
}
3939
},
40+
"otherDeclareDirectives": null,
4041
"closeParen": {
4142
"kind": "CloseParenToken",
4243
"textLength": 1
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
3+
declare(strict_types=1, ticks=1);

0 commit comments

Comments
 (0)