Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.intellij.java.language.patterns;

import com.intellij.java.language.psi.*;
import consulo.annotation.access.RequiredReadAction;
import consulo.language.pattern.ElementPattern;
import consulo.language.pattern.IElementTypePattern;
import consulo.language.pattern.InitialPatternCondition;
Expand All @@ -28,162 +29,168 @@
import consulo.language.pattern.VirtualFilePattern;

import org.jspecify.annotations.Nullable;

import java.util.Collections;
import java.util.List;

/**
* @author peter
*/
public class PsiJavaPatterns extends StandardPatterns {
public static IElementTypePattern elementType() {
return PlatformPatterns.elementType();
}

public static VirtualFilePattern virtualFile() {
return PlatformPatterns.virtualFile();
}

public static PsiJavaElementPattern.Capture<PsiElement> psiJavaElement() {
return new PsiJavaElementPattern.Capture<>(PsiElement.class);
}

public static PsiJavaElementPattern.Capture<PsiElement> psiJavaElement(IElementType type) {
return psiJavaElement().withElementType(type);
}

public static <T extends PsiElement> PsiJavaElementPattern.Capture<T> psiJavaElement(Class<T> aClass) {
return new PsiJavaElementPattern.Capture<>(aClass);
}

@SafeVarargs
public static PsiJavaElementPattern.Capture<PsiElement> psiJavaElement(final Class<? extends PsiElement>... classAlternatives) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the reformat removed final from the other parameters (for example psiJavaElement(Class<T> aClass)), but it's still here and on L84, L98 and L117. Effectively-final is enough for capture in the anonymous classes.

Suggested change
public static PsiJavaElementPattern.Capture<PsiElement> psiJavaElement(final Class<? extends PsiElement>... classAlternatives) {
public static PsiJavaElementPattern.Capture<PsiElement> psiJavaElement(Class<? extends PsiElement>... classAlternatives) {

return new PsiJavaElementPattern.Capture<>(new InitialPatternCondition<>(PsiElement.class) {
@Override
@RequiredReadAction
Comment on lines +63 to +64

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This accepts only calls Class.isInstance, so it never touches PSI and doesn't need @RequiredReadAction. Meanwhile the conditions that do read PSI (psiNewExpression, psiLiteral, literalExpression) have no annotation. I'd drop it here (and in psiModifierListOwner below) and add it where it actually applies.

Suggested change
@Override
@RequiredReadAction
@Override

public boolean accepts(@Nullable Object o, ProcessingContext context) {
for (Class<? extends PsiElement> classAlternative : classAlternatives) {
if (classAlternative.isInstance(o)) {
return true;
}
}
return false;
}
});
}

public static PsiJavaElementPattern.Capture<PsiLiteralExpression> literalExpression() {
return literalExpression(null);
}

public static PsiJavaElementPattern.Capture<PsiLiteral> psiLiteral() {
return psiLiteral(null);
}

public static PsiJavaElementPattern.Capture<PsiLiteral> psiLiteral(@Nullable final ElementPattern value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static PsiJavaElementPattern.Capture<PsiLiteral> psiLiteral(@Nullable final ElementPattern value) {
public static PsiJavaElementPattern.Capture<PsiLiteral> psiLiteral(@Nullable ElementPattern value) {

return new PsiJavaElementPattern.Capture<>(new InitialPatternConditionPlus<>(PsiLiteral.class) {
@Override
public boolean accepts(@Nullable Object o, ProcessingContext context) {
return o instanceof PsiLiteral literal && (value == null || value.accepts(literal.getValue(), context));
}

@Override
public List<ElementPattern<?>> getPatterns() {
return Collections.<ElementPattern<?>>singletonList(value);
}
});
}

public static PsiJavaElementPattern.Capture<PsiNewExpression> psiNewExpression(final String... fqns) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static PsiJavaElementPattern.Capture<PsiNewExpression> psiNewExpression(final String... fqns) {
public static PsiJavaElementPattern.Capture<PsiNewExpression> psiNewExpression(String... fqns) {

return new PsiJavaElementPattern.Capture<>(new InitialPatternCondition<>(PsiNewExpression.class) {
@Override

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the condition that needs @RequiredReadAction: getClassOrAnonymousClassReference() and getQualifiedName() both walk or resolve PSI. The same goes for PsiLiteral.getValue() in psiLiteral (L86) and literalExpression (L119).

Suggested change
@Override
@Override
@RequiredReadAction

public boolean accepts(@Nullable Object o, ProcessingContext context) {
if (o instanceof PsiNewExpression newExpr) {
PsiJavaCodeReferenceElement reference = newExpr.getClassOrAnonymousClassReference();
if (reference != null) {
for (String fqn : fqns) {
if (fqn.equals(reference.getQualifiedName())) {
return true;
}
}
}
}
return false;
}
});
}

public static PsiJavaElementPattern.Capture<PsiLiteralExpression> literalExpression(@Nullable final ElementPattern value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static PsiJavaElementPattern.Capture<PsiLiteralExpression> literalExpression(@Nullable final ElementPattern value) {
public static PsiJavaElementPattern.Capture<PsiLiteralExpression> literalExpression(@Nullable ElementPattern value) {

return new PsiJavaElementPattern.Capture<>(new InitialPatternConditionPlus<>(PsiLiteralExpression.class) {
@Override
public boolean accepts(@Nullable Object o, ProcessingContext context) {
return o instanceof PsiLiteralExpression literal && (value == null || value.accepts(literal.getValue(), context));
}

public static IElementTypePattern elementType() {
return PlatformPatterns.elementType();
}

public static VirtualFilePattern virtualFile() {
return PlatformPatterns.virtualFile();
}

public static PsiJavaElementPattern.Capture<PsiElement> psiJavaElement() {
return new PsiJavaElementPattern.Capture<>(PsiElement.class);
}

public static PsiJavaElementPattern.Capture<PsiElement> psiJavaElement(IElementType type) {
return psiJavaElement().withElementType(type);
}

public static <T extends PsiElement> PsiJavaElementPattern.Capture<T> psiJavaElement(final Class<T> aClass) {
return new PsiJavaElementPattern.Capture<>(aClass);
}

@SafeVarargs
public static PsiJavaElementPattern.Capture<PsiElement> psiJavaElement(final Class<? extends PsiElement>... classAlternatives) {
return new PsiJavaElementPattern.Capture<>(new InitialPatternCondition<>(PsiElement.class) {
@Override
public boolean accepts(@Nullable Object o, ProcessingContext context) {
for (Class<? extends PsiElement> classAlternative : classAlternatives) {
if (classAlternative.isInstance(o)) {
return true;
}
}
return false;
}
});
}

public static PsiJavaElementPattern.Capture<PsiLiteralExpression> literalExpression() {
return literalExpression(null);
}

public static PsiJavaElementPattern.Capture<PsiLiteral> psiLiteral() {
return psiLiteral(null);
}

public static PsiJavaElementPattern.Capture<PsiLiteral> psiLiteral(@Nullable final ElementPattern value) {
return new PsiJavaElementPattern.Capture<>(new InitialPatternConditionPlus<>(PsiLiteral.class) {
public boolean accepts(@Nullable final Object o, final ProcessingContext context) {
return o instanceof PsiLiteral && (value == null || value.accepts(((PsiLiteral)o).getValue(), context));
}

@Override
public List<ElementPattern<?>> getPatterns() {
return Collections.<ElementPattern<?>>singletonList(value);
}
});
}

public static PsiJavaElementPattern.Capture<PsiNewExpression> psiNewExpression(final String... fqns) {
return new PsiJavaElementPattern.Capture<>(new InitialPatternCondition<>(PsiNewExpression.class) {
public boolean accepts(@Nullable final Object o, final ProcessingContext context) {
if(o instanceof PsiNewExpression) {
PsiJavaCodeReferenceElement reference = ((PsiNewExpression)o).getClassOrAnonymousClassReference();
if (reference != null) {
for (String fqn : fqns) {
if( fqn.equals(reference.getQualifiedName())) return true;
@Override
public List<ElementPattern<?>> getPatterns() {
return Collections.<ElementPattern<?>>singletonList(value);
}
});
}

public static PsiMemberPattern.Capture psiMember() {
return new PsiMemberPattern.Capture();
}

public static PsiMethodPattern psiMethod() {
return new PsiMethodPattern();
}

public static PsiParameterPattern psiParameter() {
return new PsiParameterPattern();
}

public static PsiModifierListOwnerPattern.Capture<PsiModifierListOwner> psiModifierListOwner() {
return new PsiModifierListOwnerPattern.Capture<>(new InitialPatternCondition<>(PsiModifierListOwner.class) {
@Override
@RequiredReadAction
Comment on lines +145 to +146

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: a plain instanceof check doesn't need a read action.

Suggested change
@Override
@RequiredReadAction
@Override

public boolean accepts(@Nullable Object o, ProcessingContext context) {
return o instanceof PsiModifierListOwner;
}
}
}
return false;
}
});
}

public static PsiJavaElementPattern.Capture<PsiLiteralExpression> literalExpression(@Nullable final ElementPattern value) {
return new PsiJavaElementPattern.Capture<>(new InitialPatternConditionPlus<>(PsiLiteralExpression.class) {
public boolean accepts(@Nullable final Object o, final ProcessingContext context) {
return o instanceof PsiLiteralExpression && (value == null || value.accepts(((PsiLiteralExpression)o).getValue(), context));
}

@Override
public List<ElementPattern<?>> getPatterns() {
return Collections.<ElementPattern<?>>singletonList(value);
}
});
}

public static PsiMemberPattern.Capture psiMember() {
return new PsiMemberPattern.Capture();
}

public static PsiMethodPattern psiMethod() {
return new PsiMethodPattern();
}

public static PsiParameterPattern psiParameter() {
return new PsiParameterPattern();
}

public static PsiModifierListOwnerPattern.Capture<PsiModifierListOwner> psiModifierListOwner() {
return new PsiModifierListOwnerPattern.Capture<>(new InitialPatternCondition<>(PsiModifierListOwner.class) {
@Override
public boolean accepts(@Nullable Object o, ProcessingContext context) {
return o instanceof PsiModifierListOwner;
}
});
}


public static PsiFieldPattern psiField() {
return new PsiFieldPattern();
}

public static PsiClassPattern psiClass() {
return new PsiClassPattern();
}

public static PsiAnnotationPattern psiAnnotation() {
return new PsiAnnotationPattern();
}

public static PsiNameValuePairPattern psiNameValuePair() {
return new PsiNameValuePairPattern();
}

public static PsiTypePattern psiType() {
return new PsiTypePattern();
}

public static PsiExpressionPattern.Capture<PsiExpression> psiExpression() {
return new PsiExpressionPattern.Capture<>(PsiExpression.class);
}

public static PsiBinaryExpressionPattern psiBinaryExpression() {
return new PsiBinaryExpressionPattern();
}

public static PsiTypeCastExpressionPattern psiTypeCastExpression() {
return new PsiTypeCastExpressionPattern();
}

public static PsiJavaElementPattern.Capture<PsiReferenceExpression> psiReferenceExpression() {
return psiJavaElement(PsiReferenceExpression.class);
}

public static PsiStatementPattern.Capture<PsiExpressionStatement> psiExpressionStatement() {
return new PsiStatementPattern.Capture<>(PsiExpressionStatement.class);
}

public static PsiStatementPattern.Capture<PsiReturnStatement> psiReturnStatement() {
return new PsiStatementPattern.Capture<>(PsiReturnStatement.class);
}
});
}

public static PsiFieldPattern psiField() {
return new PsiFieldPattern();
}

public static PsiClassPattern psiClass() {
return new PsiClassPattern();
}

public static PsiAnnotationPattern psiAnnotation() {
return new PsiAnnotationPattern();
}

public static PsiNameValuePairPattern psiNameValuePair() {
return new PsiNameValuePairPattern();
}

public static PsiTypePattern psiType() {
return new PsiTypePattern();
}

public static PsiExpressionPattern.Capture<PsiExpression> psiExpression() {
return new PsiExpressionPattern.Capture<>(PsiExpression.class);
}

public static PsiBinaryExpressionPattern psiBinaryExpression() {
return new PsiBinaryExpressionPattern();
}

public static PsiTypeCastExpressionPattern psiTypeCastExpression() {
return new PsiTypeCastExpressionPattern();
}

public static PsiJavaElementPattern.Capture<PsiReferenceExpression> psiReferenceExpression() {
return psiJavaElement(PsiReferenceExpression.class);
}

public static PsiStatementPattern.Capture<PsiExpressionStatement> psiExpressionStatement() {
return new PsiStatementPattern.Capture<>(PsiExpressionStatement.class);
}

public static PsiStatementPattern.Capture<PsiReturnStatement> psiReturnStatement() {
return new PsiStatementPattern.Capture<>(PsiReturnStatement.class);
}
}
Loading
Loading