Skip to content

Commit

Permalink
PHP 8.3 Support: Dynamic class constant fetch (Part 5)
Browse files Browse the repository at this point in the history
- apache#6701
- https://wiki.php.net/rfc/dynamic_class_constant_fetch
- Fix the `IntroduceSuggestion` and `PHP55UnhandledError`
- Add unit tests
  • Loading branch information
junichi11 committed Nov 27, 2023
1 parent a491904 commit e53b927
Show file tree
Hide file tree
Showing 24 changed files with 373 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
import org.netbeans.modules.php.editor.model.FileScope;
import org.netbeans.modules.php.editor.model.FunctionScope;
import org.netbeans.modules.php.editor.model.IndexScope;
import org.netbeans.modules.php.editor.model.InterfaceScope;
import org.netbeans.modules.php.editor.model.MethodScope;
import org.netbeans.modules.php.editor.model.ModelElement;
import org.netbeans.modules.php.editor.model.ModelUtils;
Expand Down Expand Up @@ -1684,7 +1683,8 @@ public static Collection<? extends TypeScope> getStaticTypeName(Scope inScope, S
csi = (EnumScope) methodInScope;
}
}
if (inScope instanceof ClassScope || inScope instanceof InterfaceScope) {
if (inScope instanceof TypeScope) {
// e.g. const EXAMPLE = self::UNDEFINED;
csi = (TypeScope) inScope;
}
if (csi != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
import org.netbeans.modules.php.editor.parser.astnodes.Expression;
import org.netbeans.modules.php.editor.parser.astnodes.FieldAccess;
import org.netbeans.modules.php.editor.parser.astnodes.MethodInvocation;
import org.netbeans.modules.php.editor.parser.astnodes.NamespaceName;
import org.netbeans.modules.php.editor.parser.astnodes.StaticConstantAccess;
import org.netbeans.modules.php.editor.parser.astnodes.StaticFieldAccess;
import org.netbeans.modules.php.editor.parser.astnodes.StaticMethodInvocation;
Expand Down Expand Up @@ -349,7 +350,9 @@ public void visit(StaticConstantAccess staticConstantAccess) {
if (CancelSupport.getDefault().isCancelled()) {
return;
}
if (lineBounds.containsInclusive(staticConstantAccess.getStartOffset())) {
if (!staticConstantAccess.isDynamicName()
&& (staticConstantAccess.getDispatcher() instanceof NamespaceName) // e.g. ClassName::CONSTANT, self::CONSTANT
&& lineBounds.containsInclusive(staticConstantAccess.getStartOffset())) {
String constName = staticConstantAccess.getConstantName().getName();
String clzName = CodeUtils.extractUnqualifiedClassName(staticConstantAccess);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,15 @@ public void visit(StaticConstantAccess node) {
if (CancelSupport.getDefault().isCancelled()) {
return;
}
Identifier constant = node.getConstantName();
if (constant != null) {
String constantName = constant.getName();
if ("class".equals(constantName.toLowerCase())) { //NOI18N
createError(constant);
if (node.isDynamicName()) {
super.visit(node);
} else {
Identifier constant = node.getConstantName();
if (constant != null) {
String constantName = constant.getName();
if ("class".equals(constantName.toLowerCase())) { //NOI18N
createError(constant);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

class Test {
public const BAR = 'bar';
public const BA = 'BA';
public const A = self::{'BAR'};
public const B = self::{self::{'BA'} . 'R'};
public const C = self::{self::BA . self::R};
}

trait TraitTest {
public const TRAIT_BA = 'BA';
public const TRAIT_B = self::{self::{'BA'} . 'R'};
public const TRAIT_C = self::{self::TRAIT_BA . self::TRAIT_R};
}

enum EnumTest: string {
case BAR = 'bar';
case BA = 'BA';
case A = self::{'BAR'};
case B = self::{self::{'BA'} . 'R'};
case C = self::{self::BA . self::R};
}

Test::{"BAR"};
$test::{"BAR"};
Test::{test()}::{test($bar)};
Test::{test('foo')}::FOO;

EnumTest::{"BAR"};
EnumTest::{test()}::{test($bar)};
EnumTest::{test('foo')}::FOO;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public const C = self::{self::BA . self::^R};
-------
HINT:Introduce Hint
FIX:Create Constant "R" in Class "Test" (testDynamicClassConstantFetch.php)
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

class Test {
public const BAR = 'bar';
public const BA = 'BA';
public const A = self::{'BAR'};
public const B = self::{self::{'BA'} . 'R'};
public const C = self::{self::BA . self::R};
const R = "";
}

trait TraitTest {
public const TRAIT_BA = 'BA';
public const TRAIT_B = self::{self::{'BA'} . 'R'};
public const TRAIT_C = self::{self::TRAIT_BA . self::TRAIT_R};
}

enum EnumTest: string {
case BAR = 'bar';
case BA = 'BA';
case A = self::{'BAR'};
case B = self::{self::{'BA'} . 'R'};
case C = self::{self::BA . self::R};
}

Test::{"BAR"};
$test::{"BAR"};
Test::{test()}::{test($bar)};
Test::{test('foo')}::FOO;

EnumTest::{"BAR"};
EnumTest::{test()}::{test($bar)};
EnumTest::{test('foo')}::FOO;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
case C = self::{self::BA . self::^R};
-------
HINT:Introduce Hint
FIX:Create Constant "R" in Enum "EnumTest" (testDynamicClassConstantFetch.php)
HINT:Introduce Hint
FIX:Create Enum Case "R" in Enum "EnumTest" (testDynamicClassConstantFetch.php)
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

class Test {
public const BAR = 'bar';
public const BA = 'BA';
public const A = self::{'BAR'};
public const B = self::{self::{'BA'} . 'R'};
public const C = self::{self::BA . self::R};
}

trait TraitTest {
public const TRAIT_BA = 'BA';
public const TRAIT_B = self::{self::{'BA'} . 'R'};
public const TRAIT_C = self::{self::TRAIT_BA . self::TRAIT_R};
}

enum EnumTest: string {

const R = "";

case BAR = 'bar';
case BA = 'BA';
case A = self::{'BAR'};
case B = self::{self::{'BA'} . 'R'};
case C = self::{self::BA . self::R};
}

Test::{"BAR"};
$test::{"BAR"};
Test::{test()}::{test($bar)};
Test::{test('foo')}::FOO;

EnumTest::{"BAR"};
EnumTest::{test()}::{test($bar)};
EnumTest::{test('foo')}::FOO;
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

class Test {
public const BAR = 'bar';
public const BA = 'BA';
public const A = self::{'BAR'};
public const B = self::{self::{'BA'} . 'R'};
public const C = self::{self::BA . self::R};
}

trait TraitTest {
public const TRAIT_BA = 'BA';
public const TRAIT_B = self::{self::{'BA'} . 'R'};
public const TRAIT_C = self::{self::TRAIT_BA . self::TRAIT_R};
}

enum EnumTest: string {
case BAR = 'bar';
case BA = 'BA';
case A = self::{'BAR'};
case B = self::{self::{'BA'} . 'R'};
case C = self::{self::BA . self::R};
case R = '';
}

Test::{"BAR"};
$test::{"BAR"};
Test::{test()}::{test($bar)};
Test::{test('foo')}::FOO;

EnumTest::{"BAR"};
EnumTest::{test()}::{test($bar)};
EnumTest::{test('foo')}::FOO;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public const TRAIT_C = self::{self::TRAIT_BA . self::TRA^IT_R};
-------------
HINT:Introduce Hint
FIX:Create Constant "TRAIT_R" in Trait "TraitTest" (testDynamicClassConstantFetch.php)
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

class Test {
public const BAR = 'bar';
public const BA = 'BA';
public const A = self::{'BAR'};
public const B = self::{self::{'BA'} . 'R'};
public const C = self::{self::BA . self::R};
}

trait TraitTest {
public const TRAIT_BA = 'BA';
public const TRAIT_B = self::{self::{'BA'} . 'R'};
public const TRAIT_C = self::{self::TRAIT_BA . self::TRAIT_R};
const TRAIT_R = "";
}

enum EnumTest: string {
case BAR = 'bar';
case BA = 'BA';
case A = self::{'BAR'};
case B = self::{self::{'BA'} . 'R'};
case C = self::{self::BA . self::R};
}

Test::{"BAR"};
$test::{"BAR"};
Test::{test()}::{test($bar)};
Test::{test('foo')}::FOO;

EnumTest::{"BAR"};
EnumTest::{test()}::{test($bar)};
EnumTest::{test('foo')}::FOO;

0 comments on commit e53b927

Please sign in to comment.