boolean (@NotNull InspectionManager manager, @NotNull GlobalInspectionContext globalContext, @NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor) { checkForReachableRefs(globalContext); int phase = Objects.requireNonNull(globalContext.getUserData(PHASE_KEY)); Set<RefElement> processedSuspicious = globalContext.getUserData(PROCESSED_SUSPICIOUS_ELEMENTS_KEY); boolean firstPhase = phase == 1; RefFilter filter = firstPhase ? new StrictUnreferencedFilter(this, globalContext) : new RefUnreachableFilter(this, globalContext); LOG.assertTrue(processedSuspicious != null, "phase: " + phase); boolean[] requestAdded = {false}; globalContext.getRefManager().iterate(new RefJavaVisitor() { @Override public void visitField(@NotNull RefField refField) { if (!filter.accepts(refField) || processedSuspicious.contains(refField)) { return; } processedSuspicious.add(refField); UField uField = refField.getUastElement(); if (uField != null && isSerializationImplicitlyUsedField(uField)) { getEntryPointsManager(globalContext).addEntryPoint(refField, false); } else { globalContext.getExtension(GlobalJavaInspectionContext.CONTEXT).enqueueFieldUsagesProcessor(refField, psiReference -> { getEntryPointsManager(globalContext).addEntryPoint(refField, false); return false; }); requestAdded[0] = true; } } @Override public void visitMethod(@NotNull RefMethod refMethod) { if (!filter.accepts(refMethod) || processedSuspicious.contains(refMethod)) { return; } processedSuspicious.add(refMethod); if (refMethod instanceof RefImplicitConstructor ctor) { RefClass ownerClass = ctor.getOwnerClass(); doVisitClass(ownerClass); return; } if (refMethod.isConstructor()) { RefClass ownerClass = refMethod.getOwnerClass(); if (ownerClass != null) { queryQualifiedNameUsages(ownerClass); } } UMethod uMethod = refMethod.getUastElement(); if (uMethod != null && (isSerializablePatternMethod(uMethod, refMethod.getOwnerClass()) || // todo this method potentially leads to INRE. Perhaps, it should be reconsidered/deleted (IJ-CR-5556) belongsToRepeatableAnnotationContainer(uMethod, refMethod.getOwnerClass()))) { getEntryPointsManager(globalContext).addEntryPoint(refMethod, false); } else if (!refMethod.isExternalOverride() && !PsiModifier.PRIVATE.equals(refMethod.getAccessModifier())) { processedSuspicious.addAll(refMethod.getDerivedMethods()); enqueueMethodUsages(globalContext, refMethod); requestAdded[0] = true; } } @Override public void visitClass(@NotNull RefClass refClass) { if (!filter.accepts(refClass) || processedSuspicious.contains(refClass)) { return; } doVisitClass(refClass); } private void doVisitClass(@NotNull RefClass refClass) { if (!refClass.isAnonymous()) { processedSuspicious.add(refClass); globalContext.getExtension(GlobalJavaInspectionContext.CONTEXT).enqueueDerivedClassesProcessor(refClass, inheritor -> { getEntryPointsManager(globalContext).addEntryPoint(refClass, false); return false; }); globalContext.getExtension(GlobalJavaInspectionContext.CONTEXT).enqueueClassUsagesProcessor(refClass, psiReference -> { getEntryPointsManager(globalContext).addEntryPoint(refClass, false); return false; }); queryQualifiedNameUsages(refClass); requestAdded[0] = true; } } void queryQualifiedNameUsages(@NotNull RefClass refClass) { if (firstPhase && isAddNonJavaUsedEnabled()) { globalContext.getExtension(GlobalJavaInspectionContext.CONTEXT).enqueueQualifiedNameOccurrencesProcessor(refClass, () -> { EntryPointsManager entryPointsManager = getEntryPointsManager(globalContext); entryPointsManager.addEntryPoint(refClass, false); for (RefMethod constructor : refClass.getConstructors()) { entryPointsManager.addEntryPoint(constructor, false); } }); //references from java-like are already in graph, or //they would be checked during GlobalJavaInspectionContextImpl.performPostRunActivities for (RefElement element : refClass.getInReferences()) { if (!(element instanceof RefJavaElement)) { getEntryPointsManager(globalContext).addEntryPoint(refClass, false); } } requestAdded[0] = true; } } }); if (!requestAdded[0]) { if (phase == 2) { globalContext.putUserData(PROCESSED_SUSPICIOUS_ELEMENTS_KEY, null); return false; } else { globalContext.putUserData(PHASE_KEY, 2); } } return true; }