Skip to content

Commit

Permalink
Merge pull request #8139 from junichi11/php84-deprecated-attribute
Browse files Browse the repository at this point in the history
PHP 8.4 Support: #[\Deprecated] Attribute
  • Loading branch information
junichi11 authored Jan 11, 2025
2 parents 56b8332 + 2490982 commit 0b5cc44
Show file tree
Hide file tree
Showing 102 changed files with 7,107 additions and 211 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -901,4 +901,9 @@ public static boolean isDnfType(UnionType unionType) {
}
return false;
}

public static boolean isTypeDeclaration(ASTNode node) {
return node instanceof TypeDeclaration
|| ((node instanceof ClassInstanceCreation) && ((ClassInstanceCreation) node).isAnonymous());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ public static enum VariableKind {
public static enum Attributes {
ATTRIBUTE("Attribute"), // NOI18N
ALLOW_DYNAMIC_PROPERTIES("AllowDynamicProperties"), // NOI18N
DEPRECATED("Deprecated"), // NOI18N
OVERRIDE("Override"), // NOI18N
RETURN_TYPE_WILL_CHANGE("ReturnTypeWillChange"), // NOI18N
SENSITIVE_PARAMETER("SensitiveParameter"), // NOI18N
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public static EnumCaseElement fromNode(final TypeElement type, CaseDeclaration n
info.getAccessModifiers().toFlags(),
fileQuery.getURL().toExternalForm(),
fileQuery,
VariousUtils.isDeprecatedFromPHPDoc(fileQuery.getResult().getProgram(), node),
VariousUtils.isDeprecated(fileQuery.getResult().getModel().getFileScope(), fileQuery.getResult().getProgram(), node),
isBacked
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public static FunctionElement fromNode(final NamespaceElement namespace, final F
fullyQualifiedName.append(info.getName()), info.getRange().getStart(),
fileQuery.getURL().toExternalForm(), fileQuery, BaseFunctionElementSupport.ParametersImpl.create(info.getParameters()),
BaseFunctionElementSupport.ReturnTypesImpl.create(TypeResolverImpl.parseTypes(VariousUtils.getReturnType(fileQuery.getResult().getProgram(), node)), node.getReturnType()),
VariousUtils.isDeprecatedFromPHPDoc(fileQuery.getResult().getProgram(), node));
VariousUtils.isDeprecated(fileQuery.getResult().getModel().getFileScope(), fileQuery.getResult().getProgram(), node));
}

private static boolean matchesQuery(final NameKind query, FunctionSignatureParser signParser) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ public static MethodElement fromNode(final TypeElement type, final MethodDeclara
BaseFunctionElementSupport.ParametersImpl.create(info.getParameters()),
BaseFunctionElementSupport.ReturnTypesImpl.create(
TypeResolverImpl.parseTypes(VariousUtils.getReturnType(fileQuery.getResult().getProgram(), node.getFunction())), node.getFunction().getReturnType()),
VariousUtils.isDeprecatedFromPHPDoc(fileQuery.getResult().getProgram(), node.getFunction()));
VariousUtils.isDeprecated(fileQuery.getResult().getModel().getFileScope(), fileQuery.getResult().getProgram(), node.getFunction()));
}

private static boolean matchesQuery(final NameKind query, MethodSignatureParser signParser) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ public static Set<TypeConstantElement> fromNode(final TypeElement type, Constant
retval.add(new TypeConstantElementImpl(
type, info.getDeclaredType(), info.getName(), info.getValue(), info.getRange().getStart(),
info.getAccessModifiers().toFlags(), fileQuery.getURL().toExternalForm(), fileQuery,
VariousUtils.isDeprecatedFromPHPDoc(fileQuery.getResult().getProgram(), node)));
VariousUtils.isDeprecated(fileQuery.getResult().getModel().getFileScope(), fileQuery.getResult().getProgram(), node)));
}
return retval;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ static EnumScopeImpl create(EnumDeclarationInfo nodeInfo, ModelBuilder context)

