Skip to content

Commit a2917f5

Browse files
committed
PHP 8.4 Support: new MyClass()->method() without parentheses (Part 2)
- apache#8035 - https://wiki.php.net/rfc#php_84 - https://wiki.php.net/rfc/new_without_parentheses - Fix the formatter - Add `Other` to spaces within parentheses option e.g. `($a + $b);`, `new (trim(' Example '))()->field;` - Add/Fix unit tests
1 parent eda6940 commit a2917f5

27 files changed

+2078
-8
lines changed

php/php.editor/src/org/netbeans/modules/php/editor/indent/CodeStyle.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,10 @@ public boolean spaceWithinAttributeDeclParens() {
486486
return preferences.getBoolean(SPACE_WITHIN_ATTRIBUTE_DECL_PARENS, getDefaultAsBoolean(SPACE_WITHIN_ATTRIBUTE_DECL_PARENS));
487487
}
488488

489+
public boolean spaceWithinOtherParens() {
490+
return preferences.getBoolean(SPACE_WITHIN_OTHER_PARENS, getDefaultAsBoolean(SPACE_WITHIN_OTHER_PARENS));
491+
}
492+
489493
public boolean spaceBeforeComma() {
490494
return preferences.getBoolean(SPACE_BEFORE_COMMA, getDefaultAsBoolean(SPACE_BEFORE_COMMA));
491495
}

