/** * The parameter <code>allowIndirect</code> determines if the method should look for indirect * annotations, i.e. annotations which have themselves been annotated by the supplied annotation * name. Currently, this only allows one level of indirection and returns an array of * [base-annotation, indirect annotation] * * <p>The <code>annotationName</code> parameter is a pair of the target annotation class' fully * qualified name as a String and as a Set. This is done for performance reasons because the Set * is required by the {@link com.intellij.codeInsight.AnnotationUtil} utility class and allows to * avoid unnecessary object constructions. */ public static PsiAnnotation[] getAnnotationsFromImpl( PsiModifierListOwner owner, Pair<String, ? extends Set<String>> annotationName, boolean allowIndirect, boolean inHierarchy) { final PsiAnnotation directAnnotation = inHierarchy ? AnnotationUtil.findAnnotationInHierarchy(owner, annotationName.second) : AnnotationUtil.findAnnotation(owner, annotationName.second); if (directAnnotation != null) { return new PsiAnnotation[] {directAnnotation}; } if (allowIndirect) { final PsiAnnotation[] annotations = getAnnotations(owner, inHierarchy); for (PsiAnnotation annotation : annotations) { PsiJavaCodeReferenceElement nameReference = annotation.getNameReferenceElement(); if (nameReference == null) continue; PsiElement resolved = nameReference.resolve(); if (resolved instanceof PsiClass) { final PsiAnnotation psiAnnotation = AnnotationUtil.findAnnotationInHierarchy( (PsiModifierListOwner) resolved, annotationName.second); if (psiAnnotation != null) { return new PsiAnnotation[] {psiAnnotation, annotation}; } } } } return PsiAnnotation.EMPTY_ARRAY; }
@Override public boolean isEntryPoint(@NotNull PsiElement element) { if (!(element instanceof PsiModifierListOwner)) return false; PsiModifierListOwner owner = (PsiModifierListOwner) element; if (!ADDITIONAL_ANNOTATIONS.isEmpty() && ADDITIONAL_ANNOTATIONS.contains(Deprecated.class.getName()) && element instanceof PsiDocCommentOwner && ((PsiDocCommentOwner) element).isDeprecated()) { return true; } if (element instanceof PsiClass) { final String qualifiedName = ((PsiClass) element).getQualifiedName(); if (qualifiedName != null) { for (ClassPattern pattern : getPatterns()) { if (isAcceptedByPattern((PsiClass) element, qualifiedName, pattern, new HashSet<>())) { return true; } } } } return AnnotationUtil.checkAnnotatedUsingPatterns(owner, ADDITIONAL_ANNOTATIONS) || AnnotationUtil.checkAnnotatedUsingPatterns(owner, getAdditionalAnnotations()); }
/** @return were javadoc params used */ public static void collectAnnotationValues( final Map<String, Collection<String>> results, PsiMethod[] psiMethods, PsiClass... classes) { final Set<String> test = new HashSet<>(1); test.add(TEST_ANNOTATION_FQN); ContainerUtil.addAll(test, CONFIG_ANNOTATIONS_FQN); if (psiMethods != null) { for (final PsiMethod psiMethod : psiMethods) { ApplicationManager.getApplication() .runReadAction( () -> appendAnnotationAttributeValues( results, AnnotationUtil.findAnnotation(psiMethod, test), psiMethod)); } } else { for (final PsiClass psiClass : classes) { ApplicationManager.getApplication() .runReadAction( () -> { if (psiClass != null && hasTest(psiClass)) { appendAnnotationAttributeValues( results, AnnotationUtil.findAnnotation(psiClass, test), psiClass); PsiMethod[] methods = psiClass.getMethods(); for (PsiMethod method : methods) { if (method != null) { appendAnnotationAttributeValues( results, AnnotationUtil.findAnnotation(method, test), method); } } } }); } } }
/** * Filter the specified collection of classes to return only ones that contain any of the * specified values in the specified annotation parameter. For example, this method can be used to * return all classes that contain all tesng annotations that are in the groups 'foo' or 'bar'. */ public static Map<PsiClass, Collection<PsiMethod>> filterAnnotations( String parameter, Set<String> values, Collection<PsiClass> classes) { Map<PsiClass, Collection<PsiMethod>> results = new HashMap<>(); Set<String> test = new HashSet<>(1); test.add(TEST_ANNOTATION_FQN); ContainerUtil.addAll(test, CONFIG_ANNOTATIONS_FQN); for (PsiClass psiClass : classes) { if (isBrokenPsiClass(psiClass)) continue; PsiAnnotation annotation; try { annotation = AnnotationUtil.findAnnotation(psiClass, test); } catch (Exception e) { LOGGER.error( "Exception trying to findAnnotation on " + psiClass.getClass().getName() + ".\n\n" + e.getMessage()); annotation = null; } if (annotation != null) { if (isAnnotatedWithParameter(annotation, parameter, values)) { results.put(psiClass, new LinkedHashSet<>()); } } else { Collection<String> matches = extractAnnotationValuesFromJavaDoc(getTextJavaDoc(psiClass), parameter); for (String s : matches) { if (values.contains(s)) { results.put(psiClass, new LinkedHashSet<>()); break; } } } // we already have the class, no need to look through its methods PsiMethod[] methods = psiClass.getMethods(); for (PsiMethod method : methods) { if (method != null) { annotation = AnnotationUtil.findAnnotation(method, test); if (annotation != null) { if (isAnnotatedWithParameter(annotation, parameter, values)) { if (results.get(psiClass) == null) results.put(psiClass, new LinkedHashSet<>()); results.get(psiClass).add(method); } } else { Collection<String> matches = extractAnnotationValuesFromJavaDoc(getTextJavaDoc(psiClass), parameter); for (String s : matches) { if (values.contains(s)) { results.get(psiClass).add(method); } } } } } } return results; }
private static void annotateWithNullableStuff( final PsiModifierListOwner field, final PsiElementFactory factory, final PsiModifierListOwner listOwner) throws IncorrectOperationException { if (AnnotationUtil.isAnnotated(field, AnnotationUtil.NOT_NULL, false)) { annotate(factory, listOwner, AnnotationUtil.NOT_NULL); } else if (AnnotationUtil.isAnnotated(field, AnnotationUtil.NULLABLE, false)) { annotate(factory, listOwner, AnnotationUtil.NULLABLE); } }
@Override public void visitMethod(@NotNull PsiMethod method) { super.visitMethod(method); final PsiCodeBlock body = method.getBody(); if (body == null) { return; } if (method.getNameIdentifier() == null) { return; } final PsiMethod leastConcreteSuperMethod = getLeastConcreteSuperMethod(method); if (leastConcreteSuperMethod == null) { return; } final PsiClass objectClass = ClassUtils.findObjectClass(method); final PsiMethod[] superMethods = method.findSuperMethods(objectClass); if (superMethods.length > 0) { return; } if (ignoreEmptySuperMethods) { final PsiMethod superMethod = (PsiMethod) leastConcreteSuperMethod.getNavigationElement(); if (MethodUtils.isTrivial(superMethod, true)) { return; } } if (onlyReportWhenAnnotated) { if (!AnnotationUtil.isAnnotated(leastConcreteSuperMethod, annotations)) { return; } } if (containsSuperCall(body, leastConcreteSuperMethod)) { return; } registerMethodError(method); }
private static void deleteOverrideAnnotationIfFound(PsiMethod oMethod) { final PsiAnnotation annotation = AnnotationUtil.findAnnotation(oMethod, Override.class.getName()); if (annotation != null) { annotation.delete(); } }
private void reportNullableReturns( DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors, @NotNull PsiElement block) { final PsiMethod method = getScopeMethod(block); if (method == null || NullableStuffInspectionBase.isNullableNotInferred(method, true)) return; boolean notNullRequired = NullableNotNullManager.isNotNull(method); if (!notNullRequired && !SUGGEST_NULLABLE_ANNOTATIONS) return; PsiType returnType = method.getReturnType(); // no warnings in void lambdas, where the expression is not returned anyway if (block instanceof PsiExpression && block.getParent() instanceof PsiLambdaExpression && returnType == PsiType.VOID) return; // no warnings for Void methods, where only null can be possibly returned if (returnType == null || returnType.equalsToText(CommonClassNames.JAVA_LANG_VOID)) return; for (PsiElement statement : visitor.getProblems(NullabilityProblem.nullableReturn)) { assert statement instanceof PsiExpression; final PsiExpression expr = (PsiExpression) statement; if (!reportedAnchors.add(expr)) continue; if (notNullRequired) { final String text = isNullLiteralExpression(expr) ? InspectionsBundle.message("dataflow.message.return.null.from.notnull") : InspectionsBundle.message("dataflow.message.return.nullable.from.notnull"); holder.registerProblem(expr, text); } else if (AnnotationUtil.isAnnotatingApplicable(statement)) { final NullableNotNullManager manager = NullableNotNullManager.getInstance(expr.getProject()); final String defaultNullable = manager.getDefaultNullable(); final String presentableNullable = StringUtil.getShortName(defaultNullable); final String text = isNullLiteralExpression(expr) ? InspectionsBundle.message( "dataflow.message.return.null.from.notnullable", presentableNullable) : InspectionsBundle.message( "dataflow.message.return.nullable.from.notnullable", presentableNullable); final LocalQuickFix[] fixes = PsiTreeUtil.getParentOfType(expr, PsiMethod.class, PsiLambdaExpression.class) instanceof PsiLambdaExpression ? LocalQuickFix.EMPTY_ARRAY : new LocalQuickFix[] { new AnnotateMethodFix( defaultNullable, ArrayUtil.toStringArray(manager.getNotNulls())) { @Override public int shouldAnnotateBaseMethod( PsiMethod method, PsiMethod superMethod, Project project) { return 1; } } }; holder.registerProblem(expr, text, fixes); } } }
@Nullable protected InspectionGadgetsFix buildFix(Object... infos) { if (!AnnotationUtil.isAnnotatingApplicable((PsiElement) infos[0])) { return null; } return new DelegatingFix( new AnnotateMethodFix(AnnotationUtil.NULLABLE, AnnotationUtil.NOT_NULL)); }
public static String getConfigAnnotation(PsiMethod method) { if (method != null) { for (String fqn : CONFIG_ANNOTATIONS_FQN) { if (AnnotationUtil.isAnnotated(method, fqn, false)) return fqn; } } return null; }
@Override public boolean isAvailable( @NotNull Project project, @NotNull PsiFile file, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { if (!startElement.isValid()) return false; if (!PsiUtil.isLanguageLevel5OrHigher(startElement)) return false; final PsiModifierListOwner myModifierListOwner = (PsiModifierListOwner) startElement; return !AnnotationUtil.isAnnotated(myModifierListOwner, myAnnotation, false); }
private void makeStatic(PsiMethod member) { final PsiAnnotation overrideAnnotation = AnnotationUtil.findAnnotation(member, CommonClassNames.JAVA_LANG_OVERRIDE); if (overrideAnnotation != null) { overrideAnnotation.delete(); } setupTypeParameterList(member); // Add static modifier final PsiModifierList modifierList = member.getModifierList(); modifierList.setModifierProperty(PsiModifier.STATIC, true); modifierList.setModifierProperty(PsiModifier.FINAL, false); modifierList.setModifierProperty(PsiModifier.DEFAULT, false); }
private static void deleteOverrideAnnotationIfFound(PsiMethod oMethod) { final PsiAnnotation annotation = AnnotationUtil.findAnnotation(oMethod, CommonClassNames.JAVA_LANG_OVERRIDE); if (annotation != null) { PsiElement prev = annotation.getPrevSibling(); PsiElement next = annotation.getNextSibling(); if ((prev == null || org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.isLineFeed(prev)) && org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.isLineFeed(next)) { next.delete(); } annotation.delete(); } }
@Nullable public static List<String> findTestDataFiles(@NotNull DataContext context) { final PsiMethod method = findTargetMethod(context); if (method == null) { return null; } final String name = method.getName(); if (name.startsWith("test")) { String testDataPath = TestDataLineMarkerProvider.getTestDataBasePath(method.getContainingClass()); final TestDataReferenceCollector collector = new TestDataReferenceCollector(testDataPath, name.substring(4)); return collector.collectTestDataReferences(method); } final Location<?> location = Location.DATA_KEY.getData(context); if (location instanceof PsiMemberParameterizedLocation) { PsiClass containingClass = ((PsiMemberParameterizedLocation) location).getContainingClass(); if (containingClass == null) { containingClass = PsiTreeUtil.getParentOfType(location.getPsiElement(), PsiClass.class, false); } if (containingClass != null) { final PsiAnnotation annotation = AnnotationUtil.findAnnotationInHierarchy( containingClass, Collections.singleton(JUnitUtil.RUN_WITH)); if (annotation != null) { final PsiAnnotationMemberValue memberValue = annotation.findAttributeValue("value"); if (memberValue instanceof PsiClassObjectAccessExpression) { final PsiTypeElement operand = ((PsiClassObjectAccessExpression) memberValue).getOperand(); if (operand.getType().equalsToText(Parameterized.class.getName())) { final String testDataPath = TestDataLineMarkerProvider.getTestDataBasePath(containingClass); final String paramSetName = ((PsiMemberParameterizedLocation) location).getParamSetName(); final String baseFileName = StringUtil.trimEnd(StringUtil.trimStart(paramSetName, "["), "]"); final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(containingClass.getProject()).getFileIndex(); return TestDataGuessByExistingFilesUtil.suggestTestDataFiles( fileIndex, baseFileName, testDataPath, containingClass); } } } } } return null; }
private void checkAnnotations(Class<?> javaClass) { PsiClass psiClass = myJavaPsiFacade.findClass( javaClass.getName(), GlobalSearchScope.moduleWithLibrariesScope(myModule)); assertNotNull(psiClass); for (java.lang.reflect.Method javaMethod : javaClass.getDeclaredMethods()) { PsiMethod psiMethod = psiClass.findMethodsByName(javaMethod.getName(), false)[0]; Annotation[][] annotations = javaMethod.getParameterAnnotations(); // not-null parameters params: for (int i = 0; i < annotations.length; i++) { Annotation[] parameterAnnotations = annotations[i]; PsiParameter psiParameter = psiMethod.getParameterList().getParameters()[i]; PsiAnnotation inferredAnnotation = myInferredAnnotationsManager.findInferredAnnotation( psiParameter, AnnotationUtil.NOT_NULL); for (Annotation parameterAnnotation : parameterAnnotations) { if (parameterAnnotation.annotationType() == ExpectNotNull.class) { assertNotNull(javaMethod.toString() + " " + i, inferredAnnotation); continue params; } } assertNull(javaMethod.toString() + " " + i, inferredAnnotation); } // not-null result ExpectNotNull expectedAnnotation = javaMethod.getAnnotation(ExpectNotNull.class); PsiAnnotation actualAnnotation = myInferredAnnotationsManager.findInferredAnnotation(psiMethod, AnnotationUtil.NOT_NULL); assertEquals(javaMethod.toString(), expectedAnnotation == null, actualAnnotation == null); // contracts ExpectContract expectedContract = javaMethod.getAnnotation(ExpectContract.class); PsiAnnotation actualContractAnnotation = myInferredAnnotationsManager.findInferredAnnotation( psiMethod, ORG_JETBRAINS_ANNOTATIONS_CONTRACT); assertEquals(expectedContract == null, actualContractAnnotation == null); if (expectedContract != null) { String expectedContractValue = expectedContract.value(); String actualContractValue = AnnotationUtil.getStringAttributeValue(actualContractAnnotation, null); assertEquals(javaMethod.toString(), expectedContractValue, actualContractValue); } } }
private static boolean isConfigMethod(PsiMethod method, String[] configAnnotationsFqn) { for (String fqn : configAnnotationsFqn) { if (AnnotationUtil.isAnnotated(method, fqn, false)) return true; } if (hasDocTagsSupport) { final PsiDocComment comment = method.getDocComment(); if (comment != null) { for (String javadocTag : CONFIG_JAVADOC_TAGS) { if (comment.findTagByName(javadocTag) != null) return true; } } } return false; }
public static boolean mustBePropertyKey( @NotNull Project project, @NotNull PsiLiteralExpression expression, @NotNull Map<String, Object> annotationAttributeValues) { final PsiElement parent = expression.getParent(); if (parent instanceof PsiVariable) { final PsiAnnotation annotation = AnnotationUtil.findAnnotation((PsiVariable) parent, AnnotationUtil.PROPERTY_KEY); if (annotation != null) { return processAnnotationAttributes(annotationAttributeValues, annotation); } } return isPassedToAnnotatedParam( project, expression, AnnotationUtil.PROPERTY_KEY, annotationAttributeValues, null); }
@Override public boolean isAvailable( @NotNull final Project project, final Editor editor, @NotNull final PsiElement element) { if (!super.isAvailable(project, editor, element)) { return false; } PsiModifierListOwner owner = getContainer(element); if (owner == null || AnnotationUtil.isAnnotated(owner, getAnnotationsToRemove()[0], false)) { return false; } if (owner instanceof PsiMethod) { PsiType returnType = ((PsiMethod) owner).getReturnType(); return returnType != null && !(returnType instanceof PsiPrimitiveType); } return true; }
public static boolean isMethodParameterAnnotatedWith( final PsiMethod method, final int idx, @Nullable Collection<PsiMethod> processed, final String annFqn, @Nullable Map<String, Object> annotationAttributeValues, @Nullable final Set<PsiModifierListOwner> nonNlsTargets) { if (processed != null) { if (processed.contains(method)) return false; } else { processed = new THashSet<PsiMethod>(); } processed.add(method); final PsiParameter[] params = method.getParameterList().getParameters(); PsiParameter param; if (idx >= params.length) { if (params.length == 0) { return false; } PsiParameter lastParam = params[params.length - 1]; if (lastParam.isVarArgs()) { param = lastParam; } else { return false; } } else { param = params[idx]; } final PsiAnnotation annotation = AnnotationUtil.findAnnotation(param, annFqn); if (annotation != null) { return processAnnotationAttributes(annotationAttributeValues, annotation); } if (nonNlsTargets != null) { nonNlsTargets.add(param); } final PsiMethod[] superMethods = method.findSuperMethods(); for (PsiMethod superMethod : superMethods) { if (isMethodParameterAnnotatedWith( superMethod, idx, processed, annFqn, annotationAttributeValues, null)) return true; } return false; }
public static boolean isJUnitTestMethod(PsiMethod method) { //noinspection HardCodedStringLiteral if (AnnotationUtil.isAnnotated(method, "org.junit.Test", true)) { return true; } final PsiType returnType = method.getReturnType(); if (!PsiType.VOID.equals(returnType)) { return false; } if (!method.hasModifierProperty(PsiModifier.PUBLIC)) { return false; } @NonNls final String methodName = method.getName(); if (!methodName.startsWith("test")) { return false; } final PsiClass containingClass = method.getContainingClass(); return containingClass != null && isJUnitTestCase(containingClass); }
@Override public void visitField(@NotNull PsiField field) { if (field.hasModifierProperty(PsiModifier.STATIC)) { return; } if (field.getInitializer() != null) { return; } final PsiAnnotation annotation = AnnotationUtil.findAnnotation(field, annotationNames); if (annotation != null) { return; } if (m_ignorePrimitives) { final PsiType fieldType = field.getType(); if (ClassUtils.isPrimitive(fieldType)) { return; } } final PsiClass aClass = field.getContainingClass(); if (aClass == null) { return; } for (ImplicitUsageProvider provider : Extensions.getExtensions(ImplicitUsageProvider.EP_NAME)) { if (provider.isImplicitWrite(field)) { return; } } final UninitializedReadCollector uninitializedReadsCollector = new UninitializedReadCollector(); if (!isInitializedInInitializer(field, uninitializedReadsCollector)) { final PsiMethod[] constructors = aClass.getConstructors(); for (final PsiMethod constructor : constructors) { final PsiCodeBlock body = constructor.getBody(); uninitializedReadsCollector.blockAssignsVariable(body, field); } } final PsiExpression[] badReads = uninitializedReadsCollector.getUninitializedReads(); for (PsiExpression expression : badReads) { registerError(expression); } }
@Override public void invoke( @NotNull Project project, @NotNull PsiFile file, @Nullable("is null when called from inspection") Editor editor, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { final PsiModifierListOwner myModifierListOwner = (PsiModifierListOwner) startElement; final ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(project); final PsiModifierList modifierList = myModifierListOwner.getModifierList(); LOG.assertTrue(modifierList != null); if (modifierList.findAnnotation(myAnnotation) != null) return; final ExternalAnnotationsManager.AnnotationPlace annotationAnnotationPlace = annotationsManager.chooseAnnotationsPlace(myModifierListOwner); if (annotationAnnotationPlace == ExternalAnnotationsManager.AnnotationPlace.NOWHERE) return; if (annotationAnnotationPlace == ExternalAnnotationsManager.AnnotationPlace.EXTERNAL) { for (String fqn : myAnnotationsToRemove) { annotationsManager.deannotate(myModifierListOwner, fqn); } annotationsManager.annotateExternally(myModifierListOwner, myAnnotation, file, myPairs); } else { final PsiFile containingFile = myModifierListOwner.getContainingFile(); if (!CodeInsightUtilBase.preparePsiElementForWrite(containingFile)) return; for (String fqn : myAnnotationsToRemove) { PsiAnnotation annotation = AnnotationUtil.findAnnotation(myModifierListOwner, fqn); if (annotation != null) { annotation.delete(); } } PsiAnnotation inserted = modifierList.addAnnotation(myAnnotation); for (PsiNameValuePair pair : myPairs) { inserted.setDeclaredAttributeValue(pair.getName(), pair.getValue()); } JavaCodeStyleManager.getInstance(project).shortenClassReferences(inserted); if (containingFile != file) { UndoUtil.markPsiFileForUndo(file); } } }
public static boolean isJUnitTestCase(PsiClass aClass) { final Project project = aClass.getProject(); final GlobalSearchScope scope = GlobalSearchScope.allScope(project); final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); final PsiClass testCase = psiFacade.findClass("junit.framework.TestCase", scope); if (testCase == null) { return false; } if (aClass.isInheritor(testCase, true)) { return true; } final PsiMethod[] methods = aClass.getMethods(); for (PsiMethod method : methods) { //noinspection HardCodedStringLiteral if (AnnotationUtil.isAnnotated(method, "org.junit.Test", true)) { return true; } } return false; }
private static void reportNullableReturns( StandardDataFlowRunner runner, DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors) { for (PsiElement statement : visitor.getProblems(NullabilityProblem.nullableReturn)) { assert statement instanceof PsiExpression; final PsiExpression expr = (PsiExpression) statement; if (!reportedAnchors.add(expr)) continue; if (runner.isInNotNullMethod()) { final String text = isNullLiteralExpression(expr) ? InspectionsBundle.message("dataflow.message.return.null.from.notnull") : InspectionsBundle.message("dataflow.message.return.nullable.from.notnull"); holder.registerProblem(expr, text); } else if (AnnotationUtil.isAnnotatingApplicable(statement)) { final NullableNotNullManager manager = NullableNotNullManager.getInstance(expr.getProject()); final String defaultNullable = manager.getDefaultNullable(); final String presentableNullable = StringUtil.getShortName(defaultNullable); final String text = isNullLiteralExpression(expr) ? InspectionsBundle.message( "dataflow.message.return.null.from.notnullable", presentableNullable) : InspectionsBundle.message( "dataflow.message.return.nullable.from.notnullable", presentableNullable); holder.registerProblem( expr, text, new AnnotateMethodFix(defaultNullable, ArrayUtil.toStringArray(manager.getNotNulls())) { @Override public int shouldAnnotateBaseMethod( PsiMethod method, PsiMethod superMethod, Project project) { return 1; } }); } } }
@Nullable public static String getTestDataBasePath(PsiClass psiClass) { final PsiAnnotation annotation = AnnotationUtil.findAnnotationInHierarchy( psiClass, Collections.singleton(TEST_DATA_PATH_ANNOTATION_QUALIFIED_NAME)); if (annotation != null) { final PsiAnnotationMemberValue value = annotation.findAttributeValue(PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME); if (value instanceof PsiExpression) { final Project project = value.getProject(); final PsiConstantEvaluationHelper evaluationHelper = JavaPsiFacade.getInstance(project).getConstantEvaluationHelper(); final Object constantValue = evaluationHelper.computeConstantExpression(value, false); if (constantValue instanceof String) { String path = (String) constantValue; if (path.contains(CONTENT_ROOT_VARIABLE)) { final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); final VirtualFile file = psiClass.getContainingFile().getVirtualFile(); if (file == null) { return null; } final VirtualFile contentRoot = fileIndex.getContentRootForFile(file); if (contentRoot == null) return null; path = path.replace(CONTENT_ROOT_VARIABLE, contentRoot.getPath()); } if (path.contains(PROJECT_ROOT_VARIABLE)) { final VirtualFile baseDir = project.getBaseDir(); if (baseDir == null) { return null; } path = path.replace(PROJECT_ROOT_VARIABLE, baseDir.getPath()); } return path; } } } return null; }
private void reportNullableArgumentsPassedToNonAnnotated( DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors) { for (PsiElement expr : visitor.getProblems(NullabilityProblem.passingNullableArgumentToNonAnnotatedParameter)) { if (reportedAnchors.contains(expr)) continue; final String text = isNullLiteralExpression(expr) ? "Passing <code>null</code> argument to non annotated parameter" : "Argument <code>#ref</code> #loc might be null but passed to non annotated parameter"; LocalQuickFix[] fixes = createNPEFixes((PsiExpression) expr, (PsiExpression) expr, holder.isOnTheFly()); final PsiElement parent = expr.getParent(); if (parent instanceof PsiExpressionList) { final int idx = ArrayUtilRt.find(((PsiExpressionList) parent).getExpressions(), expr); if (idx > -1) { final PsiElement gParent = parent.getParent(); if (gParent instanceof PsiCallExpression) { final PsiMethod psiMethod = ((PsiCallExpression) gParent).resolveMethod(); if (psiMethod != null && psiMethod.getManager().isInProject(psiMethod) && AnnotationUtil.isAnnotatingApplicable(psiMethod)) { final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); if (idx < parameters.length) { final AddNullableAnnotationFix addNullableAnnotationFix = new AddNullableAnnotationFix(parameters[idx]); fixes = fixes == null ? new LocalQuickFix[] {addNullableAnnotationFix} : ArrayUtil.append(fixes, addNullableAnnotationFix); holder.registerProblem(expr, text, fixes); reportedAnchors.add(expr); } } } } } } }
public static void addSuppressAnnotation( final Project project, final Editor editor, final PsiElement container, final PsiModifierListOwner modifierOwner, final String id) throws IncorrectOperationException { PsiAnnotation annotation = AnnotationUtil.findAnnotation( modifierOwner, SuppressManager.SUPPRESS_INSPECTIONS_ANNOTATION_NAME); final PsiAnnotation newAnnotation = createNewAnnotation(project, editor, container, annotation, id); if (newAnnotation != null) { if (annotation != null && annotation.isPhysical()) { annotation.replace(newAnnotation); } else { final PsiNameValuePair[] attributes = newAnnotation.getParameterList().getAttributes(); new AddAnnotationFix( SuppressManager.SUPPRESS_INSPECTIONS_ANNOTATION_NAME, modifierOwner, attributes) .invoke(project, editor, container.getContainingFile()); } } }
static AllowedValues getAllowedValues( @NotNull PsiModifierListOwner element, PsiType type, Set<PsiClass> visited) { PsiAnnotation[] annotations = AnnotationUtil.getAllAnnotations(element, true, null); for (PsiAnnotation annotation : annotations) { AllowedValues values; if (type != null && MagicConstant.class.getName().equals(annotation.getQualifiedName())) { // PsiAnnotation magic = AnnotationUtil.findAnnotationInHierarchy(element, // Collections.singleton(MagicConstant.class.getName())); values = getAllowedValuesFromMagic(element, type, annotation); if (values != null) return values; } PsiJavaCodeReferenceElement ref = annotation.getNameReferenceElement(); PsiElement resolved = ref == null ? null : ref.resolve(); if (!(resolved instanceof PsiClass) || !((PsiClass) resolved).isAnnotationType()) continue; PsiClass aClass = (PsiClass) resolved; if (visited == null) visited = new THashSet<PsiClass>(); if (!visited.add(aClass)) continue; values = getAllowedValues(aClass, type, visited); if (values != null) return values; } return parseBeanInfo(element); }
@Override public void visitLiteralExpression(@NotNull PsiLiteralExpression value) { super.visitLiteralExpression(value); final String text = value.getText(); if (!PsiKeyword.NULL.equals(text)) { return; } PsiElement parent = value.getParent(); while (parent instanceof PsiParenthesizedExpression || parent instanceof PsiConditionalExpression || parent instanceof PsiTypeCastExpression) { parent = parent.getParent(); } if (parent == null || !(parent instanceof PsiReturnStatement)) { return; } final PsiMethod method = PsiTreeUtil.getParentOfType(value, PsiMethod.class); if (method == null) { return; } final PsiType returnType = method.getReturnType(); if (returnType == null) { return; } final boolean isArray = returnType.getArrayDimensions() > 0; if (AnnotationUtil.isAnnotated(method, AnnotationUtil.NULLABLE, false)) { return; } if (m_reportCollectionMethods && CollectionUtils.isCollectionClassOrInterface(returnType)) { registerError(value, value); } else if (m_reportArrayMethods && isArray) { registerError(value, value); } else if (m_reportObjectMethods && !isArray) { registerError(value, value); } }
private static AllowedValues parseBeanInfo(@NotNull PsiModifierListOwner owner) { PsiMethod method = null; if (owner instanceof PsiParameter) { PsiParameter parameter = (PsiParameter) owner; PsiElement scope = parameter.getDeclarationScope(); if (!(scope instanceof PsiMethod)) return null; PsiElement nav = scope.getNavigationElement(); if (!(nav instanceof PsiMethod)) return null; method = (PsiMethod) nav; if (method.isConstructor()) { // not a property, try the @ConstructorProperties({"prop"}) PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, "java.beans.ConstructorProperties"); if (annotation == null) return null; PsiAnnotationMemberValue value = annotation.findAttributeValue("value"); if (!(value instanceof PsiArrayInitializerMemberValue)) return null; PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue) value).getInitializers(); PsiElement parent = parameter.getParent(); if (!(parent instanceof PsiParameterList)) return null; int index = ((PsiParameterList) parent).getParameterIndex(parameter); if (index >= initializers.length) return null; PsiAnnotationMemberValue initializer = initializers[index]; if (!(initializer instanceof PsiLiteralExpression)) return null; Object val = ((PsiLiteralExpression) initializer).getValue(); if (!(val instanceof String)) return null; PsiMethod setter = PropertyUtil.findPropertySetter( method.getContainingClass(), (String) val, false, false); if (setter == null) return null; // try the @beaninfo of the corresponding setter method = (PsiMethod) setter.getNavigationElement(); } } else if (owner instanceof PsiMethod) { PsiElement nav = owner.getNavigationElement(); if (!(nav instanceof PsiMethod)) return null; method = (PsiMethod) nav; } if (method == null) return null; PsiClass aClass = method.getContainingClass(); if (aClass == null) return null; if (PropertyUtil.isSimplePropertyGetter(method)) { List<PsiMethod> setters = PropertyUtil.getSetters(aClass, PropertyUtil.getPropertyNameByGetter(method)); if (setters.size() != 1) return null; method = setters.get(0); } if (!PropertyUtil.isSimplePropertySetter(method)) return null; PsiDocComment doc = method.getDocComment(); if (doc == null) return null; PsiDocTag beaninfo = doc.findTagByName("beaninfo"); if (beaninfo == null) return null; String data = StringUtil.join( beaninfo.getDataElements(), new Function<PsiElement, String>() { @Override public String fun(PsiElement element) { return element.getText(); } }, "\n"); int enumIndex = StringUtil.indexOfSubstringEnd(data, "enum:"); if (enumIndex == -1) return null; data = data.substring(enumIndex); int colon = data.indexOf(":"); int last = colon == -1 ? data.length() : data.substring(0, colon).lastIndexOf("\n"); data = data.substring(0, last); List<PsiAnnotationMemberValue> values = new ArrayList<PsiAnnotationMemberValue>(); for (String line : StringUtil.splitByLines(data)) { List<String> words = StringUtil.split(line, " ", true, true); if (words.size() != 2) continue; String ref = words.get(1); PsiExpression constRef = JavaPsiFacade.getElementFactory(aClass.getProject()) .createExpressionFromText(ref, aClass); if (!(constRef instanceof PsiReferenceExpression)) continue; PsiReferenceExpression expr = (PsiReferenceExpression) constRef; values.add(expr); } if (values.isEmpty()) return null; PsiAnnotationMemberValue[] array = values.toArray(new PsiAnnotationMemberValue[values.size()]); return new AllowedValues(array, false); }