Skip to content

Commit ce14c99

Browse files
committed
PHP 8.4 Support: Asymmetric Visibility v2 (Part 4)
- apache#8035 - https://wiki.php.net/rfc#php_84 - https://wiki.php.net/rfc/asymmetric-visibility-v2 - Fix Code Completion - Fix/Add unit tests Note: CC does not work correctly on the following caret position because set visibility keywords contain a brace. ```php class Example { public private(se^ // ^: caret } ```
1 parent ca1f310 commit ce14c99

File tree

234 files changed

+2553
-63
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

234 files changed

+2553
-63
lines changed

php/php.editor/src/org/netbeans/modules/php/editor/completion/CompletionContextFinder.java

Lines changed: 82 additions & 59 deletions
Large diffs are not rendered by default.

php/php.editor/src/org/netbeans/modules/php/editor/completion/PHPCodeCompletion.java

Lines changed: 102 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@
123123
import org.netbeans.modules.php.editor.parser.astnodes.ClassInstanceCreation;
124124
import org.netbeans.modules.php.editor.parser.astnodes.EnumDeclaration;
125125
import org.netbeans.modules.php.editor.parser.astnodes.Expression;
126+
import org.netbeans.modules.php.editor.parser.astnodes.InterfaceDeclaration;
126127
import org.netbeans.modules.php.editor.parser.astnodes.NamespaceName;
127128
import org.netbeans.modules.php.editor.parser.astnodes.TraitDeclaration;
128129
import org.netbeans.modules.php.editor.parser.astnodes.TypeDeclaration;
@@ -168,6 +169,12 @@ private static enum UseType {
168169
PHP_KEYWORDS.put("public", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
169170
PHP_KEYWORDS.put("private", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
170171
PHP_KEYWORDS.put("protected", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
172+
PHP_KEYWORDS.put("public(set)", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
173+
PHP_KEYWORDS.put("private(set)", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
174+
PHP_KEYWORDS.put("protected(set)", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
175+
PHP_KEYWORDS.put("public protected(set)", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
176+
PHP_KEYWORDS.put("public private(set)", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
177+
PHP_KEYWORDS.put("protected private(set)", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
171178
PHP_KEYWORDS.put("abstract", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
172179
PHP_KEYWORDS.put("readonly", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
173180
PHP_KEYWORDS.put("clone", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
@@ -256,6 +263,16 @@ private static enum UseType {
256263
"protected", // NOI18N
257264
"private" // NOI18N
258265
);
266+
private static final List<String> PHP_SET_VISIBILITY_KEYWORDS = Arrays.asList(
267+
"public(set)", // NOI18N
268+
"protected(set)", // NOI18N
269+
"private(set)" // NOI18N
270+
);
271+
private static final List<String> PHP_ASYMMETRIC_VISIBILITY_KEYWORDS = Arrays.asList(
272+
"public private(set)", // NOI18N
273+
"public protected(set)", // NOI18N
274+
"protected private(set)" // NOI18N
275+
);
259276
private static final Collection<Character> AUTOPOPUP_STOP_CHARS = new TreeSet<>(
260277
Arrays.asList('=', ';', '+', '-', '*', '/',
261278
'%', '(', ')', '[', ']', '{', '}', '?'));
@@ -265,9 +282,11 @@ private static enum UseType {
265282
Arrays.asList(new String[]{"__construct", "__destruct", "__call", "__callStatic",
266283
"__clone", "__get", "__invoke", "__isset", "__set", "__set_state",
267284
"__sleep", "__toString", "__unset", "__wakeup"}); //NOI18N
268-
private static final List<String> CLASS_CONTEXT_KEYWORD_PROPOSAL =
269-
Arrays.asList(new String[]{"abstract", "const", "function", "private", "final",
270-
"protected", "public", "static", "var", "readonly"}); //NOI18N
285+
private static final List<String> CLASS_CONTEXT_KEYWORD_PROPOSAL = Arrays.asList(
286+
"abstract", "const", "function", "final", // NOI18N
287+
"private", "protected", "public", // NOI18N
288+
"static", "var", "readonly" // NOI18N
289+
);
271290
private static final List<String> INTERFACE_CONTEXT_KEYWORD_PROPOSAL =
272291
Arrays.asList(new String[]{"const", "function", "public", "static"}); //NOI18N
273292
private static final List<String> INHERITANCE_KEYWORDS =
@@ -557,6 +576,7 @@ public CodeCompletionResult complete(CodeCompletionContext completionContext) {
557576
break;
558577
case VISIBILITY_MODIFIER_OR_TYPE_NAME: // no break
559578
autoCompleteKeywords(completionResult, request, PHP_VISIBILITY_KEYWORDS);
579+
autoCompleteKeywords(completionResult, request, PHP_SET_VISIBILITY_KEYWORDS);
560580
autoCompleteKeywords(completionResult, request, Arrays.asList("readonly")); // NOI18N
561581
case TYPE_NAME:
562582
autoCompleteNamespaces(completionResult, request);
@@ -1301,7 +1321,30 @@ private void autoCompleteInClassContext(
13011321
TokenSequence<PHPTokenId> tokenSequence = th.tokenSequence(PHPTokenId.language());
13021322
assert tokenSequence != null;
13031323

1324+
boolean foundFunction = false;
1325+
boolean foundConst = false;
1326+
tokenSequence.move(caretOffset);
1327+
while (tokenSequence.moveNext()) {
1328+
Token<PHPTokenId> token = tokenSequence.token();
1329+
if (token.id() == PHPTokenId.PHP_LINE_COMMENT
1330+
|| TokenUtilities.indexOf(token.text(), '\n') != -1) {
1331+
break;
1332+
}
1333+
if (token.id() == PHPTokenId.PHP_FUNCTION) {
1334+
foundFunction = true;
1335+
break;
1336+
}
1337+
if (token.id() == PHPTokenId.PHP_CONST) {
1338+
foundConst = true;
1339+
break;
1340+
}
1341+
}
1342+
13041343
autoCompleteKeywords(completionResult, request, CLASS_CONTEXT_KEYWORD_PROPOSAL);
1344+
if (!foundConst && !foundFunction) {
1345+
autoCompleteKeywords(completionResult, request, PHP_SET_VISIBILITY_KEYWORDS);
1346+
autoCompleteKeywords(completionResult, request, PHP_ASYMMETRIC_VISIBILITY_KEYWORDS);
1347+
}
13051348
if (offerMagicAndInherited(tokenSequence, caretOffset, th)) {
13061349
EnclosingClass enclosingClass = findEnclosingClass(info, lexerToASTOffset(info, caretOffset));
13071350
if (enclosingClass != null) {
@@ -1387,15 +1430,24 @@ private void autoCompleteFieldType(ParserResult info, int caretOffset, final PHP
13871430
TokenSequence<PHPTokenId> tokenSequence = th.tokenSequence(PHPTokenId.language());
13881431
assert tokenSequence != null;
13891432
tokenSequence.move(caretOffset);
1433+
boolean addFinalKeyword = false;
13901434
boolean addStaticKeyword = false;
13911435
boolean addReadonlyKeyword = false;
13921436
boolean addVisibilityKeyword = false;
1437+
boolean addSetVisibilityKeyword = false;
13931438
if (!(!tokenSequence.moveNext() && !tokenSequence.movePrevious())) {
13941439
Token<PHPTokenId> token = tokenSequence.token();
13951440
int tokenIdOffset = tokenSequence.token().offset(th);
1441+
addFinalKeyword = !CompletionContextFinder.lineContainsAny(token, caretOffset - tokenIdOffset, tokenSequence, Arrays.asList(
1442+
PHPTokenId.PHP_FINAL,
1443+
PHPTokenId.PHP_OPERATOR // "|"
1444+
));
13961445
addStaticKeyword = !CompletionContextFinder.lineContainsAny(token, caretOffset - tokenIdOffset, tokenSequence, Arrays.asList(
13971446
PHPTokenId.PHP_STATIC,
1398-
PHPTokenId.PHP_READONLY,
1447+
PHPTokenId.PHP_READONLY, // cannot use with readonly
1448+
PHPTokenId.PHP_PUBLIC_SET, // cannot use with set visibility
1449+
PHPTokenId.PHP_PRIVATE_SET,
1450+
PHPTokenId.PHP_PROTECTED_SET,
13991451
PHPTokenId.PHP_OPERATOR // "|"
14001452
));
14011453
addReadonlyKeyword = !CompletionContextFinder.lineContainsAny(token, caretOffset - tokenIdOffset, tokenSequence, Arrays.asList(
@@ -1408,6 +1460,16 @@ private void autoCompleteFieldType(ParserResult info, int caretOffset, final PHP
14081460
PHPTokenId.PHP_PROTECTED,
14091461
PHPTokenId.PHP_OPERATOR // "|"
14101462
));
1463+
addSetVisibilityKeyword = !CompletionContextFinder.lineContainsAny(token, caretOffset - tokenIdOffset, tokenSequence, Arrays.asList(
1464+
PHPTokenId.PHP_PUBLIC_SET,
1465+
PHPTokenId.PHP_PRIVATE_SET,
1466+
PHPTokenId.PHP_PROTECTED_SET,
1467+
PHPTokenId.PHP_STATIC, // cannot use with static
1468+
PHPTokenId.PHP_OPERATOR // "|"
1469+
));
1470+
}
1471+
if (addFinalKeyword) {
1472+
keywords.add("final"); // NOI18N
14111473
}
14121474
if (addStaticKeyword) {
14131475
keywords.add("static"); // NOI18N
@@ -1418,6 +1480,12 @@ private void autoCompleteFieldType(ParserResult info, int caretOffset, final PHP
14181480
if (addVisibilityKeyword) {
14191481
keywords.addAll(PHP_VISIBILITY_KEYWORDS);
14201482
}
1483+
if (addSetVisibilityKeyword) {
1484+
keywords.addAll(PHP_SET_VISIBILITY_KEYWORDS);
1485+
}
1486+
if (addVisibilityKeyword && addSetVisibilityKeyword) {
1487+
keywords.addAll(PHP_ASYMMETRIC_VISIBILITY_KEYWORDS);
1488+
}
14211489
}
14221490
if (isNullableType) {
14231491
// ?false, ?true is OK since PHP 8.2
@@ -1439,6 +1507,10 @@ private boolean offerMagicAndInherited(TokenSequence<PHPTokenId> tokenSequence,
14391507
PHPTokenId.PHP_PRIVATE,
14401508
PHPTokenId.PHP_PUBLIC,
14411509
PHPTokenId.PHP_PROTECTED,
1510+
PHPTokenId.PHP_PRIVATE_SET,
1511+
PHPTokenId.PHP_PUBLIC_SET,
1512+
PHPTokenId.PHP_PROTECTED_SET,
1513+
PHPTokenId.PHP_FINAL,
14421514
PHPTokenId.PHP_ABSTRACT,
14431515
PHPTokenId.PHP_VAR,
14441516
PHPTokenId.PHP_STATIC,
@@ -2038,6 +2110,11 @@ private static boolean isInType(CompletionRequest request) {
20382110
return findEnclosingType(request.info, lexerToASTOffset(request.result, request.anchor)) != null;
20392111
}
20402112

2113+
private static boolean isInInterface(CompletionRequest request) {
2114+
EnclosingType enclosingType = findEnclosingType(request.info, lexerToASTOffset(request.result, request.anchor));
2115+
return enclosingType != null && enclosingType.isInterface();
2116+
}
2117+
20412118
@CheckForNull
20422119
private static NamespaceName findNamespaceName(ParserResult info, int offset) {
20432120
List<ASTNode> nodes = NavUtils.underCaret(info, offset);
@@ -2182,6 +2259,10 @@ private void autoCompleteExpression(final PHPCompletionResult completionResult,
21822259
autoCompleteNamespaces(completionResult, request);
21832260
List<String> defaultKeywords = new ArrayList<>(PHP_KEYWORDS.keySet());
21842261
defaultKeywords.remove("default =>"); // NOI18N
2262+
defaultKeywords.removeAll(PHP_ASYMMETRIC_VISIBILITY_KEYWORDS);
2263+
if (isInInterface(request)) {
2264+
defaultKeywords.removeAll(PHP_SET_VISIBILITY_KEYWORDS);
2265+
}
21852266
autoCompleteExpression(completionResult, request, defaultKeywords);
21862267
}
21872268

@@ -2801,6 +2882,8 @@ private interface EnclosingType {
28012882

28022883
boolean isEnumDeclaration();
28032884

2885+
boolean isInterface();
2886+
28042887
String extractTypeName();
28052888

28062889
//~ Factories
@@ -2822,6 +2905,11 @@ public boolean isEnumDeclaration() {
28222905
return typeDeclaration instanceof EnumDeclaration;
28232906
}
28242907

2908+
@Override
2909+
public boolean isInterface() {
2910+
return typeDeclaration instanceof InterfaceDeclaration;
2911+
}
2912+
28252913
@Override
28262914
public String extractTypeName() {
28272915
return CodeUtils.extractTypeName(typeDeclaration);
@@ -2846,6 +2934,11 @@ public boolean isEnumDeclaration() {
28462934
return tokenId == PHPTokenId.PHP_ENUM;
28472935
}
28482936

2937+
@Override
2938+
public boolean isInterface() {
2939+
return tokenId == PHPTokenId.PHP_INTERFACE;
2940+
}
2941+
28492942
@Override
28502943
public String extractTypeName() {
28512944
return typeName;
@@ -2871,6 +2964,11 @@ public boolean isEnumDeclaration() {
28712964
return false;
28722965
}
28732966

2967+
@Override
2968+
public boolean isInterface() {
2969+
return false;
2970+
}
2971+
28742972
@Override
28752973
public String extractTypeName() {
28762974
return CodeUtils.extractClassName(classInstanceCreation);

php/php.editor/test/unit/data/testfiles/completion/lib/_base/insideClass.php.testInsideClass_1.completion

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ priv|ate $fld = 0;
33
(QueryType=COMPLETION, prefixSearch=true, caseSensitive=true)
44
------------------------------------
55
KEYWORD private null
6+
KEYWORD private(set) null

php/php.editor/test/unit/data/testfiles/completion/lib/_base/insideClass3.php.testInsideClass_10.completion

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ privat|e $afterDocComment = 3;
33
(QueryType=COMPLETION, prefixSearch=true, caseSensitive=true)
44
------------------------------------
55
KEYWORD private null
6+
KEYWORD private(set) null

php/php.editor/test/unit/data/testfiles/completion/lib/_base/issue153707.php.testIssue153707_01.completion

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,11 @@ KEYWORD new null
206206
KEYWORD or null
207207
KEYWORD print ''; Language Construct
208208
KEYWORD private null
209+
KEYWORD private(set) null
209210
KEYWORD protected null
211+
KEYWORD protected(set) null
210212
KEYWORD public null
213+
KEYWORD public(set) null
211214
KEYWORD readonly null
212215
KEYWORD require ''; Language Construct
213216
KEYWORD require_once ''; Language Construct

php/php.editor/test/unit/data/testfiles/completion/lib/_base/issue153867.php.testIssue153867.completion

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,11 @@ KEYWORD new null
197197
KEYWORD or null
198198
KEYWORD print ''; Language Construct
199199
KEYWORD private null
200+
KEYWORD private(set) null
200201
KEYWORD protected null
202+
KEYWORD protected(set) null
201203
KEYWORD public null
204+
KEYWORD public(set) null
202205
KEYWORD readonly null
203206
KEYWORD require ''; Language Construct
204207
KEYWORD require_once ''; Language Construct

php/php.editor/test/unit/data/testfiles/completion/lib/nb1855/nb1855.php.testCompleteAccessPrefixInTrait_01.completion

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,11 @@ KEYWORD new null
8686
KEYWORD or null
8787
KEYWORD print ''; Language Construct
8888
KEYWORD private null
89+
KEYWORD private(set) null
8990
KEYWORD protected null
91+
KEYWORD protected(set) null
9092
KEYWORD public null
93+
KEYWORD public(set) null
9194
KEYWORD readonly null
9295
KEYWORD require ''; Language Construct
9396
KEYWORD require_once ''; Language Construct

php/php.editor/test/unit/data/testfiles/completion/lib/nb1855/nb1855.php.testCompleteAccessPrefixInTrait_03.completion

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ VARIABLE ? $protectedTraitStaticPropert [PROTECTE Trait1855
77
VARIABLE ? protectedTraitProperty [PROTECTE Trait1855
88
------------------------------------
99
KEYWORD protected null
10+
KEYWORD protected(set) null

php/php.editor/test/unit/data/testfiles/completion/lib/nb1855/nb1855.php.testCompleteAccessPrefix_01.completion

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,11 @@ KEYWORD new null
112112
KEYWORD or null
113113
KEYWORD print ''; Language Construct
114114
KEYWORD private null
115+
KEYWORD private(set) null
115116
KEYWORD protected null
117+
KEYWORD protected(set) null
116118
KEYWORD public null
119+
KEYWORD public(set) null
117120
KEYWORD readonly null
118121
KEYWORD require ''; Language Construct
119122
KEYWORD require_once ''; Language Construct

php/php.editor/test/unit/data/testfiles/completion/lib/nb1855/nb1855.php.testCompleteAccessPrefix_03.completion

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ CONSTANT PRIVATE_CONSTANT "private cons [PRIVATE] Class1855
1313
------------------------------------
1414
KEYWORD print ''; Language Construct
1515
KEYWORD private null
16+
KEYWORD private(set) null

php/php.editor/test/unit/data/testfiles/completion/lib/netbeans68version/paramdecltypes/paramdecltypes.php.testParamDeclTypes.completion

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,11 @@ KEYWORD new null
7474
KEYWORD or null
7575
KEYWORD print ''; Language Construct
7676
KEYWORD private null
77+
KEYWORD private(set) null
7778
KEYWORD protected null
79+
KEYWORD protected(set) null
7880
KEYWORD public null
81+
KEYWORD public(set) null
7982
KEYWORD readonly null
8083
KEYWORD require ''; Language Construct
8184
KEYWORD require_once ''; Language Construct

php/php.editor/test/unit/data/testfiles/completion/lib/php70/base/anonymousClass01.php.testAnonymousClass01h.completion

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,14 @@ KEYWORD const null
2424
KEYWORD final null
2525
KEYWORD function null
2626
KEYWORD private null
27+
KEYWORD private(set) null
2728
KEYWORD protected null
29+
KEYWORD protected private(set) null
30+
KEYWORD protected(set) null
2831
KEYWORD public null
32+
KEYWORD public private(set) null
33+
KEYWORD public protected(set) null
34+
KEYWORD public(set) null
2935
KEYWORD readonly null
3036
KEYWORD static null
3137
KEYWORD var null

php/php.editor/test/unit/data/testfiles/completion/lib/php70/base/anonymousClass02.php.testAnonymousClass02a.completion

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,11 @@ KEYWORD new null
143143
KEYWORD or null
144144
KEYWORD print ''; Language Construct
145145
KEYWORD private null
146+
KEYWORD private(set) null
146147
KEYWORD protected null
148+
KEYWORD protected(set) null
147149
KEYWORD public null
150+
KEYWORD public(set) null
148151
KEYWORD readonly null
149152
KEYWORD require ''; Language Construct
150153
KEYWORD require_once ''; Language Construct

php/php.editor/test/unit/data/testfiles/completion/lib/php70/base/anonymousClass02.php.testAnonymousClass02d.completion

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,11 @@ KEYWORD new null
143143
KEYWORD or null
144144
KEYWORD print ''; Language Construct
145145
KEYWORD private null
146+
KEYWORD private(set) null
146147
KEYWORD protected null
148+
KEYWORD protected(set) null
147149
KEYWORD public null
150+
KEYWORD public(set) null
148151
KEYWORD readonly null
149152
KEYWORD require ''; Language Construct
150153
KEYWORD require_once ''; Language Construct

php/php.editor/test/unit/data/testfiles/completion/lib/php70/base/anonymousClass02.php.testAnonymousClass02e.completion

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,11 @@ KEYWORD new null
143143
KEYWORD or null
144144
KEYWORD print ''; Language Construct
145145
KEYWORD private null
146+
KEYWORD private(set) null
146147
KEYWORD protected null
148+
KEYWORD protected(set) null
147149
KEYWORD public null
150+
KEYWORD public(set) null
148151
KEYWORD readonly null
149152
KEYWORD require ''; Language Construct
150153
KEYWORD require_once ''; Language Construct

0 commit comments

Comments
 (0)