Skip to content

Commit

Permalink
PHP 8.4 Support: Property hooks (Part 4)
Browse files Browse the repository at this point in the history
  • Loading branch information
junichi11 committed Feb 13, 2025
1 parent 0935fb4 commit 8cff930
Show file tree
Hide file tree
Showing 8 changed files with 614 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@
import org.netbeans.modules.parsing.api.Source;
import org.netbeans.modules.php.editor.lexer.LexUtilities;
import org.netbeans.modules.php.editor.lexer.PHPTokenId;
import org.netbeans.modules.php.editor.model.FieldElement;
import org.netbeans.modules.php.editor.model.FileScope;
import org.netbeans.modules.php.editor.model.FunctionScope;
import org.netbeans.modules.php.editor.model.GroupUseScope;
import org.netbeans.modules.php.editor.model.MethodScope;
import org.netbeans.modules.php.editor.model.Model;
import org.netbeans.modules.php.editor.model.ModelElement;
import org.netbeans.modules.php.editor.model.PropertyHookScope;
import org.netbeans.modules.php.editor.model.Scope;
import org.netbeans.modules.php.editor.model.TypeScope;
import org.netbeans.modules.php.editor.model.UseScope;
Expand Down Expand Up @@ -108,6 +110,16 @@ public final class FoldingScanner {
Bundle.FT_Functions(),
FoldTemplate.DEFAULT_BLOCK);

@NbBundle.Messages("FT_HookedFields=Fields(Properties)")
public static final FoldType TYPE_HOOKED_FIELD = FoldType.MEMBER.derive("field", // NOI18N
Bundle.FT_HookedFields(),
FoldTemplate.DEFAULT_BLOCK);

@NbBundle.Messages("FT_PropertyHooks=Property hooks")
public static final FoldType TYPE_PROPERTY_HOOK = FoldType.MEMBER.derive("property hook", // NOI18N
Bundle.FT_PropertyHooks(),
FoldTemplate.DEFAULT_BLOCK);

