Skip to content

Commit

Permalink
[NETBEANS-1861] Recognize @method static for documenting static methods
Browse files Browse the repository at this point in the history
Example:
```
/**
 * Example class.
 *
 * @method testVoid(Test $test)  test comment
 * @method int testType(Test $test)  test comment
 * @method static staticTestVoid(Test $test) test comment
 * @method static int staticTestType(Test $param1, $param2)  test comment
 * @method static ?int staticTestNullable(?string $param, int $param2) test comment
 * @method static ?Example getDefault() Description
 */
class Example {

    public function test() {
        self::staticTestVoid($test);
        self::staticTestType($param1, $param2);
        self::staticTestNullable($param1, $param2);
        self::getDefault();
    }

}
```

- Fix DeclarationFinderImpl and PHPDocCommentParser
- Fix MarkOccurences and GoToDeclaration features
- Add unit tests for CC, MarkOccurences, GoToDeclaration, Navigator, CommentExtractor, ASTPHP5Parser, and PHPDocCommentParser
  • Loading branch information
junichi11 committed Aug 30, 2019
1 parent fdf9c5f commit fbeb749
Show file tree
Hide file tree
Showing 64 changed files with 1,589 additions and 31 deletions.
2 changes: 1 addition & 1 deletion php/php.editor/nbproject/project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ build.compiler=extJavac
nbjavac.ignore.missing.enclosing=**/CUP$ASTPHP5Parser$actions.class
javac.compilerargs=-J-Xmx512m
nbm.needs.restart=true
spec.version.base=1.83.0
spec.version.base=1.84.0
release.external/predefined_vars-1.0.zip=docs/predefined_vars.zip
sigtest.gen.fail.on.error=false

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ public void run(ResultIterator resultIterator) throws Exception {
private static class ReferenceSpanFinder {

private static final int RECURSION_LIMIT = 100;
// e.g. @var VarType $variable
// e.g. @var VarType $variable
private static final Pattern INLINE_PHP_VAR_COMMENT_PATTERN = Pattern.compile("^[ \t]*@var[ \t]+.+[ \t]+\\$.+$"); // NOI18N
private static final Logger LOGGER = Logger.getLogger(DeclarationFinderImpl.class.getName());

Expand Down Expand Up @@ -317,19 +317,20 @@ public OffsetRange getReferenceSpan(TokenSequence<PHPTokenId> ts, final int care
if (node != null) {
return node.getRange().containsInclusive(caretOffset) ? node.getRange() : OffsetRange.NONE;
}
if (typeTag instanceof PHPDocMethodTag) {
OffsetRange magicMethodRange = getMagicMethodRange((PHPDocMethodTag) typeTag, caretOffset);
if (magicMethodRange != OffsetRange.NONE) {
return magicMethodRange;
}
}
}
} else {
List<PHPDocTag> tags = docBlock.getTags();
for (PHPDocTag phpDocTag : tags) {
if (phpDocTag instanceof PHPDocMethodTag) {
PHPDocMethodTag methodTag = (PHPDocMethodTag) phpDocTag;
MagicMethodDeclarationInfo methodInfo = MagicMethodDeclarationInfo.create(methodTag);
if (methodInfo != null) {
if (methodInfo.getRange().containsInclusive(caretOffset)) {
return methodInfo.getRange();
} else if (methodInfo.getTypeRange().containsInclusive(caretOffset)) {
return methodInfo.getTypeRange();
}
OffsetRange magicMethodRange = getMagicMethodRange((PHPDocMethodTag) phpDocTag, caretOffset);
if (magicMethodRange != OffsetRange.NONE) {
return magicMethodRange;
}
}
}
Expand All @@ -356,6 +357,19 @@ public OffsetRange getReferenceSpan(TokenSequence<PHPTokenId> ts, final int care
return OffsetRange.NONE;
}

private OffsetRange getMagicMethodRange(PHPDocMethodTag methodTag, final int caretOffset) {
OffsetRange offsetRange = OffsetRange.NONE;
MagicMethodDeclarationInfo methodInfo = MagicMethodDeclarationInfo.create(methodTag);
if (methodInfo != null) {
if (methodInfo.getRange().containsInclusive(caretOffset)) {
offsetRange = methodInfo.getRange();
} else if (methodInfo.getTypeRange().containsInclusive(caretOffset)) {
offsetRange = methodInfo.getTypeRange();
}
}
return offsetRange;
}

@CheckForNull
private OffsetRange getVarCommentOffsetRange(TokenSequence<PHPTokenId> ts, String text, int caretOffset) {
final String dollaredVar = "@var"; // NOI18N
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import org.netbeans.modules.php.editor.model.VariableScope;
import org.netbeans.modules.php.editor.model.nodes.ASTNodeInfo;
import org.netbeans.modules.php.editor.model.nodes.ASTNodeInfo.Kind;
import org.netbeans.modules.php.editor.model.nodes.ASTNodeInfoUtils;
import org.netbeans.modules.php.editor.model.nodes.ClassConstantDeclarationInfo;
import org.netbeans.modules.php.editor.model.nodes.ClassDeclarationInfo;
import org.netbeans.modules.php.editor.model.nodes.ConstantDeclarationInfo;
Expand Down Expand Up @@ -100,6 +101,7 @@
import org.netbeans.modules.php.editor.parser.astnodes.MethodDeclaration;
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.PHPDocMethodTag;
import org.netbeans.modules.php.editor.parser.astnodes.PHPDocTypeTag;
import org.netbeans.modules.php.editor.parser.astnodes.Scalar;
import org.netbeans.modules.php.editor.parser.astnodes.SingleFieldDeclaration;
Expand Down Expand Up @@ -460,7 +462,7 @@ void prepare(MethodDeclaration methodDeclaration, MethodScope scope) {

void prepare(final MagicMethodDeclarationInfo node, MethodScope scope) {
if (canBePrepared(node.getOriginalNode(), scope)) {
if (node.getKind().equals(Kind.METHOD)) {
if (ASTNodeInfoUtils.isMethod(node.getKind())) {
magicMethodDeclarations.put(node, scope);
}
}
Expand Down Expand Up @@ -998,6 +1000,7 @@ private void buildStaticMethods(final Index index, FileScopeImpl fileScope, fina
buildMethodInvocations(elementInfo, fileScope, Accuracy.UNIQUE, occurences);
}
buildMethodDeclarations(elementInfo, fileScope, occurences);
buildMagicMethodDeclarations(elementInfo, fileScope, cachedOccurences);
}
}
}
Expand Down Expand Up @@ -2461,7 +2464,8 @@ public QualifiedName getTypeQualifiedName() {
} else {
if (getScope().getInScope() instanceof TypeScope) {
if (originalNode instanceof MethodDeclaration
|| originalNode instanceof SingleFieldDeclaration) {
|| originalNode instanceof SingleFieldDeclaration
|| originalNode instanceof PHPDocMethodTag) { // NETBEANS-1861
return ((TypeScope) getScope().getInScope()).getFullyQualifiedName();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* 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.
*/
package org.netbeans.modules.php.editor.model.nodes;

import org.netbeans.modules.php.editor.model.nodes.ASTNodeInfo.Kind;
import static org.netbeans.modules.php.editor.model.nodes.ASTNodeInfo.Kind.METHOD;
import static org.netbeans.modules.php.editor.model.nodes.ASTNodeInfo.Kind.STATIC_METHOD;

public final class ASTNodeInfoUtils {

private ASTNodeInfoUtils() {
}

/**
* Check whether the kind is METHOD or STATIC_METHOD.
*
* @param kind the kind
* @return {@code true} if this is METHOD or STATIC_METHOD, {@code false}
* otherwise
*/
public static boolean isMethod(Kind kind) {
return kind == METHOD || kind == STATIC_METHOD;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.netbeans.modules.php.editor.model.nodes;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -51,10 +52,21 @@ public class MagicMethodDeclarationInfo extends ASTNodeInfo<PHPDocMethodTag> {
private String methodName;
private int offset;
private int typeOffset;
private final boolean isStatic;

MagicMethodDeclarationInfo(PHPDocMethodTag node) {
super(node);
// @method int get(Type $object) message
// @method static int staticGet(Type $object) message
String[] parts = node.getValue().trim().split("\\s+", 3); //NOI18N
isStatic = parts.length >= 1 && parts[0].equals("static"); // NOI18N NETBEANS-1861
// the method is already checked whether it is static when PHPDocMethodTag is created
// So, they should be the same result
// see: PHPDocCommentParser.createTag()
assert isStatic == node.isStatic() : "PHPDocMethodTag static: " + node.isStatic(); // NOI18N
if (isStatic) {
parts = Arrays.copyOfRange(parts, 1, parts.length);
}
if (parts.length == 1 || (parts.length > 0 && parts[0].trim().indexOf("(") > 0)) { //NOI18N
// expect that the type is void
returnType = Type.VOID;
Expand Down Expand Up @@ -137,7 +149,7 @@ public PhpElementKind getPhpElementKind() {

@Override
public Kind getKind() {
return Kind.METHOD;
return isStatic ? Kind.STATIC_METHOD : Kind.METHOD;
}

@Override
Expand Down Expand Up @@ -168,6 +180,7 @@ public List<? extends ParameterElement> getParameters() {
}

public PhpModifiers getAccessModifiers() {
return PhpModifiers.fromBitMask(PhpModifiers.PUBLIC);
int modifiers = isStatic ? (PhpModifiers.PUBLIC | PhpModifiers.STATIC) : PhpModifiers.PUBLIC;
return PhpModifiers.fromBitMask(modifiers);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.php.api.annotation.PhpAnnotations;
import org.netbeans.modules.php.api.util.StringUtils;
import org.netbeans.modules.php.editor.model.impl.Type;
import org.netbeans.modules.php.editor.parser.astnodes.PHPDocBlock;
import org.netbeans.modules.php.editor.parser.astnodes.PHPDocMethodTag;
import org.netbeans.modules.php.editor.parser.astnodes.PHPDocNode;
Expand Down Expand Up @@ -221,13 +222,14 @@ private PHPDocTag createTag(int start, int end, AnnotationParsedLine type, Strin
} else if (type.equals(PHPDocTag.Type.METHOD)) {
String name = getMethodName(description);
if (name != null) {
boolean isStatic = description.trim().startsWith("static"); // NOI18N
int startOfVariable = findStartOfDocNode(originalComment, originalCommentStart, name, start);
if (startOfVariable != -1) {
PHPDocNode methodNode = new PHPDocNode(startOfVariable, startOfVariable + name.length(), name);
int startOfDescription = findStartOfDocNode(originalComment, originalCommentStart, description, start);
if (startOfDescription != -1) {
List<PHPDocVarTypeTag> params = findMethodParams(description, startOfDescription);
return new PHPDocMethodTag(start, end, type, docTypes, methodNode, params, description);
return new PHPDocMethodTag(start, end, type, docTypes, methodNode, params, description, isStatic);
}
}
}
Expand Down Expand Up @@ -287,13 +289,21 @@ private List<PHPDocTypeNode> findTypes(String description, int startDescription,

private List<String> getTypes(String description, boolean isReturnTag) {
String[] tokens = description.trim().split("[ ]+"); //NOI18N
if (tokens.length > 0 && tokens[0].equals("static")) { // NOI18N
tokens = Arrays.copyOfRange(tokens, 1, tokens.length);
}
ArrayList<String> types = new ArrayList<>();
if (tokens.length > 0 && (isReturnTag || !tokens[0].startsWith("$"))) { //NOI18N
if (tokens[0].indexOf('|') > -1) {
String[] ttokens = tokens[0].split("[|]"); //NOI18N
for (String ttoken : ttokens) {
types.add(ttoken.trim());
}
} else if (tokens[0].indexOf('(') > 0) {
// e.g. @method getSomething(int $i)
// NOTE: add void type but it is not shown as a return type in doc popup
// because it doesn't exist
types.add(Type.VOID);
} else {
types.add(tokens[0].trim());
}
Expand Down Expand Up @@ -326,7 +336,11 @@ private String getMethodName(String description) {
} else {
// probably defined without () after the name
// then we expect that the name is after the first space
String[] tokens = description.trim().split("[ \n\t]+"); //NOI18N
String desc = description.trim();
if (desc.startsWith("static ")) { // NOI18N
desc = desc.substring("static ".length()); // NOI18N
}
String[] tokens = desc.trim().split("[ \n\t]+"); //NOI18N
if (tokens.length > 1) {
name = tokens[1];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,44 @@ public class PHPDocMethodTag extends PHPDocTypeTag {

private final List<PHPDocVarTypeTag> params;
private final PHPDocNode name;
private final boolean isStatic;

public PHPDocMethodTag(int start, int end, AnnotationParsedLine kind,
List<PHPDocTypeNode> returnTypes, PHPDocNode methodName,
List<PHPDocVarTypeTag> parameters, String documentation) {
this(start, end, kind, returnTypes, methodName, parameters, documentation, false);
}

/**
* Constructor.
*
* @param start start offset
* @param end end offset
* @param kind parsed annotation line
* @param returnTypes return types
* @param methodName method name
* @param parameters parameters
* @param documentation documentation
* @param isStatic static flag
* @since 1.84.0
*/
public PHPDocMethodTag(int start, int end, AnnotationParsedLine kind,
List<PHPDocTypeNode> returnTypes, PHPDocNode methodName,
List<PHPDocVarTypeTag> parameters, String documentation, boolean isStatic) {
super(start, end, kind, documentation, returnTypes);
this.params = parameters;
this.name = methodName;
this.isStatic = isStatic;
}

/**
* Check whethere the method is static.
*
* @return {@code true} if the method is static, {@code false} otherwise
* @since 1.84.0
*/
public boolean isStatic() {
return isStatic;
}

public PHPDocNode getMethodName() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
|-Example [1215, 1317] : ESCAPED{Example}
|--testVoid [852, 860] : ESCAPED{testVoid}ESCAPED{(}<font color="#999999">ESCAPED{Test}ESCAPED{ }</font>ESCAPED{$test}ESCAPED{)}<font color="#999999">:ESCAPED{void}</font>
|--testType [902, 910] : ESCAPED{testType}ESCAPED{(}<font color="#999999">ESCAPED{Test}ESCAPED{ }</font>ESCAPED{$test}ESCAPED{)}<font color="#999999">:ESCAPED{int}</font>
|--staticTestVoid [955, 969] : ESCAPED{staticTestVoid}ESCAPED{(}<font color="#999999">ESCAPED{Test}ESCAPED{ }</font>ESCAPED{$test}ESCAPED{)}<font color="#999999">:ESCAPED{void}</font>
|--staticTestType [1017, 1031] : ESCAPED{staticTestType}ESCAPED{(}<font color="#999999">ESCAPED{Test}ESCAPED{ }</font>ESCAPED{$param1}ESCAPED{, }ESCAPED{$param2}ESCAPED{)}<font color="#999999">:ESCAPED{int}</font>
|--staticTestNullable [1092, 1110] : ESCAPED{staticTestNullable}ESCAPED{(}<font color="#999999">ESCAPED{?}ESCAPED{string}ESCAPED{ }</font>ESCAPED{$param}ESCAPED{, }<font color="#999999">ESCAPED{int}ESCAPED{ }</font>ESCAPED{$param2}ESCAPED{)}<font color="#999999">:ESCAPED{?}ESCAPED{int}</font>
|--getDefault [1180, 1190] : ESCAPED{getDefault}ESCAPED{(}ESCAPED{)}<font color="#999999">:ESCAPED{?}ESCAPED{\Example}</font>
|--test [1246, 1260] : ESCAPED{test}ESCAPED{(}ESCAPED{)}
|--staticTest [1289, 1314] : ESCAPED{staticTest}ESCAPED{(}ESCAPED{)}<font color="#999999">:ESCAPED{int}</font>
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<Comments>
<PHPDocBlock start='10' end='31'>
<Tags>
<PHPDocMethodTag start='14' end='27' kind='method'>
<PHPDocMethodTag start='14' end='27' kind='method' isStatic='false'>
<Name>
<PHPDocNode start='24' end='26' value='m1'/>
</Name>
Expand All @@ -37,7 +37,7 @@
</PHPDocBlock>
<PHPDocBlock start='10' end='31'>
<Tags>
<PHPDocMethodTag start='14' end='27' kind='method'>
<PHPDocMethodTag start='14' end='27' kind='method' isStatic='false'>
<Name>
<PHPDocNode start='24' end='26' value='m1'/>
</Name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<Comments>
<PHPDocBlock start='10' end='33'>
<Tags>
<PHPDocMethodTag start='14' end='29' kind='method'>
<PHPDocMethodTag start='14' end='29' kind='method' isStatic='false'>
<Name>
<PHPDocNode start='24' end='26' value='m1'/>
</Name>
Expand All @@ -37,7 +37,7 @@
</PHPDocBlock>
<PHPDocBlock start='10' end='33'>
<Tags>
<PHPDocMethodTag start='14' end='29' kind='method'>
<PHPDocMethodTag start='14' end='29' kind='method' isStatic='false'>
<Name>
<PHPDocNode start='24' end='26' value='m1'/>
</Name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<Comments>
<PHPDocBlock start='10' end='50'>
<Tags>
<PHPDocMethodTag start='14' end='46' kind='method'>
<PHPDocMethodTag start='14' end='46' kind='method' isStatic='false'>
<Name>
<PHPDocNode start='24' end='26' value='m1'/>
</Name>
Expand All @@ -37,7 +37,7 @@
</PHPDocBlock>
<PHPDocBlock start='10' end='50'>
<Tags>
<PHPDocMethodTag start='14' end='46' kind='method'>
<PHPDocMethodTag start='14' end='46' kind='method' isStatic='false'>
<Name>
<PHPDocNode start='24' end='26' value='m1'/>
</Name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<Comments>
<PHPDocBlock start='10' end='57'>
<Tags>
<PHPDocMethodTag start='14' end='53' kind='method'>
<PHPDocMethodTag start='14' end='53' kind='method' isStatic='false'>
<Name>
<PHPDocNode start='24' end='26' value='m1'/>
</Name>
Expand All @@ -44,7 +44,7 @@
</PHPDocBlock>
<PHPDocBlock start='10' end='57'>
<Tags>
<PHPDocMethodTag start='14' end='53' kind='method'>
<PHPDocMethodTag start='14' end='53' kind='method' isStatic='false'>
<Name>
<PHPDocNode start='24' end='26' value='m1'/>
</Name>
Expand Down
Loading

0 comments on commit fbeb749

Please sign in to comment.