Repository: glayzzle/php-parser
Pull request #93 (2017-10-08 00:10:35)

Added support for static lookup on property
Example
```php
$this->foo::bar;
```

I don't see any rfc or documentation for this feature but it does work in php 7.0, iv been using it in production for quit a while.


Patch:
diff --git a/src/parser/variable.js b/src/parser/variable.js
index 1379fece..668d742a 100644
--- a/src/parser/variable.js
+++ b/src/parser/variable.js
@@ -126,7 +126,25 @@ module.exports = {
           }
           result = node(result, offset);
           break;
-        
+        case this.tok.T_DOUBLE_COLON:
+          var node = this.node('staticlookup'), offset;
+          this.next();
+
+          if(this.is('IDENTIFIER') || this.token === this.tok.T_STRING
+              || this.token === this.tok.T_CLASS
+          ) {
+            offset = this.node('constref');
+            var name = this.text();
+            this.next();
+            offset = offset(name);
+
+            if(this.token === this.tok.T_OBJECT_OPERATOR || this.token === this.tok.T_DOUBLE_COLON) {
+              this.error();
+            }
+          }
+
+          result = node(result, offset);
+          break;
         case this.tok.T_OBJECT_OPERATOR:
           var node = this.node('propertylookup');
           var what = null;


Test patch:
diff --git a/test/variableTests.js b/test/variableTests.js
index 48a009eb..2165a08c 100644
--- a/test/variableTests.js
+++ b/test/variableTests.js
@@ -48,7 +48,8 @@ describe('Test variables', function() {
       'parent::foo();',
       'foo::class;',
       '$this->foo();',
-      'foo::$bar;'
+      'foo::$bar;',
+      '$this->foo::bar["baz"]::qux();'
     ].join('\n'), {
       parser: {
         // debug: true
@@ -104,6 +105,30 @@ describe('Test variables', function() {
       expr.offset.kind.should.be.exactly('variable');
       expr.offset.name.should.be.exactly('bar');
     });
+    it('should be $this->foo::bar["baz"]::qux();', function() {
+      var expr = ast.children[6];
+
+      expr.kind.should.be.exactly("call");
+      expr.arguments.length.should.be.exactly(0);
+
+      expr.what.kind.should.be.exactly("staticlookup");
+      expr.what.offset.kind.should.be.exactly("constref");
+      expr.what.offset.name.should.be.exactly("qux");
+
+      expr.what.what.kind.should.be.exactly("offsetlookup");
+      expr.what.what.offset.kind.should.be.exactly("string");
+      expr.what.what.offset.value.should.be.exactly("baz");
+
+      expr.what.what.what.kind.should.be.exactly("staticlookup");
+      expr.what.what.what.offset.kind.should.be.exactly("constref");
+      expr.what.what.what.offset.name.should.be.exactly("bar");
+
+      expr.what.what.what.what.kind.should.be.exactly("propertylookup");
+      expr.what.what.what.what.what.kind.should.be.exactly("variable");
+      expr.what.what.what.what.what.name.should.be.exactly("this");
+      expr.what.what.what.what.offset.kind.should.be.exactly("constref");
+      expr.what.what.what.what.offset.name.should.be.exactly("foo");
+    });
   });
 
 
@@ -163,5 +188,36 @@ describe('Test variables', function() {
       ast.children[0].left.kind.should.be.exactly('variable');
       ast.children[0].left.name.should.be.exactly('?');
     });
+    
+    it('should fail on double static lookup', function() {
+      var astErr = parser.parseEval([
+        'this->foo::bar::baz;'
+      ].join('\n'), {
+        parser: {
+          suppressErrors: true
+        }
+      });
+
+      var msg = 'Parse Error : syntax error, unexpected \'::\' (T_DOUBLE_COLON) on line 1';
+      astErr.errors.length.should.be.exactly(1);
+      astErr.errors[0].line.should.be.exactly(1);
+      astErr.errors[0].message.should.be.exactly(msg);
+    });
+    
+    it('should fail on property lookup on static lookup', function() {
+      var astErr = parser.parseEval([
+        'this->foo::bar->baz;'
+      ].join('\n'), {
+        parser: {
+          suppressErrors: true
+        }
+      });
+
+      var msg = 'Parse Error : syntax error, unexpected \'->\' (T_OBJECT_OPERATOR) on line 1';
+      astErr.errors.length.should.be.exactly(1);
+      astErr.errors[0].line.should.be.exactly(1);
+      astErr.errors[0].message.should.be.exactly(msg);
+    });
+    
   });
 });