@Override public void onInitialize(RefElement refElement) { ((RefElementImpl) refElement).setFlag(true, CAN_BE_FINAL_MASK); if (refElement instanceof RefClass) { final RefClass refClass = (RefClass) refElement; final PsiClass psiClass = refClass.getElement(); if (refClass.isEntry()) { ((RefClassImpl) refClass).setFlag(false, CAN_BE_FINAL_MASK); return; } if (refClass.isAbstract() || refClass.isAnonymous() || refClass.isInterface()) { ((RefClassImpl) refClass).setFlag(false, CAN_BE_FINAL_MASK); return; } if (!refClass.isSelfInheritor(psiClass)) { for (PsiClass psiSuperClass : psiClass.getSupers()) { if (myManager.belongsToScope(psiSuperClass)) { RefClass refSuperClass = (RefClass) myManager.getReference(psiSuperClass); if (refSuperClass != null) { ((RefClassImpl) refSuperClass).setFlag(false, CAN_BE_FINAL_MASK); } } } } } else if (refElement instanceof RefMethod) { final RefMethod refMethod = (RefMethod) refElement; final PsiElement element = refMethod.getElement(); if (element instanceof PsiMethod) { PsiMethod psiMethod = (PsiMethod) element; if (refMethod.isConstructor() || refMethod.isAbstract() || refMethod.isStatic() || PsiModifier.PRIVATE.equals(refMethod.getAccessModifier()) || refMethod.getOwnerClass().isAnonymous() || refMethod.getOwnerClass().isInterface()) { ((RefMethodImpl) refMethod).setFlag(false, CAN_BE_FINAL_MASK); } if (PsiModifier.PRIVATE.equals(refMethod.getAccessModifier()) && refMethod.getOwner() != null && !(refMethod.getOwnerClass().getOwner() instanceof RefElement)) { ((RefMethodImpl) refMethod).setFlag(false, CAN_BE_FINAL_MASK); } for (PsiMethod psiSuperMethod : psiMethod.findSuperMethods()) { if (myManager.belongsToScope(psiSuperMethod)) { RefMethod refSuperMethod = (RefMethod) myManager.getReference(psiSuperMethod); if (refSuperMethod != null) { ((RefMethodImpl) refSuperMethod).setFlag(false, CAN_BE_FINAL_MASK); } } } } } }
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { if (!CodeInsightUtilBase.preparePsiElementForWrite(descriptor.getPsiElement())) return; final PsiMethod psiMethod = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiMethod.class); if (psiMethod != null) { final ArrayList<PsiElement> psiParameters = new ArrayList<PsiElement>(); final RefElement refMethod = myManager != null ? myManager.getReference(psiMethod) : null; if (refMethod != null) { for (final RefParameter refParameter : getUnusedParameters((RefMethod) refMethod)) { psiParameters.add(refParameter.getElement()); } } else { final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); for (PsiParameter parameter : parameters) { if (Comparing.strEqual(parameter.getName(), myHint)) { psiParameters.add(parameter); break; } } } final PsiModificationTracker tracker = psiMethod.getManager().getModificationTracker(); final long startModificationCount = tracker.getModificationCount(); removeUnusedParameterViaChangeSignature(psiMethod, psiParameters); if (refMethod != null && startModificationCount != tracker.getModificationCount()) { myProcessor.ignoreElement(refMethod); } } }
@Override public void resolveEntryPoints(@NotNull final RefManager manager) { if (!myResolved) { myResolved = true; cleanup(); validateEntryPoints(); ApplicationManager.getApplication() .runReadAction( () -> { for (SmartRefElementPointer entryPoint : myPersistentEntryPoints.values()) { if (entryPoint.resolve(manager)) { RefEntity refElement = entryPoint.getRefElement(); ((RefElementImpl) refElement).setEntry(true); ((RefElementImpl) refElement).setPermanentEntry(entryPoint.isPersistent()); } } for (ClassPattern pattern : myPatterns) { final RefEntity refClass = manager.getReference(RefJavaManager.CLASS, pattern.pattern); if (refClass != null) { for (RefMethod constructor : ((RefClass) refClass).getConstructors()) { ((RefMethodImpl) constructor).setEntry(true); ((RefMethodImpl) constructor).setPermanentEntry(true); } } } }); } }
protected boolean queryExternalUsagesRequests( final RefManager manager, final GlobalJavaInspectionContext globalContext, final ProblemDescriptionsProcessor processor) { manager.iterate( new RefJavaVisitor() { @Override public void visitElement(RefEntity refEntity) { if (refEntity instanceof RefElement && processor.getDescriptions(refEntity) != null) { refEntity.accept( new RefJavaVisitor() { @Override public void visitMethod(final RefMethod refMethod) { globalContext.enqueueMethodUsagesProcessor( refMethod, new GlobalJavaInspectionContext.UsagesProcessor() { public boolean process(PsiReference psiReference) { processor.ignoreElement(refMethod); return false; } }); } }); } } }); return false; }
@Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { final PsiElement element = descriptor.getPsiElement(); final PsiModifierListOwner psiElement = PsiTreeUtil.getParentOfType(element, PsiModifierListOwner.class); if (psiElement != null) { RefJavaElement refElement = (RefJavaElement) (myManager != null ? myManager.getReference(psiElement) : null); try { if (psiElement instanceof PsiVariable) { ((PsiVariable) psiElement).normalizeDeclaration(); } final PsiModifierList modifierList = psiElement.getModifierList(); LOG.assertTrue(modifierList != null); modifierList.setModifierProperty(PsiModifier.FINAL, true); modifierList.setModifierProperty(PsiModifier.VOLATILE, false); } catch (IncorrectOperationException e) { LOG.error(e); } if (refElement != null) { RefJavaUtil.getInstance().setIsFinal(refElement, true); } } }
@Override protected boolean queryExternalUsagesRequests( @NotNull final RefManager manager, @NotNull final GlobalJavaInspectionContext context, @NotNull final ProblemDescriptionsProcessor descriptionsProcessor) { manager.iterate( new RefJavaVisitor() { @Override public void visitMethod(@NotNull final RefMethod refMethod) { if (descriptionsProcessor.getDescriptions(refMethod) != null) { // suspicious method -> need to check external usages final GlobalJavaInspectionContext.UsagesProcessor usagesProcessor = new GlobalJavaInspectionContext.UsagesProcessor() { @Override public boolean process(PsiReference psiReference) { final PsiElement psiReferenceExpression = psiReference.getElement(); if (psiReferenceExpression instanceof PsiReferenceExpression && !isInvertedMethodCall( (PsiReferenceExpression) psiReferenceExpression)) { descriptionsProcessor.ignoreElement(refMethod); } return false; } }; traverseSuperMethods(refMethod, context, usagesProcessor); } } }); return false; }
@Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { if (!FileModificationService.getInstance() .preparePsiElementForWrite(descriptor.getPsiElement())) return; final PsiModifierListOwner element = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiModifierListOwner.class); if (element != null) { RefElement refElement = null; if (myManager != null) { refElement = myManager.getReference(element); } try { if (element instanceof PsiVariable) { ((PsiVariable) element).normalizeDeclaration(); } PsiModifierList list = element.getModifierList(); LOG.assertTrue(list != null); if (element instanceof PsiMethod) { PsiMethod psiMethod = (PsiMethod) element; PsiClass containingClass = psiMethod.getContainingClass(); if (containingClass != null && containingClass.getParent() instanceof PsiFile && myHint == PsiModifier.PRIVATE && list.hasModifierProperty(PsiModifier.FINAL)) { list.setModifierProperty(PsiModifier.FINAL, false); } } list.setModifierProperty(myHint, true); if (refElement instanceof RefJavaElement) { RefJavaUtil.getInstance().setAccessModifier((RefJavaElement) refElement, myHint); } } catch (IncorrectOperationException e) { LOG.error(e); } } }
protected boolean queryExternalUsagesRequests( final RefManager manager, final GlobalJavaInspectionContext globalContext, final ProblemDescriptionsProcessor processor) { final Project project = manager.getProject(); for (RefElement entryPoint : globalContext.getEntryPointsManager(manager).getEntryPoints()) { processor.ignoreElement(entryPoint); } final PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(project); final AnalysisScope scope = manager.getScope(); manager.iterate( new RefJavaVisitor() { @Override public void visitElement(RefEntity refEntity) { if (refEntity instanceof RefMethod) { RefMethod refMethod = (RefMethod) refEntity; final PsiModifierListOwner element = refMethod.getElement(); if (element instanceof PsiMethod) { // implicit construcors are invisible PsiMethod psiMethod = (PsiMethod) element; if (!refMethod.isStatic() && !refMethod.isConstructor() && !PsiModifier.PRIVATE.equals(refMethod.getAccessModifier())) { final ArrayList<RefParameter> unusedParameters = getUnusedParameters(refMethod); if (unusedParameters.isEmpty()) return; PsiMethod[] derived = OverridingMethodsSearch.search(psiMethod, true) .toArray(PsiMethod.EMPTY_ARRAY); for (final RefParameter refParameter : unusedParameters) { if (refMethod.isAbstract() && derived.length == 0) { refParameter.parameterReferenced(false); processor.ignoreElement(refParameter); } else { int idx = refParameter.getIndex(); final boolean[] found = {false}; for (int i = 0; i < derived.length && !found[0]; i++) { if (!scope.contains(derived[i])) { final PsiParameter[] parameters = derived[i].getParameterList().getParameters(); if (parameters.length >= idx) continue; PsiParameter psiParameter = parameters[idx]; ReferencesSearch.search( psiParameter, helper.getUseScope(psiParameter), false) .forEach( new PsiReferenceProcessorAdapter( new PsiReferenceProcessor() { public boolean execute(PsiReference element) { refParameter.parameterReferenced(false); processor.ignoreElement(refParameter); found[0] = true; return false; } })); } } } } } } } } }); return false; }
@Override public void initialize(RefManager refManager) { CAN_BE_FINAL_MASK = refManager.getLastUsedMask(); }
@Override public void onReferencesBuild(RefElement refElement) { if (refElement instanceof RefClass) { final PsiClass psiClass = (PsiClass) refElement.getElement(); if (psiClass != null) { if (refElement.isEntry()) { ((RefClassImpl) refElement).setFlag(false, CAN_BE_FINAL_MASK); } PsiMethod[] psiMethods = psiClass.getMethods(); PsiField[] psiFields = psiClass.getFields(); HashSet<PsiVariable> allFields = new HashSet<PsiVariable>(); ContainerUtil.addAll(allFields, psiFields); ArrayList<PsiVariable> instanceInitializerInitializedFields = new ArrayList<PsiVariable>(); boolean hasInitializers = false; for (PsiClassInitializer initializer : psiClass.getInitializers()) { PsiCodeBlock body = initializer.getBody(); hasInitializers = true; ControlFlow flow; try { flow = ControlFlowFactory.getInstance(body.getProject()) .getControlFlow( body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false); } catch (AnalysisCanceledException e) { flow = ControlFlow.EMPTY; } Collection<PsiVariable> writtenVariables = new ArrayList<PsiVariable>(); ControlFlowUtil.getWrittenVariables(flow, 0, flow.getSize(), false, writtenVariables); for (PsiVariable psiVariable : writtenVariables) { if (allFields.contains(psiVariable)) { if (instanceInitializerInitializedFields.contains(psiVariable)) { allFields.remove(psiVariable); instanceInitializerInitializedFields.remove(psiVariable); } else { instanceInitializerInitializedFields.add(psiVariable); } } } for (PsiVariable psiVariable : writtenVariables) { if (!instanceInitializerInitializedFields.contains(psiVariable)) { allFields.remove(psiVariable); } } } for (PsiMethod psiMethod : psiMethods) { if (psiMethod.isConstructor()) { PsiCodeBlock body = psiMethod.getBody(); if (body != null) { hasInitializers = true; ControlFlow flow; try { flow = ControlFlowFactory.getInstance(body.getProject()) .getControlFlow( body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false); } catch (AnalysisCanceledException e) { flow = ControlFlow.EMPTY; } Collection<PsiVariable> writtenVariables = ControlFlowUtil.getWrittenVariables(flow, 0, flow.getSize(), false); for (PsiVariable psiVariable : writtenVariables) { if (instanceInitializerInitializedFields.contains(psiVariable)) { allFields.remove(psiVariable); instanceInitializerInitializedFields.remove(psiVariable); } } List<PsiMethod> redirectedConstructors = HighlightControlFlowUtil.getChainedConstructors(psiMethod); if (redirectedConstructors == null || redirectedConstructors.isEmpty()) { List<PsiVariable> ssaVariables = ControlFlowUtil.getSSAVariables(flow); ArrayList<PsiVariable> good = new ArrayList<PsiVariable>(ssaVariables); good.addAll(instanceInitializerInitializedFields); allFields.retainAll(good); } else { allFields.removeAll(writtenVariables); } } } } for (PsiField psiField : psiFields) { if ((!hasInitializers || !allFields.contains(psiField)) && psiField.getInitializer() == null) { final RefFieldImpl refField = (RefFieldImpl) myManager.getReference(psiField); if (refField != null) { refField.setFlag(false, CAN_BE_FINAL_MASK); } } } } } else if (refElement instanceof RefMethod) { final RefMethod refMethod = (RefMethod) refElement; if (refMethod.isEntry()) { ((RefMethodImpl) refMethod).setFlag(false, CAN_BE_FINAL_MASK); } } }
@Override protected boolean queryExternalUsagesRequests( @NotNull final RefManager manager, @NotNull final GlobalJavaInspectionContext globalContext, @NotNull final ProblemDescriptionsProcessor problemsProcessor) { for (RefElement entryPoint : globalContext.getEntryPointsManager(manager).getEntryPoints()) { problemsProcessor.ignoreElement(entryPoint); } manager.iterate( new RefJavaVisitor() { @Override public void visitElement(@NotNull RefEntity refEntity) { if (problemsProcessor.getDescriptions(refEntity) == null) return; refEntity.accept( new RefJavaVisitor() { @Override public void visitMethod(@NotNull final RefMethod refMethod) { if (!refMethod.isStatic() && !PsiModifier.PRIVATE.equals(refMethod.getAccessModifier()) && !(refMethod instanceof RefImplicitConstructor)) { globalContext.enqueueDerivedMethodsProcessor( refMethod, new GlobalJavaInspectionContext.DerivedMethodsProcessor() { @Override public boolean process(PsiMethod derivedMethod) { ((RefElementImpl) refMethod) .setFlag(false, CanBeFinalAnnotator.CAN_BE_FINAL_MASK); problemsProcessor.ignoreElement(refMethod); return false; } }); } } @Override public void visitClass(@NotNull final RefClass refClass) { if (!refClass.isAnonymous()) { globalContext.enqueueDerivedClassesProcessor( refClass, new GlobalJavaInspectionContext.DerivedClassesProcessor() { @Override public boolean process(PsiClass inheritor) { ((RefClassImpl) refClass) .setFlag(false, CanBeFinalAnnotator.CAN_BE_FINAL_MASK); problemsProcessor.ignoreElement(refClass); return false; } }); } } @Override public void visitField(@NotNull final RefField refField) { globalContext.enqueueFieldUsagesProcessor( refField, new GlobalJavaInspectionContext.UsagesProcessor() { @Override public boolean process(PsiReference psiReference) { PsiElement expression = psiReference.getElement(); if (expression instanceof PsiReferenceExpression && PsiUtil.isAccessedForWriting((PsiExpression) expression)) { ((RefFieldImpl) refField) .setFlag(false, CanBeFinalAnnotator.CAN_BE_FINAL_MASK); problemsProcessor.ignoreElement(refField); return false; } return true; } }); } }); } }); return false; }
@Override protected boolean queryExternalUsagesRequests( @NotNull final RefManager manager, @NotNull final GlobalJavaInspectionContext globalContext, @NotNull final ProblemDescriptionsProcessor processor) { final EntryPointsManager entryPointsManager = globalContext.getEntryPointsManager(manager); for (RefElement entryPoint : entryPointsManager.getEntryPoints()) { ignoreElement(processor, entryPoint); } ExtensionPoint<VisibilityExtension> point = Extensions.getRootArea().getExtensionPoint(ExtensionPoints.VISIBLITY_TOOL); for (VisibilityExtension addin : point.getExtensions()) { addin.fillIgnoreList(manager, processor); } manager.iterate( new RefJavaVisitor() { @Override public void visitElement(@NotNull final RefEntity refEntity) { if (!(refEntity instanceof RefElement)) return; if (processor.getDescriptions(refEntity) == null) return; refEntity.accept( new RefJavaVisitor() { @Override public void visitField(@NotNull final RefField refField) { if (refField.getAccessModifier() != PsiModifier.PRIVATE) { globalContext.enqueueFieldUsagesProcessor( refField, new GlobalJavaInspectionContext.UsagesProcessor() { @Override public boolean process(PsiReference psiReference) { ignoreElement(processor, refField); return false; } }); } } @Override public void visitMethod(@NotNull final RefMethod refMethod) { if (!refMethod.isExternalOverride() && refMethod.getAccessModifier() != PsiModifier.PRIVATE && !(refMethod instanceof RefImplicitConstructor)) { globalContext.enqueueDerivedMethodsProcessor( refMethod, new GlobalJavaInspectionContext.DerivedMethodsProcessor() { @Override public boolean process(PsiMethod derivedMethod) { ignoreElement(processor, refMethod); return false; } }); globalContext.enqueueMethodUsagesProcessor( refMethod, new GlobalJavaInspectionContext.UsagesProcessor() { @Override public boolean process(PsiReference psiReference) { ignoreElement(processor, refMethod); return false; } }); if (entryPointsManager.isAddNonJavaEntries()) { final RefClass ownerClass = refMethod.getOwnerClass(); if (refMethod.isConstructor() && ownerClass.getDefaultConstructor() != null) { String qualifiedName = ownerClass.getElement().getQualifiedName(); if (qualifiedName != null) { final Project project = manager.getProject(); PsiSearchHelper.SERVICE .getInstance(project) .processUsagesInNonJavaFiles( qualifiedName, new PsiNonJavaFileReferenceProcessor() { @Override public boolean process( PsiFile file, int startOffset, int endOffset) { entryPointsManager.addEntryPoint(refMethod, false); ignoreElement(processor, refMethod); return false; } }, GlobalSearchScope.projectScope(project)); } } } } } @Override public void visitClass(@NotNull final RefClass refClass) { if (!refClass.isAnonymous()) { globalContext.enqueueDerivedClassesProcessor( refClass, new GlobalJavaInspectionContext.DerivedClassesProcessor() { @Override public boolean process(PsiClass inheritor) { ignoreElement(processor, refClass); return false; } }); globalContext.enqueueClassUsagesProcessor( refClass, new GlobalJavaInspectionContext.UsagesProcessor() { @Override public boolean process(PsiReference psiReference) { ignoreElement(processor, refClass); return false; } }); } } }); } }); return false; }