static MethodScopeImpl create(MethodDeclarationInfo nodeInfo, ModelBuilder context, ModelVisitor visitor) {
String returnType = VariousUtils.getReturnType(context.getProgram(), nodeInfo.getOriginalNode().getFunction());
boolean isDeprecated = VariousUtils.isDeprecatedFromPHPDoc(context.getProgram(), nodeInfo.getOriginalNode().getFunction());
boolean isDeprecated = VariousUtils.isDeprecated(context.getFileScope(), context.getProgram(), nodeInfo.getOriginalNode());
String qualifiedReturnType = VariousUtils.qualifyTypeNames(returnType, nodeInfo.getOriginalNode().getStartOffset(), context.getCurrentScope());
MethodScopeImpl method = new MethodScopeImpl(context.getCurrentScope(), qualifiedReturnType, nodeInfo, visitor, isDeprecated);
return method;
Expand All @@ -341,12 +341,12 @@ static FieldElementImpl create(SingleFieldDeclarationInfo nodeInfo, ModelBuilder
}

static ClassConstantElementImpl create(ClassConstantDeclarationInfo clsConst, ModelBuilder context) {
boolean isDeprecated = VariousUtils.isDeprecatedFromPHPDoc(context.getProgram(), clsConst.getOriginalNode());
boolean isDeprecated = VariousUtils.isDeprecated(context.getFileScope(), context.getProgram(), clsConst.getConstantDeclaration());
return new ClassConstantElementImpl(context.getCurrentScope(), clsConst, isDeprecated);
}

static CaseElementImpl create(CaseDeclarationInfo enumCase, ModelBuilder context) {
boolean isDeprecated = VariousUtils.isDeprecatedFromPHPDoc(context.getProgram(), enumCase.getOriginalNode());
boolean isDeprecated = VariousUtils.isDeprecated(context.getFileScope(), context.getProgram(), enumCase.getCaseDeclaration());
return new CaseElementImpl(context.getCurrentScope(), enumCase, isDeprecated);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ FunctionScopeImpl createElement(Program program, FunctionDeclaration node) {
qualifiedReturnType = VariousUtils.qualifyTypeNames(VariousUtils.getReturnType(program, node), returnType.getStartOffset(), this);
}
FunctionScopeImpl retval = new FunctionScopeImpl(this, FunctionDeclarationInfo.create(program, node),
qualifiedReturnType, VariousUtils.isDeprecatedFromPHPDoc(program, node));
qualifiedReturnType, VariousUtils.isDeprecated(getFileScope(), program, node));
return retval;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,14 @@
import java.util.Stack;
import java.util.regex.Pattern;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.lexer.Token;
import org.netbeans.api.lexer.TokenSequence;
import org.netbeans.api.lexer.TokenUtilities;
import org.netbeans.modules.php.api.util.StringUtils;
import org.netbeans.modules.php.editor.CodeUtils;
import org.netbeans.modules.php.editor.PredefinedSymbols.Attributes;
import static org.netbeans.modules.php.editor.PredefinedSymbols.Attributes.DEPRECATED;
import org.netbeans.modules.php.editor.api.AliasedName;
import org.netbeans.modules.php.editor.api.PhpModifiers;
import org.netbeans.modules.php.editor.api.QualifiedName;
Expand Down Expand Up @@ -69,6 +72,9 @@
import org.netbeans.modules.php.editor.parser.astnodes.AnonymousObjectVariable;
import org.netbeans.modules.php.editor.parser.astnodes.ArrayCreation;
import org.netbeans.modules.php.editor.parser.astnodes.Assignment;
import org.netbeans.modules.php.editor.parser.astnodes.Attribute;
import org.netbeans.modules.php.editor.parser.astnodes.AttributeDeclaration;
import org.netbeans.modules.php.editor.parser.astnodes.Attributed;
import org.netbeans.modules.php.editor.parser.astnodes.ClassInstanceCreation;
import org.netbeans.modules.php.editor.parser.astnodes.ClassInstanceCreationVariable;
import org.netbeans.modules.php.editor.parser.astnodes.ClassName;
Expand Down Expand Up @@ -358,6 +364,61 @@ public static boolean isDeprecatedFromPHPDoc(Program root, ASTNode node) {
return getDeprecatedDescriptionFromPHPDoc(root, node) != null;
}

public static boolean isDeprecatedFromAttribute(FileScope fileScope, Program root, ASTNode node) {
if (node instanceof Attributed) {
List<Attribute> attributes = ((Attributed) node).getAttributes();
for (Attribute attribute : attributes) {
for (AttributeDeclaration attributeDeclaration : attribute.getAttributeDeclarations()) {
String attributeName = CodeUtils.extractQualifiedName(attributeDeclaration.getAttributeName());
if (isPredefinedAttributeName(DEPRECATED, attributeName, fileScope, attributeDeclaration.getStartOffset())) {
return true;
}
}
}
}
return false;
}

public static boolean isDeprecated(FileScope fileScope, Program root, ASTNode node) {
if (isDeprecatedFromAttribute(fileScope, root, node)) {
return true;
}
return isDeprecatedFromPHPDoc(root, node);
}

public static boolean isPredefinedAttributeName(Attributes attribute, String attributeName, FileScope fileScope, int offset) {
if (attribute.getFqName().equals(attributeName)) {
return true;
}
if (attribute.getName().equals(attributeName)) {
List<? extends NamespaceScope> declaredNamespaces = new ArrayList<NamespaceScope>(fileScope.getDeclaredNamespaces());
Collections.sort(declaredNamespaces, (n1, n2) -> -Integer.compare(n1.getOffset(), n2.getOffset()));
NamespaceScope namespaceScope = null;
for (NamespaceScope declaredNamespace : declaredNamespaces) {
int namespaceOffset = declaredNamespace.getOffset();
if (namespaceOffset < offset) {
namespaceScope = declaredNamespace;
break;
}
}
// check FQ name because there may be `use \AttributeName;`
if (isPredefinedAttributeName(attribute, attributeName, namespaceScope, offset)) {
return true;
}
}
return false;
}

private static boolean isPredefinedAttributeName(Attributes attribute, String attributeName, @NullAllowed NamespaceScope namespaceScope, int offset) {
if (namespaceScope != null) {
QualifiedName fullyQualifiedName = VariousUtils.getFullyQualifiedName(QualifiedName.create(attributeName), offset, namespaceScope);
if (attribute.getFqName().equals(fullyQualifiedName.toString())) {
return true;
}
}
return false;
}

public static Map<String, Pair<String, List<Pair<QualifiedName, Boolean>>>> getParamTypesFromPHPDoc(Program root, ASTNode node) {
Map<String, Pair<String, List<Pair<QualifiedName, Boolean>>>> retval = new HashMap<>();
Comment comment = Utils.getCommentForNode(root, node);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ public PhpModifiers getAccessModifiers() {
return PhpModifiers.fromBitMask(caseDeclaration.getModifier());
}

public CaseDeclaration getCaseDeclaration() {
return caseDeclaration;
}

@CheckForNull
protected static String getCaseValue(Expression expr) {
if (expr instanceof Scalar) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ public PhpModifiers getAccessModifiers() {
return PhpModifiers.fromBitMask(constantDeclaration.getModifier());
}

public ConstantDeclaration getConstantDeclaration() {
return constantDeclaration;
}

@CheckForNull
protected static String getConstantValue(Expression expr) {
if (expr instanceof Scalar) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@
<file name="org-netbeans-modules-php-editor-verification-IncorrectConstructorPropertyPromotionHintError.instance"/>
<file name="org-netbeans-modules-php-editor-verification-FinalModifierHintError.instance"/>
<file name="org-netbeans-modules-php-editor-verification-IncorrectFirstClassCallableSyntaxHintError.instance"/>
<file name="org-netbeans-modules-php-editor-verification-IncorrectDeprecatedAttributeHintError.instance"/>
<file name="org-netbeans-modules-php-editor-verification-IncorrectEnumHintError.instance"/>
<file name="org-netbeans-modules-php-editor-verification-IncorrectListUnhandledError.instance"/>
<file name="org-netbeans-modules-php-editor-verification-IncorrectMixedGroupUseHintError.instance"/>
Expand Down
Loading

0 comments on commit 0b5cc44

Please sign in to comment.