下面列出了怎么用com.intellij.psi.PsiModifierList的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public void visitClass(UClass uClass) {
//only check interface
if(!uClass.isInterface()){
return;
}
Set<PropInfo> infos = getPropInfoWithSupers(uClass);
if(infos.isEmpty()){
return;
}
//check method is relative of any field
for(UMethod method: uClass.getMethods()){
PsiModifierList list = method.getModifierList();
PsiAnnotation pa_keep = list.findAnnotation(NAME_KEEP);
PsiAnnotation pa_impl = list.findAnnotation(NAME_IMPL_METHOD);
if (pa_keep == null && pa_impl == null) {
if(!hasPropInfo(infos, method.getName())){
report(method);
}
}
}
}
@Override
public void visitClass(UClass uClass) {
//only check interface
if(!uClass.isInterface()){
return;
}
Set<PropInfo> infos = getPropInfoWithSupers(uClass);
if(infos.isEmpty()){
return;
}
//check method is relative of any field
for(UMethod method: uClass.getMethods()){
PsiModifierList list = method.getModifierList();
PsiAnnotation pa_keep = list.findAnnotation(NAME_KEEP);
PsiAnnotation pa_impl = list.findAnnotation(NAME_IMPL_METHOD);
if (pa_keep == null && pa_impl == null) {
if(!hasPropInfo(infos, method.getName())){
report(method);
}
}
}
}
static PsiAnnotation findAnnotation(PsiElement element, String annotationName) {
if (element instanceof PsiModifierListOwner) {
PsiModifierListOwner listOwner = (PsiModifierListOwner) element;
PsiModifierList modifierList = listOwner.getModifierList();
if (modifierList != null) {
for (PsiAnnotation psiAnnotation : modifierList.getAnnotations()) {
if (annotationName.equals(psiAnnotation.getQualifiedName())) {
return psiAnnotation;
}
}
}
}
return null;
}
private static boolean isJUnit4Class(PsiClass psiClass) {
String qualifiedName = JUnitUtil.RUN_WITH;
if (AnnotationUtil.isAnnotated(psiClass, qualifiedName, true)) {
return true;
}
// handle the case where RunWith and/or the current class isn't indexed
PsiModifierList modifierList = psiClass.getModifierList();
if (modifierList == null) {
return false;
}
if (modifierList.hasAnnotation(qualifiedName)) {
return true;
}
String shortName = StringUtil.getShortName(qualifiedName);
return modifierList.hasAnnotation(shortName) && hasImport(psiClass, qualifiedName);
}
@Nullable
public static TestSize getTestSize(PsiClass psiClass) {
PsiModifierList psiModifierList = psiClass.getModifierList();
if (psiModifierList == null) {
return null;
}
PsiAnnotation[] annotations = psiModifierList.getAnnotations();
TestSize testSize = getTestSize(annotations);
if (testSize != null) {
return testSize;
}
String fullText = psiModifierList.getText();
return CATEGORY_ANNOTATION_HEURISTIC
.entrySet()
.stream()
.filter(e -> fullText.contains(e.getKey()))
.map(Map.Entry::getValue)
.findFirst()
.orElse(null);
}
public static boolean isModifierListSupported(@NotNull PsiModifierList modifierList) {
PsiElement modifierListParent = modifierList.getParent();
if (modifierListParent instanceof PsiClass) {
PsiClass parentClass = (PsiClass) modifierListParent;
if (PsiAnnotationSearchUtil.isAnnotatedWith(parentClass, UtilityClass.class)) {
return UtilityClassProcessor.validateOnRightType(parentClass, new ProblemNewBuilder());
}
}
if (!isElementFieldOrMethodOrInnerClass(modifierListParent)) {
return false;
}
PsiClass searchableClass = PsiTreeUtil.getParentOfType(modifierListParent, PsiClass.class, true);
return null != searchableClass && PsiAnnotationSearchUtil.isAnnotatedWith(searchableClass, UtilityClass.class) && UtilityClassProcessor.validateOnRightType(searchableClass, new ProblemNewBuilder());
}
@Override
public void transformModifiers(@NotNull PsiModifierList modifierList, @NotNull final Set<String> modifiers) {
final PsiElement parent = modifierList.getParent();
// FINAL
if (parent instanceof PsiClass) {
PsiClass psiClass = (PsiClass) parent;
if (PsiAnnotationSearchUtil.isAnnotatedWith(psiClass, UtilityClass.class)) {
modifiers.add(PsiModifier.FINAL);
}
}
// STATIC
if (isElementFieldOrMethodOrInnerClass(parent)) {
modifiers.add(PsiModifier.STATIC);
}
}
@NotNull
public PsiMethod createGetterMethod(@NotNull PsiField psiField, @NotNull PsiClass psiClass, @NotNull String methodModifier) {
final String methodName = LombokUtils.getGetterName(psiField);
LombokLightMethodBuilder methodBuilder = new LombokLightMethodBuilder(psiField.getManager(), methodName)
.withMethodReturnType(psiField.getType())
.withContainingClass(psiClass)
.withNavigationElement(psiField);
if (StringUtil.isNotEmpty(methodModifier)) {
methodBuilder.withModifier(methodModifier);
}
boolean isStatic = psiField.hasModifierProperty(PsiModifier.STATIC);
if (isStatic) {
methodBuilder.withModifier(PsiModifier.STATIC);
}
final String blockText = String.format("return %s.%s;", isStatic ? psiClass.getName() : "this", psiField.getName());
methodBuilder.withBody(PsiMethodUtil.createCodeBlockFromText(blockText, methodBuilder));
PsiModifierList modifierList = methodBuilder.getModifierList();
copyAnnotations(psiField, modifierList,
LombokUtils.NON_NULL_PATTERN, LombokUtils.NULLABLE_PATTERN, LombokUtils.DEPRECATED_PATTERN);
addOnXAnnotations(PsiAnnotationSearchUtil.findAnnotation(psiField, Getter.class), modifierList, "onMethod");
return methodBuilder;
}
@Override
protected void process(List<ClassMember> classMembers) {
for (ClassMember classMember : classMembers) {
final PsiElementClassMember elementClassMember = (PsiElementClassMember) classMember;
PsiField psiField = (PsiField) elementClassMember.getPsiElement();
PsiMethod psiMethod = PropertyUtil.findPropertySetter(psiField.getContainingClass(), psiField.getName(), false, false);
if (null != psiMethod) {
PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
PsiAnnotation psiAnnotation = modifierList.addAnnotation(Setter.class.getName());
psiMethod.delete();
}
}
}
}
@Override
protected void process(List<ClassMember> classMembers) {
for (ClassMember classMember : classMembers) {
final PsiElementClassMember elementClassMember = (PsiElementClassMember) classMember;
PsiField psiField = (PsiField) elementClassMember.getPsiElement();
PsiMethod psiMethod = PropertyUtil.findPropertyGetter(psiField.getContainingClass(), psiField.getName(), false, false);
if (null != psiMethod) {
PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
PsiAnnotation psiAnnotation = modifierList.addAnnotation(Getter.class.getName());
// psiAnnotation.setDeclaredAttributeValue("value", )
psiMethod.delete();
}
}
}
}
@Override public boolean visitField(UField field) {
PsiModifierList modifierList = field.getModifierList();
if (modifierList == null || modifierList.hasModifierProperty(PsiModifier.TRANSIENT)) {
return false;
}
if (!isInJob(field)) {
return false;
}
if (hasAnnotation(modifierList, JAVAX_INJECT)) {
context.report(ISSUE, context.getLocation(field), LINT_ERROR_MESSAGE);
}
return super.visitField(field);
}
public static Set<String> getQualifierAnnotations(PsiElement element) {
Set<String> qualifiedClasses = new HashSet<String>();
if (element instanceof PsiModifierListOwner) {
PsiModifierListOwner listOwner = (PsiModifierListOwner) element;
PsiModifierList modifierList = listOwner.getModifierList();
if (modifierList != null) {
for (PsiAnnotation psiAnnotation : modifierList.getAnnotations()) {
if (psiAnnotation != null && psiAnnotation.getQualifiedName() != null) {
JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(element.getProject());
PsiClass psiClass = psiFacade.findClass(psiAnnotation.getQualifiedName(),
GlobalSearchScope.projectScope(element.getProject()));
if (hasAnnotation(psiClass, CLASS_QUALIFIER)) {
qualifiedClasses.add(psiAnnotation.getQualifiedName());
}
}
}
}
}
return qualifiedClasses;
}
private static CompletionProvider<CompletionParameters> typeCompletionProvider() {
return new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(
@NotNull CompletionParameters completionParameters,
ProcessingContext processingContext,
@NotNull CompletionResultSet completionResultSet) {
PsiElement element = completionParameters.getPosition();
// Method parameter type in the Spec class
// PsiIdentifier -> PsiJavaCodeReferenceElement -> PsiTypeElement -> PsiMethod -> PsiClass
PsiElement typeElement = PsiTreeUtil.getParentOfType(element, PsiTypeElement.class);
if (typeElement == null) {
return;
}
PsiMethod containingMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
if (containingMethod == null) {
return;
}
PsiClass cls = containingMethod.getContainingClass();
if (!LithoPluginUtils.isLithoSpec(cls)) {
return;
}
// @Prop or @State annotation
PsiModifierList parameterModifiers =
PsiTreeUtil.getPrevSiblingOfType(typeElement, PsiModifierList.class);
if (parameterModifiers == null) {
return;
}
if (parameterModifiers.findAnnotation(Prop.class.getName()) != null) {
addCompletionResult(
completionResultSet, containingMethod, cls.getMethods(), LithoPluginUtils::isProp);
} else if (parameterModifiers.findAnnotation(State.class.getName()) != null) {
addCompletionResult(
completionResultSet, containingMethod, cls.getMethods(), LithoPluginUtils::isState);
}
}
};
}
private static List<Modifier> extractModifiersInternal(PsiModifierList modifierList) {
List<Modifier> modifiers = new ArrayList<>();
PsiElement[] children = modifierList.getChildren();
for (PsiElement child : children) {
if (child instanceof PsiModifier || child instanceof PsiKeyword) {
modifiers.add(psiModifierToModifier(child));
}
}
return modifiers;
}
@Override
public void visitClass(JavaContext context, UClass declaration) {
PsiModifierList classModifiers = declaration.getModifierList();
if (classModifiers == null || !classModifiers.hasModifierProperty("abstract")) {
// check for static build method
boolean hasBuildMethod = false;
for (PsiMethod method : declaration.getMethods()) {
if ("build".equals(method.getName()) && method.getModifierList()
.hasModifierProperty("static")) {
hasBuildMethod = true;
break;
}
}
if (!hasBuildMethod){
context.report(BUILD_OVERWRITE, context.getLocation(declaration.getExtendsList()),
BUILD_OVERWRITE_MESSAGE);
}
// check for public static String TAG
boolean hasTag = false;
for (UField field : declaration.getFields()) {
PsiModifierList modifiers = field.getModifierList();
if ("TAG".equals(field.getName()) && LintUtils.isString(field.getType()) &&
modifiers != null && modifiers.hasModifierProperty("public") &&
modifiers.hasModifierProperty("static")) {
hasTag = true;
break;
}
}
if (!hasTag) {
context.report(TAG, context.getLocation(declaration.getExtendsList()), TAG_MESSAGE);
}
}
}
private void markLeakSuspects(PsiElement element, PsiElement lambdaBody, @NonNull final JavaContext context) {
if (element instanceof PsiReferenceExpression) {
PsiReferenceExpression ref = (PsiReferenceExpression) element;
if (ref.getQualifierExpression() == null) {
PsiElement res = ref.resolve();
if (!(res instanceof PsiParameter)) {
if (!(res instanceof PsiClass)) {
boolean error = false;
if (res instanceof PsiLocalVariable) {
PsiLocalVariable lVar = (PsiLocalVariable) res;
if (!isParent(lambdaBody, lVar.getParent())) {
error = true;
}
}
if (res instanceof PsiField) {
PsiField field = (PsiField) res;
final PsiModifierList modifierList = field.getModifierList();
if (modifierList == null) {
error = true;
} else if (!modifierList.hasExplicitModifier(PsiModifier.STATIC)) {
error = true;
}
}
if (error) {
context.report(ISSUE, element, context.getNameLocation(element), "Possible leak");
}
}
}
}
}
for (PsiElement psiElement : element.getChildren()) {
markLeakSuspects(psiElement, lambdaBody, context);
}
}
@Override
public void visitClass(JavaContext context, UClass declaration) {
PsiModifierList classModifiers = declaration.getModifierList();
if (classModifiers == null || !classModifiers.hasModifierProperty("abstract")) {
// check for static build method
boolean hasBuildMethod = false;
for (PsiMethod method : declaration.getMethods()) {
if ("build".equals(method.getName()) && method.getModifierList()
.hasModifierProperty("static")) {
hasBuildMethod = true;
break;
}
}
if (!hasBuildMethod){
context.report(BUILD_OVERWRITE, context.getLocation(declaration.getExtendsList()),
BUILD_OVERWRITE_MESSAGE);
}
// check for public static String TAG
boolean hasTag = false;
for (UField field : declaration.getFields()) {
PsiModifierList modifiers = field.getModifierList();
if ("TAG".equals(field.getName()) && LintUtils.isString(field.getType()) &&
modifiers != null && modifiers.hasModifierProperty("public") &&
modifiers.hasModifierProperty("static")) {
hasTag = true;
break;
}
}
if (!hasTag) {
context.report(TAG, context.getLocation(declaration.getExtendsList()), TAG_MESSAGE);
}
}
}
@Override
public boolean isImplicitUsage(PsiElement element) {
if (!(element instanceof PsiMethod)) {
return false;
}
PsiMethod method = (PsiMethod) element;
if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
return false;
}
PsiModifierList modifiers = method.getModifierList();
return IMPLICIT_METHOD_USAGE_ANNOTATIONS
.stream()
.anyMatch(s -> modifiers.findAnnotation(s) != null);
}
/** Returns true if the method is called in generated code. */
static boolean isImplicitUsageMethod(PsiElement element) {
if (!(element instanceof PsiMethod)) {
return false;
}
PsiMethod method = (PsiMethod) element;
if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
return false;
}
PsiModifierList modifiers = method.getModifierList();
return IMPLICIT_METHOD_USAGE_ANNOTATIONS
.stream()
.anyMatch(s -> modifiers.findAnnotation(s) != null);
}
static boolean isAutoFactoryClass(PsiElement element) {
PsiClass psiClass = getPsiClass(element);
if (psiClass == null || !psiClass.hasModifierProperty(PsiModifier.PUBLIC)) {
return false;
}
PsiModifierList modifiers = psiClass.getModifierList();
return modifiers != null && modifiers.findAnnotation(AUTO_FACTORY_ANNOTATION) != null;
}
/**
* Validates whether the variable has {@code @Service} annotation declared correctly.
*
* @param variable variable to check.
* @return Look at {@link ServiceAnnotationDeclarationValidationResult}.
* @since 0.1
*/
@NotNull
public static ServiceAnnotationDeclarationValidationResult isValidServiceAnnotationDeclaration(
@NotNull PsiVariable variable )
{
PsiAnnotation serviceAnnotation = getServiceAnnotation( variable );
if( serviceAnnotation == null )
{
return invalidServiceAnnotationNotDeclared;
}
PsiModifierList modifierList = variable.getModifierList();
if( modifierList != null )
{
if( modifierList.hasModifierProperty( STATIC ) )
{
return invalidDeclaredOnStaticVariable;
}
}
// Can't be type that is injected by @Structure
if( isInjecteableByStructureAnnotation( variable ) )
{
return invalidTypeIsInjectedViaStructureAnnotation;
}
return valid;
}
@Override
public final ProblemDescriptor[] checkField( @NotNull PsiField field,
@NotNull InspectionManager manager,
boolean isOnTheFly )
{
PsiAnnotation annotationToCheck = getAnnotationToCheck( field );
if( annotationToCheck == null )
{
return null;
}
PsiModifierList modifierList = field.getModifierList();
if( modifierList != null )
{
if( modifierList.hasModifierProperty( com.intellij.psi.PsiModifier.STATIC ) )
{
String message = getInjectionAnnotationValidDeclarationMessage();
AbstractFix removeAnnotationFix = createRemoveAnnotationFix( annotationToCheck );
ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
annotationToCheck, message, removeAnnotationFix, com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING
);
return new ProblemDescriptor[]{ problemDescriptor };
}
}
return verifyAnnotationDeclaredCorrectly( field, annotationToCheck, manager );
}
@Test
public void TestIsHook() throws Exception {
PsiMethod method = mock(PsiMethod.class);
PsiModifierList list = mock(PsiModifierList.class);
PsiAnnotation annotation = mock(PsiAnnotation.class);
when(annotation.getQualifiedName()).thenReturn(BeforeStep.class.getCanonicalName());
when(list.getAnnotations()).thenReturn(new PsiAnnotation[]{annotation});
when(method.getModifierList()).thenReturn(list);
assertTrue(HookUtil.isHook(method));
}
@Test
public void TestIsHookWhenNonHookAnnotation() throws Exception {
PsiMethod method = mock(PsiMethod.class);
PsiModifierList list = mock(PsiModifierList.class);
PsiAnnotation annotation = mock(PsiAnnotation.class);
when(annotation.getQualifiedName()).thenReturn("Unequal");
when(list.getAnnotations()).thenReturn(new PsiAnnotation[]{annotation});
when(method.getModifierList()).thenReturn(list);
assertFalse(HookUtil.isHook(method));
}
@Test
public void TestIsHookWhenNoAnnotationPresent() throws Exception {
PsiMethod method = mock(PsiMethod.class);
PsiModifierList list = mock(PsiModifierList.class);
when(list.getAnnotations()).thenReturn(new PsiAnnotation[]{});
when(method.getModifierList()).thenReturn(list);
assertFalse(HookUtil.isHook(method));
}
@Override
public void transformModifiers(@NotNull PsiModifierList modifierList, @NotNull final Set<String> modifiers) {
if (modifiers.contains(PsiModifier.STATIC)) {
return; // skip static fields
}
final PsiModifierListOwner parentElement = PsiTreeUtil.getParentOfType(modifierList, PsiModifierListOwner.class, false);
if (null != parentElement) {
// FINAL
if (!PsiAnnotationSearchUtil.isAnnotatedWith(parentElement, lombok.experimental.NonFinal.class)) {
modifiers.add(PsiModifier.FINAL);
}
// PRIVATE
if (modifierList.getParent() instanceof PsiField &&
// Visibility is only changed for package private fields
hasPackagePrivateModifier(modifierList) &&
// except they are annotated with @PackagePrivate
!PsiAnnotationSearchUtil.isAnnotatedWith(parentElement, lombok.experimental.PackagePrivate.class)) {
modifiers.add(PsiModifier.PRIVATE);
// IDEA _right now_ checks if other modifiers are set, and ignores PACKAGE_LOCAL but may as well clean it up
modifiers.remove(PsiModifier.PACKAGE_LOCAL);
}
}
}
@NotNull
Collection<PsiField> filterFields(@NotNull PsiClass psiClass, PsiAnnotation psiAnnotation) {
final Collection<PsiField> psiFields = new ArrayList<>();
final boolean onlyExplicitlyIncluded = PsiAnnotationUtil.getBooleanAnnotationValue(psiAnnotation, "onlyExplicitlyIncluded", false);
for (PsiField psiField : PsiClassUtil.collectClassFieldsIntern(psiClass)) {
boolean useField = true;
PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
//Skip static fields.
useField = !modifierList.hasModifierProperty(PsiModifier.STATIC);
//Skip transient fields
useField &= !modifierList.hasModifierProperty(PsiModifier.TRANSIENT);
}
//Skip fields that start with $
useField &= !psiField.getName().startsWith(LombokUtils.LOMBOK_INTERN_FIELD_MARKER);
//Skip fields annotated with @FieldNameConstants.Exclude
useField &= !PsiAnnotationSearchUtil.isAnnotatedWith(psiField, FIELD_NAME_CONSTANTS_EXCLUDE);
if (onlyExplicitlyIncluded) {
//Only use fields annotated with @FieldNameConstants.Include, Include annotation overrides other rules
useField = PsiAnnotationSearchUtil.isAnnotatedWith(psiField, FIELD_NAME_CONSTANTS_INCLUDE);
}
if (useField) {
psiFields.add(psiField);
}
}
return psiFields;
}
protected static void addOnXAnnotations(@Nullable PsiAnnotation processedAnnotation,
@NotNull PsiModifierList modifierList,
@NotNull String onXParameterName) {
if (processedAnnotation == null) {
return;
}
Collection<String> annotationsToAdd = LombokProcessorUtil.getOnX(processedAnnotation, onXParameterName);
for (String annotation : annotationsToAdd) {
modifierList.addAnnotation(annotation);
}
}
private void addApplicableProcessors(@NotNull PsiMember psiMember, @NotNull Collection<LombokProcessorData> target) {
final PsiModifierList psiModifierList = psiMember.getModifierList();
if (null != psiModifierList) {
for (PsiAnnotation psiAnnotation : psiModifierList.getAnnotations()) {
for (Processor processor : getProcessors(psiAnnotation)) {
target.add(new LombokProcessorData(processor, psiAnnotation));
}
}
}
}
@NotNull
@Override
protected Set<String> transformModifiers(@NotNull PsiModifierList modifierList, @NotNull final Set<String> modifiers) {
// make copy of original modifiers
Set<String> result = new HashSet<>(modifiers);
// Loop through all available processors and give all of them a chance to respond
for (ModifierProcessor processor : modifierProcessors) {
if (processor.isSupported(modifierList)) {
processor.transformModifiers(modifierList, result);
}
}
return result;
}