@Override public boolean isMemberEnabled(MemberInfo member) { final PsiClass currentSuperClass = getSuperClass(); if (currentSuperClass == null) return true; if (myMemberInfoStorage.getDuplicatedMemberInfos(currentSuperClass).contains(member)) return false; if (myMemberInfoStorage.getExtending(currentSuperClass).contains(member.getMember())) return false; final boolean isInterface = currentSuperClass.isInterface(); if (!isInterface) return true; PsiElement element = member.getMember(); if (element instanceof PsiClass && ((PsiClass) element).isInterface()) return true; if (element instanceof PsiField) { return ((PsiModifierListOwner) element).hasModifierProperty(PsiModifier.STATIC); } if (element instanceof PsiMethod) { final PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor( currentSuperClass, myClass, PsiSubstitutor.EMPTY); final MethodSignature signature = ((PsiMethod) element).getSignature(superSubstitutor); final PsiMethod superClassMethod = MethodSignatureUtil.findMethodBySignature(currentSuperClass, signature, false); if (superClassMethod != null && !PsiUtil.isLanguageLevel8OrHigher(currentSuperClass)) return false; return !((PsiModifierListOwner) element).hasModifierProperty(PsiModifier.STATIC) || PsiUtil.isLanguageLevel8OrHigher(currentSuperClass); } return true; }
private static void makeVariableFinalIfNeeded( InsertionContext context, @Nullable PsiReferenceExpression ref) { if (!Registry.is("java.completion.make.outer.variables.final") || ref == null || PsiUtil.isLanguageLevel8OrHigher(ref) || JspPsiUtil.isInJspFile(ref)) { return; } PsiElement target = ref.resolve(); if (target instanceof PsiLocalVariable || target instanceof PsiParameter) { PsiClass placeClass = PsiTreeUtil.findElementOfClassAtOffset( context.getFile(), context.getTailOffset() - 1, PsiClass.class, false); if (placeClass != null && !PsiTreeUtil.isAncestor(placeClass, target, true) && !HighlightControlFlowUtil.isReassigned( (PsiVariable) target, new HashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>())) { PsiModifierList modifierList = ((PsiVariable) target).getModifierList(); if (modifierList != null) { modifierList.setModifierProperty(PsiModifier.FINAL, true); } } } }
@Override public boolean isAbstractEnabled(MemberInfo member) { PsiClass currentSuperClass = getSuperClass(); if (currentSuperClass == null || !currentSuperClass.isInterface()) return true; if (PsiUtil.isLanguageLevel8OrHigher(currentSuperClass)) { return true; } return false; }
@NotNull @Override public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { if (!PsiUtil.isLanguageLevel8OrHigher(holder.getFile())) { return PsiElementVisitor.EMPTY_VISITOR; } return new PsiElementVisitor() { @Override public void visitElement(PsiElement element) { if (element instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) element; String qName = methodCallExpression.getMethodExpression().getQualifiedName(); if (qName == null) { return; } qName = StringUtil.getShortName(qName); final Collection<StaticPseudoFunctionalStyleMethodOptions.PipelineElement> handlerInfos = myOptions.findElementsByMethodName(qName); if (handlerInfos.isEmpty()) { return; } final PsiMethod method = methodCallExpression.resolveMethod(); if (method == null) { return; } final PsiClass aClass = method.getContainingClass(); if (aClass == null) { return; } final String classQualifiedName = aClass.getQualifiedName(); if (classQualifiedName == null) { return; } StaticPseudoFunctionalStyleMethodOptions.PipelineElement suitableHandler = null; for (StaticPseudoFunctionalStyleMethodOptions.PipelineElement h : handlerInfos) { if (h.getHandlerClass().equals(classQualifiedName)) { suitableHandler = h; break; } } if (suitableHandler == null) { return; } final PseudoLambdaReplaceTemplate.ValidationInfo validationInfo = suitableHandler.getTemplate().validate(methodCallExpression); if (validationInfo != null) { holder.registerProblem( methodCallExpression.getMethodExpression(), "Pseudo functional style code", new ReplacePseudoLambdaWithLambda(suitableHandler)); } } } }; }
@NotNull public static SearchScope getMemberUseScope(@NotNull PsiMember member) { PsiFile file = member.getContainingFile(); PsiElement topElement = file == null ? member : file; Project project = topElement.getProject(); final GlobalSearchScope maximalUseScope = ResolveScopeManager.getInstance(project).getUseScope(topElement); if (isInServerPage(file)) return maximalUseScope; PsiClass aClass = member.getContainingClass(); if (aClass instanceof PsiAnonymousClass && !(aClass instanceof PsiEnumConstantInitializer && member instanceof PsiMethod && member.hasModifierProperty(PsiModifier.PUBLIC) && ((PsiMethod) member).findSuperMethods().length > 0)) { // member from anonymous class can be called from outside the class PsiElement methodCallExpr = PsiUtil.isLanguageLevel8OrHigher(aClass) ? PsiTreeUtil.getTopmostParentOfType(aClass, PsiStatement.class) : PsiTreeUtil.getParentOfType(aClass, PsiMethodCallExpression.class); return new LocalSearchScope(methodCallExpr != null ? methodCallExpr : aClass); } PsiModifierList modifierList = member.getModifierList(); int accessLevel = modifierList == null ? PsiUtil.ACCESS_LEVEL_PUBLIC : PsiUtil.getAccessLevel(modifierList); if (accessLevel == PsiUtil.ACCESS_LEVEL_PUBLIC || accessLevel == PsiUtil.ACCESS_LEVEL_PROTECTED) { return maximalUseScope; // class use scope doesn't matter, since another very visible class // can inherit from aClass } if (accessLevel == PsiUtil.ACCESS_LEVEL_PRIVATE) { PsiClass topClass = PsiUtil.getTopLevelClass(member); return topClass != null ? new LocalSearchScope(topClass) : file == null ? maximalUseScope : new LocalSearchScope(file); } if (file instanceof PsiJavaFile) { PsiPackage aPackage = JavaPsiFacade.getInstance(project).findPackage(((PsiJavaFile) file).getPackageName()); if (aPackage != null) { SearchScope scope = PackageScope.packageScope(aPackage, false); return scope.intersectWith(maximalUseScope); } } return maximalUseScope; }
public void fillCompletions( CompletionParameters parameters, final Consumer<LookupElement> result) { final PsiElement position = parameters.getPosition(); if (PsiTreeUtil.getParentOfType(position, PsiComment.class, false) != null) { return; } PsiStatement statement = PsiTreeUtil.getParentOfType(position, PsiExpressionStatement.class); if (statement == null) { statement = PsiTreeUtil.getParentOfType(position, PsiDeclarationStatement.class); } PsiElement prevLeaf = PsiTreeUtil.prevVisibleLeaf(position); if (statement != null && statement.getTextRange().getStartOffset() == position.getTextRange().getStartOffset()) { if (!psiElement() .withSuperParent(2, PsiSwitchStatement.class) .afterLeaf("{") .accepts(statement)) { PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(prevLeaf, PsiTryStatement.class); if (tryStatement == null || tryStatement.getCatchSections().length > 0 || tryStatement.getFinallyBlock() != null) { result.consume( new OverrideableSpace( createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD)); } } } if (isStatementPosition(position)) { if (PsiTreeUtil.getParentOfType(position, PsiSwitchStatement.class, false, PsiMember.class) != null) { result.consume( new OverrideableSpace(createKeyword(position, PsiKeyword.CASE), TailType.INSERT_SPACE)); result.consume( new OverrideableSpace( createKeyword(position, PsiKeyword.DEFAULT), TailType.CASE_COLON)); if (START_SWITCH.accepts(position)) { return; } } addBreakContinue(result, position); addStatementKeywords(result, position); } if (SUPER_OR_THIS_PATTERN.accepts(position)) { final boolean afterDot = AFTER_DOT.accepts(position); final boolean insideQualifierClass = isInsideQualifierClass(position); final boolean insideInheritorClass = PsiUtil.isLanguageLevel8OrHigher(position) && isInsideInheritorClass(position); if (!afterDot || insideQualifierClass || insideInheritorClass) { if (!afterDot || insideQualifierClass) { result.consume(createKeyword(position, PsiKeyword.THIS)); } final LookupItem superItem = (LookupItem) createKeyword(position, PsiKeyword.SUPER); if (psiElement() .afterLeaf(psiElement().withText("{").withSuperParent(2, psiMethod().constructor(true))) .accepts(position)) { final PsiMethod method = PsiTreeUtil.getParentOfType(position, PsiMethod.class, false, PsiClass.class); assert method != null; final boolean hasParams = superConstructorHasParameters(method); superItem.setInsertHandler( new ParenthesesInsertHandler<LookupElement>() { @Override protected boolean placeCaretInsideParentheses( InsertionContext context, LookupElement item) { return hasParams; } @Override public void handleInsert(InsertionContext context, LookupElement item) { super.handleInsert(context, item); TailType.insertChar(context.getEditor(), context.getTailOffset(), ';'); } }); } result.consume(superItem); } } if (isExpressionPosition(position)) { if (PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) == null) { result.consume( TailTypeDecorator.withTail( createKeyword(position, PsiKeyword.NEW), TailType.INSERT_SPACE)); result.consume(createKeyword(position, PsiKeyword.NULL)); } if (mayExpectBoolean(parameters)) { result.consume(createKeyword(position, PsiKeyword.TRUE)); result.consume(createKeyword(position, PsiKeyword.FALSE)); } } PsiFile file = position.getContainingFile(); if (!(file instanceof PsiExpressionCodeFragment) && !(file instanceof PsiJavaCodeReferenceCodeFragment) && !(file instanceof PsiTypeCodeFragment)) { if (prevLeaf == null) { result.consume( new OverrideableSpace( createKeyword(position, PsiKeyword.PACKAGE), TailType.HUMBLE_SPACE_BEFORE_WORD)); result.consume( new OverrideableSpace( createKeyword(position, PsiKeyword.IMPORT), TailType.HUMBLE_SPACE_BEFORE_WORD)); } else if (END_OF_BLOCK.getValue().isAcceptable(position, position) && PsiTreeUtil.getParentOfType(position, PsiMember.class) == null) { result.consume( new OverrideableSpace( createKeyword(position, PsiKeyword.IMPORT), TailType.HUMBLE_SPACE_BEFORE_WORD)); } } if ((isInsideParameterList(position) || isAtResourceVariableStart(position) || isAtCatchVariableStart(position)) && !psiElement().afterLeaf(PsiKeyword.FINAL).accepts(position) && !AFTER_DOT.accepts(position)) { result.consume( TailTypeDecorator.withTail( createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD)); } if (isInstanceofPlace(position)) { result.consume( LookupElementDecorator.withInsertHandler( createKeyword(position, PsiKeyword.INSTANCEOF), new InsertHandler<LookupElementDecorator<LookupElement>>() { @Override public void handleInsert( InsertionContext context, LookupElementDecorator<LookupElement> item) { TailType tailType = TailType.HUMBLE_SPACE_BEFORE_WORD; if (tailType.isApplicable(context)) { tailType.processTail(context.getEditor(), context.getTailOffset()); } if ('!' == context.getCompletionChar()) { context.setAddCompletionChar(false); context.commitDocument(); PsiInstanceOfExpression expr = PsiTreeUtil.findElementOfClassAtOffset( context.getFile(), context.getStartOffset(), PsiInstanceOfExpression.class, false); if (expr != null) { String space = context.getCodeStyleSettings().SPACE_WITHIN_PARENTHESES ? " " : ""; context .getDocument() .insertString(expr.getTextRange().getStartOffset(), "!(" + space); context.getDocument().insertString(context.getTailOffset(), space + ")"); } } } })); } if (isSuitableForClass(position)) { for (String s : ModifierChooser.getKeywords(position)) { result.consume( new OverrideableSpace(createKeyword(position, s), TailType.HUMBLE_SPACE_BEFORE_WORD)); } result.consume( new OverrideableSpace( createKeyword(position, PsiKeyword.CLASS), TailType.HUMBLE_SPACE_BEFORE_WORD)); if (PsiTreeUtil.getParentOfType(position, PsiCodeBlock.class, true, PsiMember.class) == null) { result.consume( new OverrideableSpace( createKeyword(position, PsiKeyword.INTERFACE), TailType.HUMBLE_SPACE_BEFORE_WORD)); if (PsiUtil.getLanguageLevel(position).isAtLeast(LanguageLevel.JDK_1_5)) { result.consume( new OverrideableSpace( createKeyword(position, PsiKeyword.ENUM), TailType.INSERT_SPACE)); } } } addPrimitiveTypes(result, position); if (isAfterTypeDot(position)) { result.consume(createKeyword(position, PsiKeyword.CLASS)); } addUnfinishedMethodTypeParameters(position, result); if (JavaMemberNameCompletionContributor.INSIDE_TYPE_PARAMS_PATTERN.accepts(position)) { result.consume( new OverrideableSpace( createKeyword(position, PsiKeyword.EXTENDS), TailType.HUMBLE_SPACE_BEFORE_WORD)); result.consume( new OverrideableSpace( createKeyword(position, PsiKeyword.SUPER), TailType.HUMBLE_SPACE_BEFORE_WORD)); } }
static HighlightInfo checkDuplicateAnnotations(@NotNull PsiAnnotation annotationToCheck) { PsiAnnotationOwner owner = annotationToCheck.getOwner(); if (owner == null) return null; PsiJavaCodeReferenceElement element = annotationToCheck.getNameReferenceElement(); if (element == null) return null; PsiElement resolved = element.resolve(); if (!(resolved instanceof PsiClass)) return null; PsiClass annotationType = (PsiClass) resolved; PsiClass contained = contained(annotationType); String containedElementFQN = contained == null ? null : contained.getQualifiedName(); if (containedElementFQN != null) { PsiClass container = annotationType; String containerName = container.getQualifiedName(); if (isAnnotationRepeatedTwice(owner, containedElementFQN)) { String description = JavaErrorMessages.message("annotation.container.wrong.place", containerName); return annotationError(annotationToCheck, description); } } else if (isAnnotationRepeatedTwice(owner, annotationType.getQualifiedName())) { if (!PsiUtil.isLanguageLevel8OrHigher(annotationToCheck)) { String description = JavaErrorMessages.message("annotation.duplicate.annotation"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(element) .descriptionAndTooltip(description) .create(); } PsiAnnotation metaAnno = PsiImplUtil.findAnnotation( annotationType.getModifierList(), CommonClassNames.JAVA_LANG_ANNOTATION_REPEATABLE); if (metaAnno == null) { String explanation = JavaErrorMessages.message( "annotation.non.repeatable", annotationType.getQualifiedName()); String description = JavaErrorMessages.message("annotation.duplicate.explained", explanation); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(element) .descriptionAndTooltip(description) .create(); } String explanation = doCheckRepeatableAnnotation(metaAnno); if (explanation != null) { String description = JavaErrorMessages.message("annotation.duplicate.explained", explanation); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(element) .descriptionAndTooltip(description) .create(); } PsiClass container = getRepeatableContainer(metaAnno); if (container != null) { PsiAnnotation.TargetType[] targets = PsiImplUtil.getTargetsForLocation(owner); PsiAnnotation.TargetType applicable = PsiImplUtil.findApplicableTarget(container, targets); if (applicable == null) { String target = JavaErrorMessages.message("annotation.target." + targets[0]); String message = JavaErrorMessages.message( "annotation.container.not.applicable", container.getName(), target); return annotationError(annotationToCheck, message); } } } for (PsiAnnotation annotation : owner.getAnnotations()) { if (annotation == annotationToCheck) continue; PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement(); if (nameRef == null) continue; PsiElement aClass = nameRef.resolve(); if (!resolved.equals(aClass)) continue; } return null; }
private void doMoveMethod(PsiSubstitutor substitutor, MemberInfo info) { PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject); PsiMethod method = (PsiMethod) info.getMember(); PsiMethod sibling = method; PsiMethod anchor = null; while (sibling != null) { sibling = PsiTreeUtil.getNextSiblingOfType(sibling, PsiMethod.class); if (sibling != null) { anchor = MethodSignatureUtil.findMethodInSuperClassBySignatureInDerived( method.getContainingClass(), myTargetSuperClass, sibling.getSignature(PsiSubstitutor.EMPTY), false); if (anchor != null) { break; } } } PsiMethod methodCopy = (PsiMethod) method.copy(); Language language = myTargetSuperClass.getLanguage(); final PsiMethod superClassMethod = myTargetSuperClass.findMethodBySignature(methodCopy, false); if (superClassMethod != null && superClassMethod.findDeepestSuperMethods().length == 0 || method.findSuperMethods(myTargetSuperClass).length == 0) { deleteOverrideAnnotationIfFound(methodCopy); } boolean isOriginalMethodAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT) || method.hasModifierProperty(PsiModifier.DEFAULT); boolean isOriginalMethodPrototype = method instanceof HaxeFunctionPrototypeDeclarationWithAttributes; if (myIsTargetInterface || info.isToAbstract()) { ChangeContextUtil.clearContextInfo(method); if (!info.isToAbstract() && !method.hasModifierProperty(PsiModifier.ABSTRACT) && PsiUtil.isLanguageLevel8OrHigher(myTargetSuperClass)) { // pull as default RefactoringUtil.makeMethodDefault(methodCopy); isOriginalMethodAbstract = true; } else { RefactoringUtil.makeMethodAbstract(myTargetSuperClass, methodCopy); } RefactoringUtil.replaceMovedMemberTypeParameters( methodCopy, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory); myJavaDocPolicy.processCopiedJavaDoc( methodCopy.getDocComment(), method.getDocComment(), isOriginalMethodAbstract); final PsiMember movedElement; if (superClassMethod != null && superClassMethod.hasModifierProperty(PsiModifier.ABSTRACT)) { movedElement = (PsiMember) superClassMethod.replace(convertMethodToLanguage(methodCopy, language)); } else { methodCopy = HaxeElementGenerator.createFunctionPrototypeDeclarationWithAttributes( myProject, methodCopy.getText().trim() + ";"); movedElement = anchor != null ? (PsiMember) myTargetSuperClass.addBefore(methodCopy, anchor) : (PsiMember) myTargetSuperClass.addBefore(methodCopy, myTargetSuperClass.getRBrace()); reformat(movedElement); } CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(method.getProject()); if (styleSettings.INSERT_OVERRIDE_ANNOTATION) { if (PsiUtil.isLanguageLevel5OrHigher(mySourceClass) && !myIsTargetInterface || PsiUtil.isLanguageLevel6OrHigher(mySourceClass)) { new AddAnnotationFix(Override.class.getName(), method) .invoke(method.getProject(), null, mySourceClass.getContainingFile()); } } if (!PsiUtil.isLanguageLevel6OrHigher(mySourceClass) && myIsTargetInterface) { if (isOriginalMethodAbstract) { for (PsiMethod oMethod : OverridingMethodsSearch.search(method)) { deleteOverrideAnnotationIfFound(oMethod); } } deleteOverrideAnnotationIfFound(method); } myMembersAfterMove.add(movedElement); // if (isOriginalMethodAbstract) { method.delete(); // } } else { if (isOriginalMethodAbstract) { PsiUtil.setModifierProperty(myTargetSuperClass, PsiModifier.ABSTRACT, true); } RefactoringUtil.replaceMovedMemberTypeParameters( methodCopy, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory); fixReferencesToStatic(methodCopy); if (superClassMethod != null && superClassMethod.hasModifierProperty(PsiModifier.ABSTRACT)) { superClassMethod.replace(convertMethodToLanguage(methodCopy, language)); } else { final PsiMember movedElement = anchor != null ? (PsiMember) myTargetSuperClass.addBefore( convertMethodToLanguage(methodCopy, language), anchor) : (PsiMember) myTargetSuperClass.addBefore( convertMethodToLanguage(methodCopy, language), myTargetSuperClass.getRBrace()); reformat(movedElement); myMembersAfterMove.add(movedElement); } method.delete(); } }
@NotNull @Override public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { if (!PsiUtil.isLanguageLevel8OrHigher(holder.getFile())) { return PsiElementVisitor.EMPTY_VISITOR; } return new JavaElementVisitor() { private final AtomicNotNullLazyValue<Map<String, PsiClass>> myGuavaClassConversions = new AtomicNotNullLazyValue<Map<String, PsiClass>>() { @NotNull @Override protected Map<String, PsiClass> compute() { Map<String, PsiClass> map = new HashMap<String, PsiClass>(); for (TypeConversionRule rule : TypeConversionRule.EP_NAME.getExtensions()) { if (rule instanceof BaseGuavaTypeConversionRule) { final String fromClass = ((BaseGuavaTypeConversionRule) rule).ruleFromClass(); final String toClass = ((BaseGuavaTypeConversionRule) rule).ruleToClass(); final Project project = holder.getProject(); final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project); final PsiClass targetClass = javaPsiFacade.findClass(toClass, GlobalSearchScope.allScope(project)); if (targetClass != null) { map.put(fromClass, targetClass); } } } return map; } }; @Override public void visitVariable(PsiVariable variable) { final PsiType type = variable.getType(); if (type instanceof PsiClassType) { final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType) type).resolveGenerics(); final PsiClass psiClass = resolveResult.getElement(); if (psiClass != null) { final String qName = psiClass.getQualifiedName(); final PsiClass targetClass = myGuavaClassConversions.getValue().get(qName); if (targetClass != null) { final VariableTypeFix fix = TypeMigrationVariableTypeFixProvider.createTypeMigrationFix( variable, addTypeParameters(type, resolveResult, targetClass)); holder.registerProblem(variable, PROBLEM_DESCRIPTION_FOR_VARIABLE, fix); } } } } private PsiClassType addTypeParameters( PsiType currentType, PsiClassType.ClassResolveResult currentTypeResolveResult, PsiClass targetClass) { final Map<PsiTypeParameter, PsiType> substitutionMap = currentTypeResolveResult.getSubstitutor().getSubstitutionMap(); final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(holder.getProject()); if (substitutionMap.size() == 1) { return elementFactory.createType( targetClass, ContainerUtil.getFirstItem(substitutionMap.values())); } else { LOG.assertTrue(substitutionMap.size() == 2); LOG.assertTrue( GuavaFunctionConversionRule.JAVA_UTIL_FUNCTION_FUNCTION.equals( targetClass.getQualifiedName())); final PsiType returnType = LambdaUtil.getFunctionalInterfaceReturnType(currentType); final List<PsiType> types = new ArrayList<PsiType>(substitutionMap.values()); types.remove(returnType); final PsiType parameterType = types.get(0); return elementFactory.createType(targetClass, parameterType, returnType); } } }; }
@NotNull @Override public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { if (!PsiUtil.isLanguageLevel8OrHigher(holder.getFile())) { return PsiElementVisitor.EMPTY_VISITOR; } return new JavaElementVisitor() { void handleIteratorLoop( PsiLoopStatement statement, PsiJavaToken endToken, IteratorDeclaration declaration) { if (endToken == null || declaration == null || !declaration.isCollection()) return; PsiStatement body = statement.getBody(); if (!(body instanceof PsiBlockStatement)) return; PsiStatement[] statements = ((PsiBlockStatement) body).getCodeBlock().getStatements(); if (statements.length == 2 && statements[1] instanceof PsiIfStatement) { PsiVariable element = declaration.getNextElementVariable(statements[0]); if (element == null) return; PsiIfStatement ifStatement = (PsiIfStatement) statements[1]; if (checkAndExtractCondition(declaration, ifStatement) == null) return; registerProblem(statement, endToken); } else if (statements.length == 1 && statements[0] instanceof PsiIfStatement) { PsiIfStatement ifStatement = (PsiIfStatement) statements[0]; PsiExpression condition = checkAndExtractCondition(declaration, ifStatement); if (condition == null) return; PsiElement ref = declaration.findOnlyIteratorRef(condition); if (ref != null && declaration.isIteratorMethodCall(ref.getParent().getParent(), "next") && isAlwaysExecuted(condition, ref)) { registerProblem(statement, endToken); } } } private boolean isAlwaysExecuted(PsiExpression condition, PsiElement ref) { while (ref != condition) { PsiElement parent = ref.getParent(); if (parent instanceof PsiPolyadicExpression) { PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression) parent; IElementType type = polyadicExpression.getOperationTokenType(); if ((type.equals(JavaTokenType.ANDAND) || type.equals(JavaTokenType.OROR)) && polyadicExpression.getOperands()[0] != ref) { return false; } } if (parent instanceof PsiConditionalExpression && ((PsiConditionalExpression) parent).getCondition() != ref) { return false; } ref = parent; } return true; } private void registerProblem(PsiLoopStatement statement, PsiJavaToken endToken) { //noinspection DialogTitleCapitalization holder.registerProblem( statement, new TextRange(0, endToken.getTextOffset() - statement.getTextOffset() + 1), QuickFixBundle.message("java.8.collection.removeif.inspection.description"), new ReplaceWithRemoveIfQuickFix()); } @Nullable private PsiExpression checkAndExtractCondition( IteratorDeclaration declaration, PsiIfStatement ifStatement) { PsiExpression condition = ifStatement.getCondition(); if (condition == null || ifStatement.getElseBranch() != null) return null; PsiStatement thenStatement = ControlFlowUtils.stripBraces(ifStatement.getThenBranch()); if (!(thenStatement instanceof PsiExpressionStatement)) return null; if (!declaration.isIteratorMethodCall( ((PsiExpressionStatement) thenStatement).getExpression(), "remove")) return null; if (!LambdaGenerationUtil.canBeUncheckedLambda(condition)) return null; return condition; } @Override public void visitForStatement(PsiForStatement statement) { super.visitForStatement(statement); IteratorDeclaration declaration = IteratorDeclaration.fromLoop(statement); handleIteratorLoop(statement, statement.getRParenth(), declaration); } @Override public void visitWhileStatement(PsiWhileStatement statement) { super.visitWhileStatement(statement); IteratorDeclaration declaration = IteratorDeclaration.fromLoop(statement); handleIteratorLoop(statement, statement.getRParenth(), declaration); } }; }