php/php.editor/src/org/netbeans/modules/php/editor/indent/FmtOptions.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ public final class FmtOptions {
171171
public static final String SPACE_WITHIN_ARRAY_BRACKETS = "spaceWithinArrayBrackets"; //NOI18N
172172
public static final String SPACE_WITHIN_ATTRIBUTE_BRACKETS = "spaceWithinAttributeBrackets"; //NOI18N
173173
public static final String SPACE_WITHIN_ATTRIBUTE_DECL_PARENS = "spaceWithinAttributeDeclParens"; //NOI18N
174+
public static final String SPACE_WITHIN_OTHER_PARENS = "spaceWithinOtherParens"; //NOI18N
174175
public static final String SPACE_BEFORE_COMMA = "spaceBeforeComma"; //NOI18N
175176
public static final String SPACE_AFTER_COMMA = "spaceAfterComma"; //NOI18N
176177
public static final String SPACE_BEFORE_SEMI = "spaceBeforeSemi"; //NOI18N
@@ -370,6 +371,7 @@ private static void createDefaults() {
370371
{SPACE_WITHIN_ARRAY_BRACKETS, FALSE},
371372
{SPACE_WITHIN_ATTRIBUTE_BRACKETS, FALSE},
372373
{SPACE_WITHIN_ATTRIBUTE_DECL_PARENS, FALSE},
374+
{SPACE_WITHIN_OTHER_PARENS, FALSE},
373375
{SPACE_BEFORE_COMMA, FALSE},
374376
{SPACE_AFTER_COMMA, TRUE},
375377
{SPACE_BEFORE_SEMI, FALSE},

php/php.editor/src/org/netbeans/modules/php/editor/indent/FormatToken.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ public enum Kind {
127127
WHITESPACE_WITHIN_ATTRIBUTE_DECL_PARENS,
128128
WHITESPACE_WITHIN_TYPE_CAST_PARENS,
129129
WHITESPACE_WITHIN_DNF_TYPE_PARENS, // (A&B)|C
130+
WHITESPACE_WITHIN_OTHER_PARENS, // e.g. new (trim(' Example '))()
130131
WHITESPACE_WITHIN_DYNAMIC_NAME_BRACES, // {$example}
131132
WHITESPACE_BEFORE_COMMA,
132133
WHITESPACE_AFTER_COMMA,

php/php.editor/src/org/netbeans/modules/php/editor/indent/FormatVisitor.java

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,13 @@
5858
import org.netbeans.modules.php.editor.parser.astnodes.CatchClause;
5959
import org.netbeans.modules.php.editor.parser.astnodes.ClassDeclaration;
6060
import org.netbeans.modules.php.editor.parser.astnodes.ClassInstanceCreation;
61+
import org.netbeans.modules.php.editor.parser.astnodes.ClassInstanceCreationVariable;
6162
import org.netbeans.modules.php.editor.parser.astnodes.ConditionalExpression;
6263
import org.netbeans.modules.php.editor.parser.astnodes.ConstantDeclaration;
6364
import org.netbeans.modules.php.editor.parser.astnodes.DeclareStatement;
65+
import org.netbeans.modules.php.editor.parser.astnodes.DereferencableVariable;
66+
import org.netbeans.modules.php.editor.parser.astnodes.DereferencedArrayAccess;
67+
import org.netbeans.modules.php.editor.parser.astnodes.Dispatch;
6468
import org.netbeans.modules.php.editor.parser.astnodes.DoStatement;
6569
import org.netbeans.modules.php.editor.parser.astnodes.EnumDeclaration;
6670
import org.netbeans.modules.php.editor.parser.astnodes.Expression;
@@ -89,12 +93,14 @@
8993
import org.netbeans.modules.php.editor.parser.astnodes.NamedArgument;
9094
import org.netbeans.modules.php.editor.parser.astnodes.NamespaceDeclaration;
9195
import org.netbeans.modules.php.editor.parser.astnodes.NullableType;
96+
import org.netbeans.modules.php.editor.parser.astnodes.ParenthesisExpression;
9297
import org.netbeans.modules.php.editor.parser.astnodes.Program;
9398
import org.netbeans.modules.php.editor.parser.astnodes.ReflectionVariable;
9499
import org.netbeans.modules.php.editor.parser.astnodes.ReturnStatement;
95100
import org.netbeans.modules.php.editor.parser.astnodes.SingleFieldDeclaration;
96101
import org.netbeans.modules.php.editor.parser.astnodes.SingleUseStatementPart;
97102
import org.netbeans.modules.php.editor.parser.astnodes.Statement;
103+
import org.netbeans.modules.php.editor.parser.astnodes.StaticDispatch;
98104
import org.netbeans.modules.php.editor.parser.astnodes.StaticFieldAccess;
99105
import org.netbeans.modules.php.editor.parser.astnodes.StaticMethodInvocation;
100106
import org.netbeans.modules.php.editor.parser.astnodes.StaticStatement;
@@ -299,7 +305,7 @@ public void visit(StaticStatement node) {
299305
@Override
300306
public void visit(AnonymousObjectVariable node) {
301307
// (new Test)->method();
302-
super.visit(node);
308+
scan(node.getName());
303309
// avoid adding incorrect space for "within a method call"
304310
// e.g. (new Test)->method(); -> (new Test )->method();
305311
addAllUntilOffset(node.getEndOffset());
@@ -876,7 +882,7 @@ public void visit(ClassInstanceCreation node) {
876882
ts.movePrevious();
877883
scan(node.getBody());
878884
} else {
879-
if (node.ctorParams() != null && node.ctorParams().size() > 0) {
885+
if (node.ctorParams() != null && !node.ctorParams().isEmpty()) {
880886
boolean addIndentation = !(path.get(1) instanceof ReturnStatement
881887
|| path.get(1) instanceof Assignment
882888
|| path.get(1) instanceof ExpressionStatement)
@@ -890,7 +896,10 @@ public void visit(ClassInstanceCreation node) {
890896
}
891897
addAllUntilOffset(node.getEndOffset());
892898
} else {
893-
super.visit(node);
899+
// e.g. new Example(); new $className();
900+
// ctorParams() is empty, so, add tokens until the end offset
901+
// to add WHITESPACE_WITHIN_METHOD_CALL_PARENS
902+
addAllUntilOffset(node.getEndOffset());
894903
}
895904
}
896905
}
@@ -1259,7 +1268,9 @@ public void visit(ExpressionStatement node) {
12591268
if (moveNext() && lastIndex < ts.index()) {
12601269
addFormatToken(formatTokens); // add the first token of the expression and then add the indentation
12611270
Expression expression = node.getExpression();
1262-
boolean addIndent = !(expression instanceof MethodInvocation || expression instanceof StaticMethodInvocation);
1271+
boolean addIndent = !(expression instanceof MethodInvocation
1272+
|| expression instanceof StaticMethodInvocation
1273+
|| isAnonymousClass(expression));
12631274
if (expression instanceof Assignment) {
12641275
// anonymous classes
12651276
Assignment assignment = (Assignment) expression;
@@ -2681,6 +2692,18 @@ public void visit(ReflectionVariable node) {
26812692
ts.movePrevious();
26822693
}
26832694

2695+
@Override
2696+
public void visit(DereferencableVariable node) {
2697+
scan(node.getExpression());
2698+
addAllUntilOffset(node.getEndOffset());
2699+
}
2700+
2701+
@Override
2702+
public void visit(ParenthesisExpression node) {
2703+
scan(node.getExpression());
2704+
addAllUntilOffset(node.getEndOffset());
2705+
}
2706+
26842707
private void processUnionOrIntersectionType(List<Expression> types) {
26852708
assert !types.isEmpty();
26862709
final Expression lastType = types.get(types.size() - 1);
@@ -2896,6 +2919,12 @@ private void addFormatToken(List<FormatToken> tokens) {
28962919
} else if (parent instanceof UnionType) {
28972920
tokens.add(new FormatToken(FormatToken.Kind.TEXT, ts.offset(), ts.token().text().toString()));
28982921
tokens.add(new FormatToken(FormatToken.Kind.WHITESPACE_WITHIN_DNF_TYPE_PARENS, ts.offset() + ts.token().length()));
2922+
} else if (isParenthesisExpression(parent)
2923+
|| parent instanceof DereferencableVariable
2924+
|| isAnonymousObjectVariable(parent)
2925+
) {
2926+
tokens.add(new FormatToken(FormatToken.Kind.TEXT, ts.offset(), ts.token().text().toString()));
2927+
tokens.add(new FormatToken(FormatToken.Kind.WHITESPACE_WITHIN_OTHER_PARENS, ts.offset() + ts.token().length()));
28992928
} else {
29002929
tokens.add(new FormatToken(FormatToken.Kind.TEXT, ts.offset(), ts.token().text().toString()));
29012930
}
@@ -2937,6 +2966,11 @@ private void addFormatToken(List<FormatToken> tokens) {
29372966
} else if (parent instanceof UnionType) {
29382967
tokens.add(new FormatToken(FormatToken.Kind.WHITESPACE_WITHIN_DNF_TYPE_PARENS, ts.offset()));
29392968
tokens.add(new FormatToken(FormatToken.Kind.TEXT, ts.offset(), ts.token().text().toString()));
2969+
} else if (parent instanceof ParenthesisExpression
2970+
|| parent instanceof DereferencableVariable
2971+
|| parent instanceof AnonymousObjectVariable) {
2972+
tokens.add(new FormatToken(FormatToken.Kind.WHITESPACE_WITHIN_OTHER_PARENS, ts.offset()));
2973+
tokens.add(new FormatToken(FormatToken.Kind.TEXT, ts.offset(), ts.token().text().toString()));
29402974
} else {
29412975
tokens.add(new FormatToken(FormatToken.Kind.TEXT, ts.offset(), ts.token().text().toString()));
29422976
}
@@ -3652,11 +3686,50 @@ private static boolean isCloseParen(Token<? extends PHPTokenId> token) {
36523686
return TokenUtilities.textEquals(")", token.text()); // NOI18N
36533687
}
36543688

3689+
private static boolean isParenthesisExpression(ASTNode astNode) {
3690+
ASTNode node = astNode;
3691+
if (node instanceof ExpressionStatement) {
3692+
// ($example == 1);
3693+
node = ((ExpressionStatement) node).getExpression();
3694+
}
3695+
return node instanceof ParenthesisExpression;
3696+
}
3697+
3698+
private static boolean isAnonymousObjectVariable(ASTNode astNode) {
3699+
ASTNode node = astNode;
3700+
if (node instanceof ExpressionStatement) {
3701+
// (new $class());
3702+
node = ((ExpressionStatement) node).getExpression();
3703+
if (node instanceof DereferencedArrayAccess) {
3704+
// (new $class())['key'];
3705+
node = ((DereferencedArrayAccess) node).getMember();
3706+
}
3707+
}
3708+
return node instanceof AnonymousObjectVariable;
3709+
}
3710+
36553711
private static boolean isAnonymousClass(ASTNode astNode) {
36563712
ASTNode node = astNode;
36573713
if (astNode instanceof NamedArgument) {
36583714
node = ((NamedArgument) astNode).getExpression();
36593715
}
3716+
3717+
// new class(){}['key'], new class(){}->method()
3718+
while (node instanceof Dispatch
3719+
|| node instanceof StaticDispatch
3720+
|| node instanceof ClassInstanceCreationVariable
3721+
|| node instanceof FunctionInvocation) {
3722+
if (node instanceof Dispatch) {
3723+
node = ((Dispatch) node).getDispatcher();
3724+
} else if (node instanceof StaticDispatch) {
3725+
node = ((StaticDispatch) node).getDispatcher();
3726+
} else if (node instanceof ClassInstanceCreationVariable) {
3727+
node = ((ClassInstanceCreationVariable) node).getName();
3728+
} else if (node instanceof FunctionInvocation) {
3729+
// $c = new class{}();
3730+
node = ((FunctionInvocation) node).getFunctionName().getName();
3731+
}
3732+
}
36603733
return node instanceof ClassInstanceCreation && ((ClassInstanceCreation) node).isAnonymous();
36613734
}
36623735

php/php.editor/src/org/netbeans/modules/php/editor/indent/TokenFormatter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ protected static class DocumentOptions {
138138
public boolean spaceWithinAttributeBrackets;
139139
public boolean spaceWithinAttributeDeclParens;
140140
public boolean spaceWithinTypeCastParens;
141+
public boolean spaceWithinOtherParens;
141142
public boolean spaceBeforeComma;
142143
public boolean spaceAfterComma;
143144
public boolean spaceBeforeSemi;
@@ -307,6 +308,7 @@ public DocumentOptions(BaseDocument doc) {
307308
spaceWithinAttributeBrackets = codeStyle.spaceWithinAttributeBrackets();
308309
spaceWithinAttributeDeclParens = codeStyle.spaceWithinAttributeDeclParens();
309310
spaceWithinTypeCastParens = codeStyle.spaceWithinTypeCastParens();
311+
spaceWithinOtherParens = codeStyle.spaceWithinOtherParens();
310312

311313
spaceBeforeComma = codeStyle.spaceBeforeComma();
312314
spaceAfterComma = codeStyle.spaceAfterComma();
@@ -1617,6 +1619,9 @@ && countOfNewLines(formatTokens.get(index + 1).getOldText()) > 0) {
16171619
// change here if we add the option for it
16181620
countSpaces = 0;
16191621
break;
1622+
case WHITESPACE_WITHIN_OTHER_PARENS:
1623+
countSpaces = docOptions.spaceWithinOtherParens ? 1 : 0;
1624+
break;
16201625
case WHITESPACE_WITHIN_DYNAMIC_NAME_BRACES:
16211626
// change here if we add the option for it
16221627
countSpaces = 0;

php/php.editor/src/org/netbeans/modules/php/editor/indent/ui/Bundle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ LBL_spaceWithinBraces=Braces
128128
LBL_spaceWithinArrayBrackets=Array Brackets
129129
LBL_spaceWithinAttributeBrackets=Attribute Brackets
130130
LBL_spaceWithinAttributeDeclParens=Attribute Declaration
131+
LBL_spaceWithinOtherParens=Other
131132

132133
LBL_Other=Other
133134
LBL_spaceBeforeComma=Before Comma

php/php.editor/src/org/netbeans/modules/php/editor/indent/ui/FmtSpaces.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,8 @@ private DefaultTreeModel createModel() {
309309
new Item(SPACE_WITHIN_TYPE_CAST_PARENS),
310310
new Item(SPACE_WITHIN_ARRAY_BRACKETS),
311311
new Item(SPACE_WITHIN_ATTRIBUTE_BRACKETS),
312-
new Item(SPACE_WITHIN_ATTRIBUTE_DECL_PARENS)
312+
new Item(SPACE_WITHIN_ATTRIBUTE_DECL_PARENS),
313+
new Item(SPACE_WITHIN_OTHER_PARENS)
313314
),
314315

315316

php/php.editor/src/org/netbeans/modules/php/editor/indent/ui/Spaces.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,5 @@ function namedArguments($a, $b) {}
155155
"loooooong condition" => 2,
156156
default => 0,
157157
};
158+
159+
new (trim(' Example '))()->field;

0 commit comments

Comments
 (0)