@NbBundle.Messages("FT_Arrays=Arrays")
public static final FoldType TYPE_ARRAY = FoldType.NESTED.derive(
"array",
Expand Down Expand Up @@ -273,21 +285,25 @@ private void processPHPTags(Map<String, List<OffsetRange>> folds, Document docum

private void processScopes(Map<String, List<OffsetRange>> folds, List<Scope> scopes) {
processUseScopes(folds, scopes);
processTypeAndFunctionScopes(folds, scopes);
processTypeAndMemberScopes(folds, scopes);
}

private void processTypeAndFunctionScopes(Map<String, List<OffsetRange>> folds, List<Scope> scopes) {
private void processTypeAndMemberScopes(Map<String, List<OffsetRange>> folds, List<Scope> scopes) {
for (Scope scope : scopes) {
OffsetRange offsetRange = scope.getBlockRange();
if (offsetRange == null || offsetRange.getLength() <= 1) {
continue;
}
if (scope instanceof TypeScope) {
getRanges(folds, TYPE_CLASS).add(offsetRange);
} else {
if (scope instanceof FunctionScope || scope instanceof MethodScope) {
getRanges(folds, TYPE_FUNCTION).add(offsetRange);
} else if (scope instanceof FunctionScope || scope instanceof MethodScope) {
getRanges(folds, TYPE_FUNCTION).add(offsetRange);
} else if (scope instanceof FieldElement.HookedFieldElement field) {
if (field.isHooked()) {
getRanges(folds, TYPE_HOOKED_FIELD).add(offsetRange);
}
} else if (scope instanceof PropertyHookScope) {
getRanges(folds, TYPE_PROPERTY_HOOK).add(offsetRange);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
*/
package org.netbeans.modules.php.editor.csl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.netbeans.api.editor.fold.FoldType;
import org.netbeans.api.editor.mimelookup.MimeRegistration;
import org.netbeans.modules.php.api.util.FileUtils;
Expand All @@ -32,22 +32,22 @@
@MimeRegistration(mimeType = FileUtils.PHP_MIME_TYPE, service = FoldTypeProvider.class, position = 1000)
public class PHPFoldingProvider implements FoldTypeProvider {

private static final Collection<FoldType> TYPES = new ArrayList<>(9);

static {
TYPES.add(FoldingScanner.TYPE_CLASS);
TYPES.add(FoldingScanner.TYPE_FUNCTION);
TYPES.add(FoldingScanner.TYPE_CODE_BLOCKS);
TYPES.add(FoldingScanner.TYPE_COMMENT);
TYPES.add(FoldingScanner.TYPE_PHPDOC);
TYPES.add(FoldingScanner.TYPE_ARRAY);
TYPES.add(FoldingScanner.TYPE_USE);
TYPES.add(FoldingScanner.TYPE_PHPTAG);
TYPES.add(FoldingScanner.TYPE_ATTRIBUTES);
}
private static final Collection<FoldType> TYPES = List.of(
FoldingScanner.TYPE_CLASS,
FoldingScanner.TYPE_FUNCTION,
FoldingScanner.TYPE_HOOKED_FIELD,
FoldingScanner.TYPE_PROPERTY_HOOK,
FoldingScanner.TYPE_CODE_BLOCKS,
FoldingScanner.TYPE_COMMENT,
FoldingScanner.TYPE_PHPDOC,
FoldingScanner.TYPE_ARRAY,
FoldingScanner.TYPE_USE,
FoldingScanner.TYPE_PHPTAG,
FoldingScanner.TYPE_ATTRIBUTES
);

@Override
public Collection getValues(Class type) {
public Collection<FoldType> getValues(Class type) {
return type == FoldType.class ? TYPES : null;
}

Expand Down
156 changes: 156 additions & 0 deletions php/php.editor/test/unit/data/testfiles/propertyHooks.php.folds
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<?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 PropertyHooksClass {
| public const string CONSTANT = "property hook";
| // valid properties
+ public $valid01 {
+ get {
| return $this->prop1;
- }
+ set {
| $this->valid01 = $value;
- }
- }
+ public int $valid02 = 1 {
+ get {
| echo __METHOD__, "\n";
| return $this->valid02;
- }
+ set($value){
| $this->valid02 = $value;
- }
- }
+ public $valid03 = "string" {
+ get {
| return $this->valid03;
- }
+ set {}
- }
+ public string $valid04 = self::CONSTANT {
+ get => $this->valid04;
+ set {}
- }
+ public array $valid05 = [] {
+ get => $this->valid05;
+ set => $this->valid05 = $value;
- }
+ public private(set) string $valid06 = self::CONSTANT {
+ get {
| return $this->valid06 . "test";
- }
+ set {}
- }
+ public $valid07 { // virtual
+ get => $this->test();
+ set => $this->test() . $value;
- }
+ public string $valid08 {
+ set(string|array $param) {
| $this->valid08 = is_array($param) ? join(', ', $param) : $param;
- }
- }
+ public $valid09 {
+ #[Attr1] get {}
+ #[Attr2] set {}
- }
+ public $valid10 = 100 {
+ get {
| yield 1;
| yield $this->valid10;
| yield 3;
- }
- }
+ public $valid11 { // virtual
+ get {
| yield 1;
| yield 2;
| yield 3;
- }
- }
+ public $valid12 {
+ set(#[SensitiveParameter] $value) {
| throw new Exception('test');
- }
- }
+ public $valid13 {
+ final get { return 100; }
- }
+ final public $valid14 {
+ final get => $this->valid14;
- }
+ public $valid15 {
+ &get => $this->valid15;
- }
+ public $closure {
+ get {
| return function () {
| return $this->closure;
| };
- }
- }
+ public $arrowFunction {
+ get {
| return fn() => $this->arrowFunction;
- }
- }
+ private $propertyConst {
+ get => __PROPERTY__;
- }
+ var $var { get => 100; }
|
| // invalid properties
+ public $invalidEmptyHook {} // error but parser allows
+ private $invalidPrivateFinal { final get; } // error but parser allows
+ private $invalidPublic01 {
| public get; // error but parser allows
- }
+ public $invalidStatic01 {
+ static get {} // error but parser allows
- }
+ public static $invalidStatic02 { // error but parser allows
| get;
| set;
- }
+ public $invalidGetParam {
+ get() { // error but parser allows
| var_dump($value);
- }
- }
+ public readonly int $invalidReadonly { get{} set{} } // error but parser allows
+ public $invalidSetRef {
+ set(&$value) {} // error but parser allows
- }
+ public $invalidVariadic {
+ set(...$value) {} // error but parser allows
- }
+ public $invalidUnknownHook {
+ unknown {} // error
- }
- }

+ class Child extends PropertyHooksClass {
+ public $prop = 100 {
+ get => parent::$prop::get();
+ set {
| parent::$prop::set($value);
- }
- }
- }

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?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.
- */
+ abstract class AbstractClass {
| // valid properties
+ public abstract $valid01 { // OK
| get;
| set;
- }
+ public abstract $valid02 { // OK
| get;
+ set {
| echo __METHOD__ . PHP_EOL;
- }
- }
+ public abstract $valid03 { // OK
+ get {
| echo __METHOD__ . PHP_EOL;
- }
| set;
- }
+ protected abstract int $valid04 { get; set; } // OK
|
| // invalid properties
+ public abstract $invalid01 { // error
+ get{}
+ set{}
- }
+ private abstract int $invalid02 { get; set; } // error
| abstract public $invalid03; // error
- }

Loading

0 comments on commit 8cff930

Please sign in to comment.