This is an automated email from the ASF dual-hosted git repository. neilcsmith pushed a commit to branch delivery in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/delivery by this push: new 6b9c7a3a30a Improved method checks in enum declaration new ec3ab743f84 Merge pull request #5341 from KacerCZ/php-enum-check-methods 6b9c7a3a30a is described below commit 6b9c7a3a30ad176856b5f8bfa6debeec129453d0 Author: Tomas Prochazka <ka...@razdva.cz> AuthorDate: Sun Jan 22 13:11:33 2023 +0100 Improved method checks in enum declaration - Checks declaration of forbidden methods. - Adds __invoke and __debugInfo to list of magic methods. Docs - https://www.php.net/manual/en/language.enumerations.listing.php - https://www.php.net/manual/en/class.backedenum.php - https://www.php.net/manual/en/language.enumerations.object-differences.php - https://www.php.net/manual/en/language.oop5.magic.php Closes #5086, closes #5094 --- .../modules/php/editor/PredefinedSymbols.java | 2 + .../verification/IncorrectEnumHintError.java | 40 +++++++++- .../IncorrectEnumHintError/testIncorrectEnums.php | 46 ++++++++++++ ...testIncorrectEnums.php.testIncorrectEnums.hints | 87 ++++++++++++++++++++++ 4 files changed, 172 insertions(+), 3 deletions(-) diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/PredefinedSymbols.java b/php/php.editor/src/org/netbeans/modules/php/editor/PredefinedSymbols.java index 006641fed3c..440bc9592d9 100644 --- a/php/php.editor/src/org/netbeans/modules/php/editor/PredefinedSymbols.java +++ b/php/php.editor/src/org/netbeans/modules/php/editor/PredefinedSymbols.java @@ -101,6 +101,8 @@ public final class PredefinedSymbols { "__sleep", // NOI18N "__wakeup", // NOI18N "__toString", // NOI18N + "__invoke", // NOI18N + "__debugInfo", // NOI18N "__serialize", // NOI18N PHP 7.4 "__unserialize", // NOI18N PHP 7.4 }))); diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/verification/IncorrectEnumHintError.java b/php/php.editor/src/org/netbeans/modules/php/editor/verification/IncorrectEnumHintError.java index 1c0d10d3015..faa3dcf11ad 100644 --- a/php/php.editor/src/org/netbeans/modules/php/editor/verification/IncorrectEnumHintError.java +++ b/php/php.editor/src/org/netbeans/modules/php/editor/verification/IncorrectEnumHintError.java @@ -30,6 +30,7 @@ import org.netbeans.modules.csl.api.HintFix; import org.netbeans.modules.csl.api.OffsetRange; import org.netbeans.modules.csl.spi.support.CancelSupport; import org.netbeans.modules.php.editor.CodeUtils; +import org.netbeans.modules.php.editor.PredefinedSymbols; import org.netbeans.modules.php.editor.model.EnumScope; import org.netbeans.modules.php.editor.model.FieldElement; import org.netbeans.modules.php.editor.model.FileScope; @@ -57,8 +58,26 @@ import org.openide.util.NbBundle; */ public class IncorrectEnumHintError extends HintErrorRule { + private static final Map<String, String> FORBIDDEN_MAGIC_METHODS = new HashMap<>(); + private static final Map<String, String> FORBIDDEN_BACKED_ENUM_METHODS = new HashMap<>(); + private FileObject fileObject; + static { + for (String methodName : PredefinedSymbols.MAGIC_METHODS) { + // Methods __call, __callStatic and __invoke are allowed in enum. + if ("__call".equals(methodName) // NOI18N + || "__callStatic".equals(methodName) // NOI18N + || "__invoke".equals(methodName)) { // NOI18N + continue; + } + FORBIDDEN_MAGIC_METHODS.put(methodName.toLowerCase(), methodName); + } + + FORBIDDEN_BACKED_ENUM_METHODS.put("from", "from"); // NOI18N + FORBIDDEN_BACKED_ENUM_METHODS.put("tryfrom", "tryFrom"); // NOI18N + } + @Override @NbBundle.Messages("IncorrectEnumHintError.displayName=Incorrect Declaration of Enumeration") public String getDisplayName() { @@ -73,7 +92,11 @@ public class IncorrectEnumHintError extends HintErrorRule { "# {0} - the trait name", "IncorrectEnumHintError.incorrectEnumPropertiesWithTrait=Enum cannot have properties, but \"{0}\" has properties", "IncorrectEnumHintError.incorrectEnumConstructor=Enum cannot have a constructor", - }) + "IncorrectEnumHintError.incorrectEnumMethodCases=Enum cannot redeclare method \"cases\"", + "# {0} - the method name", + "IncorrectEnumHintError.incorrectEnumMagicMethod=Enum cannot contain magic method method \"{0}\"", + "# {0} - the method name", + "IncorrectEnumHintError.incorrectBackedEnumMethod=Backed enum cannot redeclare method \"{0}\"",}) public void invoke(PHPRuleContext context, List<Hint> hints) { PHPParseResult phpParseResult = (PHPParseResult) context.parserResult; if (phpParseResult.getProgram() == null) { @@ -113,7 +136,9 @@ public class IncorrectEnumHintError extends HintErrorRule { return; } checkTraits(declaredEnum.getTraits(), declaredEnum, hints, checkVisitor.getUseTraits()); - checkConstructor(declaredEnum.getDeclaredMethods(), hints); + // Forbidden methods from traits are ignored by PHP + boolean isBackedEnum = declaredEnum.getBackingType() != null; + checkMethods(declaredEnum.getDeclaredMethods(), isBackedEnum, hints); } } } @@ -142,13 +167,22 @@ public class IncorrectEnumHintError extends HintErrorRule { } } - private void checkConstructor(Collection<? extends MethodScope> methods, List<Hint> hints) { + private void checkMethods(Collection<? extends MethodScope> methods, boolean isBackedEnum, List<Hint> hints) { for (MethodScope method : methods) { if (CancelSupport.getDefault().isCancelled()) { return; } if (method.isConstructor()) { addHint(method, Bundle.IncorrectEnumHintError_incorrectEnumConstructor(), hints); + continue; + } + String methodName = method.getName().toLowerCase(); + if ("cases".equals(methodName)) { // NOI18N + addHint(method, Bundle.IncorrectEnumHintError_incorrectEnumMethodCases(), hints); + } else if (FORBIDDEN_MAGIC_METHODS.containsKey(methodName)) { + addHint(method, Bundle.IncorrectEnumHintError_incorrectEnumMagicMethod(FORBIDDEN_MAGIC_METHODS.get(methodName)), hints); + } else if (isBackedEnum && FORBIDDEN_BACKED_ENUM_METHODS.containsKey(methodName)) { + addHint(method, Bundle.IncorrectEnumHintError_incorrectBackedEnumMethod(FORBIDDEN_BACKED_ENUM_METHODS.get(methodName)), hints); } } } diff --git a/php/php.editor/test/unit/data/testfiles/verification/IncorrectEnumHintError/testIncorrectEnums.php b/php/php.editor/test/unit/data/testfiles/verification/IncorrectEnumHintError/testIncorrectEnums.php index 1c87b7710a5..67bb8b04d25 100644 --- a/php/php.editor/test/unit/data/testfiles/verification/IncorrectEnumHintError/testIncorrectEnums.php +++ b/php/php.editor/test/unit/data/testfiles/verification/IncorrectEnumHintError/testIncorrectEnums.php @@ -40,6 +40,52 @@ enum IncorrectConstructor { } } +enum IncorrectMethods { + public function cases():array {} + public function __get($name) {} + public function __set($name,$value) {} + public function __isset($name) {} + public function __unset($name) {} + public function __sleep() {} + public function __wakeup() {} + public function __serialize() {} + public function __unserialize($array) {} + public function __toString() {} + public static function __set_state($state) {} + public function __clone() {} + public function __debugInfo() {} +} + +enum IncorrectMethodsBacked: string { + public function cases():array {} + public function from(string|int $value):self {} + public function tryFrom(string|int $value):self {} +} + +enum IncorrectMethodsCorrectCaseInMessage { + public function Cases():array {} + public function __GET($name) {} + public function __seT($name,$value) {} + public function __ISset($name) {} + public function __unSET($name) {} + public function __sleeP() {} + public function __wAkeup() {} + public function __Serialize() {} + public function __Unserialize($array) {} + public function __ToString() {} + public static function __Set_State($state) {} + public function __clONe() {} + public function __DebugInfo() {} +} + +enum CorrectMethods { + public function from(string|int $value):self {} + public function tryFrom(string|int $value):self {} + public function __call($name,$args) {} + public static function __callStatic($name,$args) {} + public function __invoke() {} +} + enum CorrectBackingTypeString: string { case CASE_NAME; } diff --git a/php/php.editor/test/unit/data/testfiles/verification/IncorrectEnumHintError/testIncorrectEnums.php.testIncorrectEnums.hints b/php/php.editor/test/unit/data/testfiles/verification/IncorrectEnumHintError/testIncorrectEnums.php.testIncorrectEnums.hints index 3ead2c1f278..36c0309db3a 100644 --- a/php/php.editor/test/unit/data/testfiles/verification/IncorrectEnumHintError/testIncorrectEnums.php.testIncorrectEnums.hints +++ b/php/php.editor/test/unit/data/testfiles/verification/IncorrectEnumHintError/testIncorrectEnums.php.testIncorrectEnums.hints @@ -20,6 +20,93 @@ HINT:Enum cannot have properties public function __construct() { ----------- HINT:Enum cannot have a constructor + public function cases():array {} + ----- +HINT:Enum cannot redeclare method "cases" + public function __get($name) {} + ----- +HINT:Enum cannot contain magic method method "__get" + public function __set($name,$value) {} + ----- +HINT:Enum cannot contain magic method method "__set" + public function __isset($name) {} + ------- +HINT:Enum cannot contain magic method method "__isset" + public function __unset($name) {} + ------- +HINT:Enum cannot contain magic method method "__unset" + public function __sleep() {} + ------- +HINT:Enum cannot contain magic method method "__sleep" + public function __wakeup() {} + -------- +HINT:Enum cannot contain magic method method "__wakeup" + public function __serialize() {} + ----------- +HINT:Enum cannot contain magic method method "__serialize" + public function __unserialize($array) {} + ------------- +HINT:Enum cannot contain magic method method "__unserialize" + public function __toString() {} + ---------- +HINT:Enum cannot contain magic method method "__toString" + public static function __set_state($state) {} + ----------- +HINT:Enum cannot contain magic method method "__set_state" + public function __clone() {} + ------- +HINT:Enum cannot contain magic method method "__clone" + public function __debugInfo() {} + ----------- +HINT:Enum cannot contain magic method method "__debugInfo" + public function cases():array {} + ----- +HINT:Enum cannot redeclare method "cases" + public function from(string|int $value):self {} + ---- +HINT:Backed enum cannot redeclare method "from" + public function tryFrom(string|int $value):self {} + ------- +HINT:Backed enum cannot redeclare method "tryFrom" + public function Cases():array {} + ----- +HINT:Enum cannot redeclare method "cases" + public function __GET($name) {} + ----- +HINT:Enum cannot contain magic method method "__get" + public function __seT($name,$value) {} + ----- +HINT:Enum cannot contain magic method method "__set" + public function __ISset($name) {} + ------- +HINT:Enum cannot contain magic method method "__isset" + public function __unSET($name) {} + ------- +HINT:Enum cannot contain magic method method "__unset" + public function __sleeP() {} + ------- +HINT:Enum cannot contain magic method method "__sleep" + public function __wAkeup() {} + -------- +HINT:Enum cannot contain magic method method "__wakeup" + public function __Serialize() {} + ----------- +HINT:Enum cannot contain magic method method "__serialize" + public function __Unserialize($array) {} + ------------- +HINT:Enum cannot contain magic method method "__unserialize" + public function __ToString() {} + ---------- +HINT:Enum cannot contain magic method method "__toString" + public static function __Set_State($state) {} + ----------- +HINT:Enum cannot contain magic method method "__set_state" + public function __clONe() {} + ------- +HINT:Enum cannot contain magic method method "__clone" + public function __DebugInfo() {} + ----------- +HINT:Enum cannot contain magic method method "__debugInfo" case C; ------- HINT:"case" can only be in enums --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists