diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/DefaultInferredAnnotationProvider.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/DefaultInferredAnnotationProvider.java index fc261ee9ab..070e5daee1 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/DefaultInferredAnnotationProvider.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/DefaultInferredAnnotationProvider.java @@ -12,6 +12,7 @@ import com.intellij.java.language.psi.util.PsiUtil; import com.siyeh.ig.callMatcher.CallMatcher; import consulo.annotation.component.ExtensionImpl; +import consulo.java.language.module.util.JavaClassNames; import consulo.language.psi.PsiElement; import consulo.project.Project; import consulo.util.collection.ContainerUtil; @@ -43,9 +44,9 @@ public class DefaultInferredAnnotationProvider implements InferredAnnotationProv // Could be added via external annotations, but there are many signatures to handle // and we have troubles supporting external annotations for JDK 9+ private static final CallMatcher IMMUTABLE_FACTORY = CallMatcher.anyOf( - CallMatcher.staticCall(CommonClassNames.JAVA_UTIL_LIST, "of", "copyOf"), - CallMatcher.staticCall(CommonClassNames.JAVA_UTIL_SET, "of", "copyOf"), - CallMatcher.staticCall(CommonClassNames.JAVA_UTIL_MAP, "of", "ofEntries", "copyOf", "entry") + CallMatcher.staticCall(JavaClassNames.JAVA_UTIL_LIST, "of", "copyOf"), + CallMatcher.staticCall(JavaClassNames.JAVA_UTIL_SET, "of", "copyOf"), + CallMatcher.staticCall(JavaClassNames.JAVA_UTIL_MAP, "of", "ofEntries", "copyOf", "entry") ); private final NullableNotNullManager myNullabilityManager; @@ -64,8 +65,8 @@ public PsiAnnotation findInferredAnnotation(@Nonnull PsiModifierListOwner listOw listOwner = PsiUtil.preferCompiledElement(listOwner); - if (ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotationFQN) && listOwner instanceof PsiMethod) { - PsiAnnotation anno = getHardcodedContractAnnotation((PsiMethod)listOwner); + if (ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotationFQN) && listOwner instanceof PsiMethod method) { + PsiAnnotation anno = getHardcodedContractAnnotation(method); if (anno != null) { return anno; } @@ -82,11 +83,11 @@ public PsiAnnotation findInferredAnnotation(@Nonnull PsiModifierListOwner listOw if (isDefaultNullabilityAnnotation(annotationFQN)) { PsiAnnotation anno = null; - if (listOwner instanceof PsiMethodImpl) { - anno = getInferredNullabilityAnnotation((PsiMethodImpl)listOwner); + if (listOwner instanceof PsiMethodImpl method) { + anno = getInferredNullabilityAnnotation(method); } - if (listOwner instanceof PsiParameter) { - anno = getInferredNullabilityAnnotation((PsiParameter)listOwner); + if (listOwner instanceof PsiParameter parameter) { + anno = getInferredNullabilityAnnotation(parameter); } return anno == null ? null : annotationFQN.equals(anno.getQualifiedName()) ? anno : null; } @@ -95,8 +96,8 @@ public PsiAnnotation findInferredAnnotation(@Nonnull PsiModifierListOwner listOw return getInferredMutabilityAnnotation(listOwner); } - if (listOwner instanceof PsiMethodImpl && ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotationFQN)) { - return getInferredContractAnnotation((PsiMethodImpl)listOwner); + if (listOwner instanceof PsiMethodImpl method && ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotationFQN)) { + return getInferredContractAnnotation(method); } return null; @@ -136,7 +137,7 @@ private boolean ignoreInference(@Nonnull PsiModifierListOwner owner, @Nullable S if (annotationFQN == null) { return true; } - if (owner instanceof PsiMethod && PsiUtil.canBeOverridden((PsiMethod)owner)) { + if (owner instanceof PsiMethod method && PsiUtil.canBeOverridden(method)) { return true; } if (ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotationFQN) && HardcodedContracts.hasHardcodedContracts(owner)) { @@ -156,16 +157,15 @@ private boolean ignoreInference(@Nonnull PsiModifierListOwner owner, @Nullable S @Nullable private PsiAnnotation getInferredMutabilityAnnotation(@Nonnull PsiModifierListOwner owner) { - if (owner instanceof PsiMethod && IMMUTABLE_FACTORY.methodMatches((PsiMethod)owner)) { + if (owner instanceof PsiMethod method && IMMUTABLE_FACTORY.methodMatches(method)) { return Mutability.UNMODIFIABLE.asAnnotation(myProject); } - if (!(owner instanceof PsiMethodImpl)) { + if (!(owner instanceof PsiMethodImpl method)) { return null; } - PsiMethodImpl method = (PsiMethodImpl)owner; PsiModifierList modifiers = method.getModifierList(); - if (modifiers.hasAnnotation(Mutability.UNMODIFIABLE_ANNOTATION) || - modifiers.hasAnnotation(Mutability.UNMODIFIABLE_VIEW_ANNOTATION)) { + if (modifiers.hasAnnotation(Mutability.UNMODIFIABLE_ANNOTATION) + || modifiers.hasAnnotation(Mutability.UNMODIFIABLE_VIEW_ANNOTATION)) { return null; } return JavaSourceInference.inferMutability(method).asAnnotation(myProject); @@ -209,18 +209,15 @@ private PsiAnnotation getInferredNullabilityAnnotation(PsiParameter parameter) { return null; } PsiElement scope = parent.getParent(); - if (scope instanceof PsiMethod) { - PsiMethod method = (PsiMethod)scope; - if (method.getName().equals("of")) { - PsiClass containingClass = method.getContainingClass(); - if (containingClass != null) { - String className = containingClass.getQualifiedName(); - if (CommonClassNames.JAVA_UTIL_LIST.equals(className) || - CommonClassNames.JAVA_UTIL_SET.equals(className) || - CommonClassNames.JAVA_UTIL_MAP.equals(className) || - "java.util.EnumSet".equals(className)) { - return ProjectBytecodeAnalysis.getInstance(myProject).getNotNullAnnotation(); - } + if (scope instanceof PsiMethod method && method.getName().equals("of")) { + PsiClass containingClass = method.getContainingClass(); + if (containingClass != null) { + String className = containingClass.getQualifiedName(); + if (JavaClassNames.JAVA_UTIL_LIST.equals(className) + || JavaClassNames.JAVA_UTIL_SET.equals(className) + || JavaClassNames.JAVA_UTIL_MAP.equals(className) + || JavaClassNames.JAVA_UTIL_ENUM_SET.equals(className)) { + return ProjectBytecodeAnalysis.getInstance(myProject).getNotNullAnnotation(); } } } @@ -265,17 +262,17 @@ public List findInferredAnnotations(@Nonnull PsiModifierListOwner } } - if (listOwner instanceof PsiMethod) { - PsiAnnotation hardcoded = getHardcodedContractAnnotation((PsiMethod)listOwner); + if (listOwner instanceof PsiMethod method) { + PsiAnnotation hardcoded = getHardcodedContractAnnotation(method); ContainerUtil.addIfNotNull(result, hardcoded); - if (listOwner instanceof PsiMethodImpl) { + if (listOwner instanceof PsiMethodImpl methodImpl) { if (hardcoded == null && !ignoreInference(listOwner, ORG_JETBRAINS_ANNOTATIONS_CONTRACT)) { - ContainerUtil.addIfNotNull(result, getInferredContractAnnotation((PsiMethodImpl)listOwner)); + ContainerUtil.addIfNotNull(result, getInferredContractAnnotation(methodImpl)); } if (!ignoreInference(listOwner, myNullabilityManager.getDefaultNotNull()) || !ignoreInference(listOwner, myNullabilityManager.getDefaultNullable())) { - PsiAnnotation annotation = getInferredNullabilityAnnotation((PsiMethodImpl)listOwner); + PsiAnnotation annotation = getInferredNullabilityAnnotation(methodImpl); if (annotation != null && !ignoreInference(listOwner, annotation.getQualifiedName())) { result.add(annotation); } @@ -283,8 +280,8 @@ public List findInferredAnnotations(@Nonnull PsiModifierListOwner } } - if (listOwner instanceof PsiParameter && !ignoreInference(listOwner, myNullabilityManager.getDefaultNotNull())) { - ContainerUtil.addIfNotNull(result, getInferredNullabilityAnnotation((PsiParameter)listOwner)); + if (listOwner instanceof PsiParameter parameter && !ignoreInference(listOwner, myNullabilityManager.getDefaultNotNull())) { + ContainerUtil.addIfNotNull(result, getInferredNullabilityAnnotation(parameter)); } ContainerUtil.addIfNotNull(result, getInferredMutabilityAnnotation(listOwner)); diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/guess/impl/GuessManagerImpl.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/guess/impl/GuessManagerImpl.java index a034d23395..2d99f7f82a 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/guess/impl/GuessManagerImpl.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/guess/impl/GuessManagerImpl.java @@ -13,10 +13,12 @@ import com.intellij.java.language.psi.util.TypeConversionUtil; import com.siyeh.ig.callMatcher.CallMatcher; import com.siyeh.ig.psiutils.ExpressionUtils; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ServiceImpl; import consulo.application.util.CachedValueProvider; import consulo.content.scope.SearchScope; import consulo.document.util.TextRange; +import consulo.java.language.module.util.JavaClassNames; import consulo.language.psi.*; import consulo.language.psi.resolve.PsiElementProcessor; import consulo.language.psi.resolve.PsiElementProcessorAdapter; @@ -73,8 +75,9 @@ private void initMethodPatterns() { myMethodPatternMap.addPattern(new MethodPattern("setElementAt", 2, 0)); } - @Override @Nonnull + @Override + @RequiredReadAction public PsiType[] guessContainerElementType(PsiExpression containerExpr, TextRange rangeToIgnore) { HashSet typesSet = new HashSet<>(); @@ -84,19 +87,15 @@ public PsiType[] guessContainerElementType(PsiExpression containerExpr, TextRang return new PsiType[]{elemType}; } - if (containerExpr instanceof PsiReferenceExpression) { - PsiElement refElement = ((PsiReferenceExpression)containerExpr).resolve(); - if (refElement instanceof PsiVariable) { - - PsiFile file = refElement.getContainingFile(); - if (file == null) { - file = containerExpr.getContainingFile(); // implicit variable in jsp - } - HashSet checkedVariables = new HashSet<>(); - addTypesByVariable(typesSet, (PsiVariable)refElement, file, checkedVariables, CHECK_USAGE | CHECK_DOWN, rangeToIgnore); - checkedVariables.clear(); - addTypesByVariable(typesSet, (PsiVariable)refElement, file, checkedVariables, CHECK_UP, rangeToIgnore); + if (containerExpr instanceof PsiReferenceExpression refExpr && refExpr.resolve() instanceof PsiVariable variable) { + PsiFile file = variable.getContainingFile(); + if (file == null) { + file = containerExpr.getContainingFile(); // implicit variable in jsp } + HashSet checkedVariables = new HashSet<>(); + addTypesByVariable(typesSet, variable, file, checkedVariables, CHECK_USAGE | CHECK_DOWN, rangeToIgnore); + checkedVariables.clear(); + addTypesByVariable(typesSet, variable, file, checkedVariables, CHECK_UP, rangeToIgnore); } return typesSet.toArray(PsiType.createArray(typesSet.size())); @@ -114,8 +113,9 @@ private static PsiType getGenericElementType(PsiType collectionType) { return null; } - @Override @Nonnull + @Override + @RequiredReadAction public PsiType[] guessTypeToCast(PsiExpression expr) { LinkedHashSet types = new LinkedHashSet<>(getControlFlowExpressionTypeConjuncts(expr)); addExprTypesWhenContainerElement(types, expr); @@ -125,6 +125,7 @@ public PsiType[] guessTypeToCast(PsiExpression expr) { @Nonnull @Override + @RequiredReadAction public MultiMap getControlFlowExpressionTypes(@Nonnull PsiExpression forPlace, boolean honorAssignments) { PsiElement scope = DfaPsiUtil.getTopmostBlockInSameClass(forPlace); if (scope == null) { @@ -137,7 +138,7 @@ public MultiMap getControlFlowExpressionTypes(@Nonnull P DataFlowRunner runner = createRunner(honorAssignments, scope); - final ExpressionTypeInstructionVisitor visitor = new ExpressionTypeInstructionVisitor(forPlace); + ExpressionTypeInstructionVisitor visitor = new ExpressionTypeInstructionVisitor(forPlace); if (runner.analyzeMethodWithInlining(scope, visitor) == RunnerResult.OK) { return visitor.getResult(); } @@ -145,6 +146,7 @@ public MultiMap getControlFlowExpressionTypes(@Nonnull P } @Nullable + @RequiredReadAction private static PsiType getTypeFromDataflow(PsiExpression forPlace, boolean honorAssignments) { PsiType type = forPlace.getType(); TypeConstraint initial = type == null ? TypeConstraints.TOP : TypeConstraints.instanceOf(type); @@ -170,7 +172,7 @@ protected void beforeExpressionPush( @Nonnull DfaMemoryState state ) { if (expression == forPlace && range == null) { - if (!(value instanceof DfaVariableValue) || ((DfaVariableValue)value).isFlushableByCalls()) { + if (!(value instanceof DfaVariableValue dfaVarValue) || dfaVarValue.isFlushableByCalls()) { value = runner.getFactory().getVarFactory().createVariableValue(new ExpressionVariableDescriptor(expression)); } constraint = constraint.join(TypeConstraint.fromDfType(state.getDfType(value))); @@ -180,11 +182,11 @@ protected void beforeExpressionPush( @Override boolean isInteresting(@Nonnull DfaValue value, @Nonnull PsiExpression expression) { - return (!(value instanceof DfaVariableValue) || ((DfaVariableValue)value).isFlushableByCalls()) && - ExpressionVariableDescriptor.EXPRESSION_HASHING_STRATEGY.equals(expression, forPlace); + return (!(value instanceof DfaVariableValue dfaVarValue) || dfaVarValue.isFlushableByCalls()) + && ExpressionVariableDescriptor.EXPRESSION_HASHING_STRATEGY.equals(expression, forPlace); } } - final Visitor visitor = new Visitor(); + Visitor visitor = new Visitor(); if (runner.analyzeMethodWithInlining(scope, visitor) == RunnerResult.OK) { return visitor.constraint.meet(initial).getPsiType(scope.getProject()); } @@ -206,17 +208,14 @@ private static PsiElement getTopmostBlock(PsiElement scope) { assert scope.isValid(); PsiElement lastScope = scope; while (true) { - final PsiCodeBlock lastCodeBlock = PsiTreeUtil.getParentOfType(lastScope, PsiCodeBlock.class, true); + PsiCodeBlock lastCodeBlock = PsiTreeUtil.getParentOfType(lastScope, PsiCodeBlock.class, true); if (lastCodeBlock == null) { break; } lastScope = lastCodeBlock; } - if (lastScope == scope) { - PsiFile file = scope.getContainingFile(); - if (file instanceof PsiCodeFragment) { - return file; - } + if (lastScope == scope && scope.getContainingFile() instanceof PsiCodeFragment codeFragment) { + return codeFragment; } return lastScope; } @@ -247,9 +246,9 @@ private void addExprTypesByDerivedClasses(LinkedHashSet set, Ps } } + @RequiredReadAction private void addExprTypesWhenContainerElement(LinkedHashSet set, PsiExpression expr) { - if (expr instanceof PsiMethodCallExpression) { - PsiMethodCallExpression callExpr = (PsiMethodCallExpression)expr; + if (expr instanceof PsiMethodCallExpression callExpr) { PsiReferenceExpression methodExpr = callExpr.getMethodExpression(); String methodName = methodExpr.getReferenceName(); MethodPattern pattern = myMethodPatternMap.findPattern(methodName, callExpr.getArgumentList().getExpressionCount()); @@ -258,10 +257,8 @@ private void addExprTypesWhenContainerElement(LinkedHashSet set if (qualifier != null) { PsiType[] types = guessContainerElementType(qualifier, null); for (PsiType type : types) { - if (type instanceof PsiClassType) { - if (((PsiClassType)type).resolve() instanceof PsiAnonymousClass) { - continue; - } + if (type instanceof PsiClassType classType && classType.resolve() instanceof PsiAnonymousClass) { + continue; } set.add(type); } @@ -274,6 +271,7 @@ private void addExprTypesWhenContainerElement(LinkedHashSet set private static final int CHECK_UP = 0x02; private static final int CHECK_DOWN = 0x04; + @RequiredReadAction private void addTypesByVariable( HashSet typesSet, PsiVariable var, @@ -300,12 +298,10 @@ private void addTypesByVariable( } if (BitUtil.isSet(flags, CHECK_DOWN)) { - if (ref.getParent() instanceof PsiExpressionList - && ref.getParent().getParent() instanceof PsiMethodCallExpression) { //TODO : new - PsiExpressionList list = (PsiExpressionList)ref.getParent(); + if (ref.getParent() instanceof PsiExpressionList list + && list.getParent() instanceof PsiMethodCallExpression methodCall) { //TODO : new int argIndex = ArrayUtil.indexOf(list.getExpressions(), ref); - PsiMethodCallExpression methodCall = (PsiMethodCallExpression)list.getParent(); PsiMethod method = (PsiMethod)methodCall.getMethodExpression().resolve(); if (method != null) { PsiParameter[] parameters = method.getParameterList().getParameters(); @@ -325,76 +321,69 @@ private void addTypesByVariable( } } - if (BitUtil.isSet(flags, CHECK_UP)) { - if (var instanceof PsiParameter && var.getParent() instanceof PsiParameterList && var.getParent() - .getParent() instanceof PsiMethod) { - PsiParameterList list = (PsiParameterList)var.getParent(); - PsiParameter[] parameters = list.getParameters(); - int argIndex = -1; - for (int i = 0; i < parameters.length; i++) { - PsiParameter parameter = parameters[i]; - if (parameter.equals(var)) { - argIndex = i; - break; - } + if (BitUtil.isSet(flags, CHECK_UP) + && var instanceof PsiParameter + && var.getParent() instanceof PsiParameterList list + && list.getParent() instanceof PsiMethod) { + PsiParameter[] parameters = list.getParameters(); + int argIndex = -1; + for (int i = 0; i < parameters.length; i++) { + PsiParameter parameter = parameters[i]; + if (parameter.equals(var)) { + argIndex = i; + break; } + } - PsiMethod method = (PsiMethod)var.getParent().getParent(); - //System.out.println("analyzing usages of " + method + " in file " + scopeFile); - for (PsiReference methodRef : ReferencesSearch.search(method, searchScope, false)) { - PsiElement ref = methodRef.getElement(); - if (ref.getParent() instanceof PsiMethodCallExpression) { - PsiMethodCallExpression methodCall = (PsiMethodCallExpression)ref.getParent(); - PsiExpression[] args = methodCall.getArgumentList().getExpressions(); - if (args.length <= argIndex) { - continue; - } - PsiExpression arg = args[argIndex]; - if (arg instanceof PsiReferenceExpression) { - PsiElement refElement = ((PsiReferenceExpression)arg).resolve(); - if (refElement instanceof PsiVariable) { - addTypesByVariable( - typesSet, - (PsiVariable)refElement, - scopeFile, - checkedVariables, - flags | CHECK_USAGE, - rangeToIgnore - ); - } - } - //TODO : constructor + PsiMethod method = (PsiMethod)var.getParent().getParent(); + //System.out.println("analyzing usages of " + method + " in file " + scopeFile); + for (PsiReference methodRef : ReferencesSearch.search(method, searchScope, false)) { + PsiElement ref = methodRef.getElement(); + if (ref.getParent() instanceof PsiMethodCallExpression methodCall) { + PsiExpression[] args = methodCall.getArgumentList().getExpressions(); + if (args.length <= argIndex) { + continue; } + PsiExpression arg = args[argIndex]; + if (arg instanceof PsiReferenceExpression argRefExpr && argRefExpr.resolve() instanceof PsiVariable variable) { + addTypesByVariable( + typesSet, + variable, + scopeFile, + checkedVariables, + flags | CHECK_USAGE, + rangeToIgnore + ); + } + //TODO : constructor } } } } @Nullable + @RequiredReadAction private static PsiType guessElementTypeFromReference( MethodPatternMap methodPatternMap, PsiElement ref, TextRange rangeToIgnore ) { - PsiElement refParent = ref.getParent(); - if (refParent instanceof PsiReferenceExpression) { - PsiReferenceExpression parentExpr = (PsiReferenceExpression)refParent; - if (ref.equals(parentExpr.getQualifierExpression()) && parentExpr.getParent() instanceof PsiMethodCallExpression) { - String methodName = parentExpr.getReferenceName(); - PsiMethodCallExpression methodCall = (PsiMethodCallExpression)parentExpr.getParent(); - PsiExpression[] args = methodCall.getArgumentList().getExpressions(); - MethodPattern pattern = methodPatternMap.findPattern(methodName, args.length); - if (pattern != null) { - if (pattern.parameterIndex < 0) { // return value - if (methodCall.getParent() instanceof PsiTypeCastExpression && - (rangeToIgnore == null || !rangeToIgnore.contains(methodCall.getTextRange()))) { - return ((PsiTypeCastExpression)methodCall.getParent()).getType(); - } - } - else { - return args[pattern.parameterIndex].getType(); + if (ref.getParent() instanceof PsiReferenceExpression parentExpr + && ref.equals(parentExpr.getQualifierExpression()) + && parentExpr.getParent() instanceof PsiMethodCallExpression methodCall) { + String methodName = parentExpr.getReferenceName(); + PsiExpression[] args = methodCall.getArgumentList().getExpressions(); + MethodPattern pattern = methodPatternMap.findPattern(methodName, args.length); + if (pattern != null) { + if (pattern.parameterIndex < 0) { // return value + if (methodCall.getParent() instanceof PsiTypeCastExpression typeCast + && (rangeToIgnore == null || !rangeToIgnore.contains(methodCall.getTextRange()))) { + return typeCast.getType(); } } + else { + return args[pattern.parameterIndex].getType(); + } } } return null; @@ -402,6 +391,7 @@ private static PsiType guessElementTypeFromReference( @Nonnull @Override + @RequiredReadAction public List getControlFlowExpressionTypeConjuncts(@Nonnull PsiExpression expr, boolean honorAssignments) { if (expr.getType() instanceof PsiPrimitiveType) { return Collections.emptyList(); @@ -421,9 +411,8 @@ public List getControlFlowExpressionTypeConjuncts(@Nonnull PsiExpressio } if (result == null) { PsiType psiType = getTypeFromDataflow(expr, honorAssignments); - if (psiType instanceof PsiIntersectionType) { - result = - ContainerUtil.mapNotNull(((PsiIntersectionType)psiType).getConjuncts(), type -> DfaPsiUtil.tryGenerify(expr, type)); + if (psiType instanceof PsiIntersectionType intersectionType) { + result = ContainerUtil.mapNotNull(intersectionType.getConjuncts(), type -> DfaPsiUtil.tryGenerify(expr, type)); } else if (psiType != null) { result = Collections.singletonList(DfaPsiUtil.tryGenerify(expr, psiType)); @@ -432,10 +421,13 @@ else if (psiType != null) { result = Collections.emptyList(); } } - result = ContainerUtil.filter(result, t -> { - PsiClass typeClass = PsiUtil.resolveClassInType(t); - return typeClass == null || PsiUtil.isAccessible(typeClass, expr, null); - }); + result = ContainerUtil.filter( + result, + t -> { + PsiClass typeClass = PsiUtil.resolveClassInType(t); + return typeClass == null || PsiUtil.isAccessible(typeClass, expr, null); + } + ); if (result.equals(Collections.singletonList(TypeConversionUtil.erasure(expr.getType())))) { return Collections.emptyList(); } @@ -457,21 +449,22 @@ private static GuessTypeVisitor tryGuessingTypeWithoutDfa(PsiExpression place, b private static List getPotentiallyAffectingElements(PsiExpression place) { PsiElement topmostBlock = getTopmostBlock(place); - return LanguageCachedValueUtil.getCachedValue(topmostBlock, () -> { - List list = - SyntaxTraverser.psiTraverser(topmostBlock) + return LanguageCachedValueUtil.getCachedValue( + topmostBlock, + () -> { + List list = SyntaxTraverser.psiTraverser(topmostBlock) .filter(e -> e instanceof PsiExpression || e instanceof PsiLocalVariable) .toList(); - return new CachedValueProvider.Result<>(list, topmostBlock); - }); + return new CachedValueProvider.Result<>(list, topmostBlock); + } + ); } private static class GuessTypeVisitor extends JavaElementVisitor { private static final CallMatcher OBJECT_GET_CLASS = - CallMatcher.exactInstanceCall(CommonClassNames.JAVA_LANG_OBJECT, "getClass").parameterCount(0); - private final + CallMatcher.exactInstanceCall(JavaClassNames.JAVA_LANG_OBJECT, "getClass").parameterCount(0); @Nonnull - PsiExpression myPlace; + private final PsiExpression myPlace; PsiType mySpecificType; private boolean myNeedDfa; private boolean myDeclared; @@ -487,10 +480,10 @@ protected void handleAssignment(@Nullable PsiExpression expression) { return; } PsiType type = expression.getType(); - if (type instanceof PsiPrimitiveType) { - type = ((PsiPrimitiveType)type).getBoxedType(expression); + if (type instanceof PsiPrimitiveType primitiveType) { + type = primitiveType.getBoxedType(expression); } - PsiType rawType = type instanceof PsiClassType ? ((PsiClassType)type).rawType() : type; + PsiType rawType = type instanceof PsiClassType classType ? classType.rawType() : type; if (rawType == null || rawType.equals(PsiType.NULL)) { return; } @@ -511,7 +504,8 @@ public void visitAssignmentExpression(PsiAssignmentExpression expression) { } @Override - public void visitLocalVariable(PsiLocalVariable variable) { + @RequiredReadAction + public void visitLocalVariable(@Nonnull PsiLocalVariable variable) { if (ExpressionUtils.isReferenceTo(myPlace, variable)) { myDeclared = true; handleAssignment(variable.getInitializer()); @@ -529,7 +523,8 @@ public void visitTypeCastExpression(PsiTypeCastExpression expression) { } @Override - public void visitMethodCallExpression(PsiMethodCallExpression call) { + @RequiredReadAction + public void visitMethodCallExpression(@Nonnull PsiMethodCallExpression call) { if (OBJECT_GET_CLASS.test(call)) { PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(call.getMethodExpression()); if (qualifier != null && ExpressionVariableDescriptor.EXPRESSION_HASHING_STRATEGY.equals(qualifier, myPlace)) { @@ -555,7 +550,7 @@ public boolean isDfaNeeded() { return false; } PsiType type = myPlace.getType(); - PsiType rawType = type instanceof PsiClassType ? ((PsiClassType)type).rawType() : type; + PsiType rawType = type instanceof PsiClassType classType ? classType.rawType() : type; return !mySpecificType.equals(rawType); } } @@ -602,11 +597,11 @@ MultiMap getResult() { MultiMap.createSet(Maps.newHashMap(ExpressionVariableDescriptor.EXPRESSION_HASHING_STRATEGY)); Project project = myForPlace.getProject(); myResult.forEach((value, constraint) -> { - if (value.getDescriptor() instanceof ExpressionVariableDescriptor) { - PsiExpression expression = ((ExpressionVariableDescriptor)value.getDescriptor()).getExpression(); + if (value.getDescriptor() instanceof ExpressionVariableDescriptor exprVarDescr) { + PsiExpression expression = exprVarDescr.getExpression(); PsiType type = constraint.getPsiType(project); - if (type instanceof PsiIntersectionType) { - result.putValues(expression, Arrays.asList(((PsiIntersectionType)type).getConjuncts())); + if (type instanceof PsiIntersectionType intersectionType) { + result.putValues(expression, Arrays.asList(intersectionType.getConjuncts())); } else if (type != null) { result.putValue(expression, type); @@ -624,9 +619,9 @@ protected void beforeExpressionPush( @Nonnull DfaMemoryState state ) { if (range == null && myForPlace == expression) { - ((DfaMemoryStateImpl)state).forRecordedVariableTypes((var, dfType) -> { - myResult.merge(var, TypeConstraint.fromDfType(dfType), TypeConstraint::join); - }); + ((DfaMemoryStateImpl)state).forRecordedVariableTypes( + (var, dfType) -> myResult.merge(var, TypeConstraint.fromDfType(dfType), TypeConstraint::join) + ); } super.beforeExpressionPush(value, expression, range, state); } diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/intention/AddAnnotationPsiFix.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/intention/AddAnnotationPsiFix.java index 78616509fd..babbd83381 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/intention/AddAnnotationPsiFix.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/intention/AddAnnotationPsiFix.java @@ -13,6 +13,7 @@ import com.siyeh.ig.psiutils.CommentTracker; import consulo.annotation.access.RequiredReadAction; import consulo.java.analysis.localize.JavaAnalysisLocalize; +import consulo.java.language.module.util.JavaClassNames; import consulo.language.editor.WriteCommandAction; import consulo.language.editor.inspection.LocalQuickFixOnPsiElement; import consulo.language.editor.intention.BaseIntentionAction; @@ -73,9 +74,9 @@ public AddAnnotationPsiFix( @RequiredReadAction public static String calcText(PsiModifierListOwner modifierListOwner, @Nullable String annotation) { - final String shortName = annotation == null ? null : annotation.substring(annotation.lastIndexOf('.') + 1); + String shortName = annotation == null ? null : annotation.substring(annotation.lastIndexOf('.') + 1); if (modifierListOwner instanceof PsiNamedElement namedElement) { - final String name = namedElement.getName(); + String name = namedElement.getName(); if (name != null) { JavaElementKind type = JavaElementKind.fromElement(modifierListOwner).lessDescriptive(); return shortName == null @@ -100,8 +101,8 @@ public static PsiModifierListOwner getContainer(PsiFile file, int offset, boolea PsiReference reference = availableOnReference ? file.findReferenceAt(offset) : null; if (reference != null) { PsiElement target = reference.resolve(); - if (target instanceof PsiMember) { - return (PsiMember)target; + if (target instanceof PsiMember member) { + return member; } } @@ -135,6 +136,7 @@ public String getFamilyName() { } @Override + @RequiredReadAction public boolean isAvailable( @Nonnull Project project, @Nonnull PsiFile file, @@ -144,6 +146,7 @@ public boolean isAvailable( return isAvailable((PsiModifierListOwner)startElement, myAnnotation); } + @RequiredReadAction public static boolean isAvailable(@Nonnull PsiModifierListOwner modifierListOwner, @Nonnull String annotationFQN) { if (!modifierListOwner.isValid()) { return false; @@ -152,14 +155,14 @@ public static boolean isAvailable(@Nonnull PsiModifierListOwner modifierListOwne return false; } - if (modifierListOwner instanceof PsiParameter && ((PsiParameter)modifierListOwner).getTypeElement() == null) { - if (modifierListOwner.getParent() instanceof PsiParameterList && - modifierListOwner.getParent().getParent() instanceof PsiLambdaExpression) { + if (modifierListOwner instanceof PsiParameter parameter && parameter.getTypeElement() == null) { + if (modifierListOwner.getParent() instanceof PsiParameterList parameterList && + parameterList.getParent() instanceof PsiLambdaExpression lambda) { // Lambda parameter without type cannot be annotated. Check if we can specify types + //noinspection SimplifiableIfStatement if (PsiUtil.isLanguageLevel11OrHigher(modifierListOwner)) { return true; } - PsiLambdaExpression lambda = (PsiLambdaExpression)modifierListOwner.getParent().getParent(); return LambdaUtil.createLambdaParameterListWithFormalTypes(lambda.getFunctionalInterfaceType(), lambda, false) != null; } return false; @@ -185,15 +188,16 @@ public void invoke( @Nonnull PsiElement startElement, @Nonnull PsiElement endElement ) { - final PsiModifierListOwner myModifierListOwner = (PsiModifierListOwner)startElement; + PsiModifierListOwner myModifierListOwner = (PsiModifierListOwner)startElement; PsiAnnotationOwner target = AnnotationTargetUtil.getTarget(myModifierListOwner, myAnnotation); if (target == null || ContainerUtil.exists(target.getApplicableAnnotations(), anno -> anno.hasQualifiedName(myAnnotation))) { return; } - final ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(project); - ExternalAnnotationsManager.AnnotationPlace place = myAnnotationPlace == ExternalAnnotationsManager.AnnotationPlace.NEED_ASK_USER ? - annotationsManager.chooseAnnotationsPlace(myModifierListOwner) : myAnnotationPlace; + ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(project); + ExternalAnnotationsManager.AnnotationPlace place = myAnnotationPlace == ExternalAnnotationsManager.AnnotationPlace.NEED_ASK_USER + ? annotationsManager.chooseAnnotationsPlace(myModifierListOwner) + : myAnnotationPlace; switch (place) { case NOWHERE: return; @@ -208,7 +212,7 @@ public void invoke( } break; case IN_CODE: - final PsiFile containingFile = myModifierListOwner.getContainingFile(); + PsiFile containingFile = myModifierListOwner.getContainingFile(); Runnable command = () -> { removePhysicalAnnotations(myModifierListOwner, myAnnotationsToRemove); @@ -231,15 +235,16 @@ public void invoke( } @Nonnull + @RequiredReadAction private ExternalAnnotationsManager.AnnotationPlace choosePlace(@Nonnull PsiModifierListOwner modifierListOwner) { Project project = modifierListOwner.getProject(); - final ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(project); + ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(project); PsiClass aClass = JavaPsiFacade.getInstance(project).findClass(myAnnotation, modifierListOwner.getResolveScope()); if (aClass != null && BaseIntentionAction.canModify(modifierListOwner)) { if (AnnotationsHighlightUtil.getRetentionPolicy(aClass) == RetentionPolicy.RUNTIME) { return ExternalAnnotationsManager.AnnotationPlace.IN_CODE; } - if (!CommonClassNames.DEFAULT_PACKAGE.equals(StringUtil.getPackageName(myAnnotation))) { + if (!JavaClassNames.DEFAULT_PACKAGE.equals(StringUtil.getPackageName(myAnnotation))) { PsiClass resolvedBySimpleName = JavaPsiFacade.getInstance(project).getResolveHelper() .resolveReferencedClass(StringUtil.getShortName(myAnnotation), modifierListOwner); if (resolvedBySimpleName != null && resolvedBySimpleName.getManager().areElementsEquivalent(resolvedBySimpleName, aClass)) { @@ -302,6 +307,7 @@ public static PsiAnnotation addPhysicalAnnotationIfAbsent( return addPhysicalAnnotationTo(fqn, pairs, owner); } + @RequiredReadAction public static PsiAnnotation addPhysicalAnnotationTo(String fqn, PsiNameValuePair[] pairs, PsiAnnotationOwner owner) { owner = expandParameterIfNecessary(owner); PsiAnnotation inserted; @@ -327,6 +333,7 @@ public static PsiAnnotation addPhysicalAnnotationTo(String fqn, PsiNameValuePair return inserted; } + @RequiredReadAction private static PsiAnnotationOwner expandParameterIfNecessary(PsiAnnotationOwner owner) { if (owner instanceof PsiModifierList modifierList) { PsiParameter parameter = ObjectUtil.tryCast(modifierList.getParent(), PsiParameter.class); diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/DataFlowInstructionVisitor.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/DataFlowInstructionVisitor.java index e42a7fa5d1..bd38efead2 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/DataFlowInstructionVisitor.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/DataFlowInstructionVisitor.java @@ -14,20 +14,21 @@ import com.intellij.java.language.psi.util.TypeConversionUtil; import com.siyeh.ig.callMatcher.CallMatcher; import com.siyeh.ig.psiutils.TypeUtils; +import consulo.annotation.access.RequiredReadAction; import consulo.application.Application; -import consulo.application.ApplicationManager; import consulo.document.util.TextRange; +import consulo.java.language.module.util.JavaClassNames; import consulo.language.psi.PsiElement; import consulo.language.psi.util.PsiTreeUtil; import consulo.logging.Logger; import consulo.util.collection.ContainerUtil; +import consulo.util.lang.Couple; import consulo.util.lang.Pair; import consulo.util.lang.ThreeState; -import one.util.streamex.EntryStream; -import one.util.streamex.StreamEx; - import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; +import one.util.streamex.EntryStream; +import one.util.streamex.StreamEx; import java.util.*; import java.util.stream.Stream; @@ -42,7 +43,7 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor { private final Map myFailingCalls = new HashMap<>(); private final Map myConstantExpressions = new HashMap<>(); private final Map myOfNullableCalls = new HashMap<>(); - private final Map> myArrayStoreProblems = new HashMap<>(); + private final Map> myArrayStoreProblems = new HashMap<>(); private final Map myMethodReferenceResults = new HashMap<>(); private final Map myOutOfBoundsArrayAccesses = new HashMap<>(); private final Set myReceiverMutabilityViolation = new HashSet<>(); @@ -54,15 +55,16 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor { private final List myEndOfInitializerStates = new ArrayList<>(); private static final CallMatcher USELESS_SAME_ARGUMENTS = CallMatcher.anyOf( - CallMatcher.staticCall(CommonClassNames.JAVA_LANG_MATH, "min", "max").parameterCount(2), - CallMatcher.staticCall(CommonClassNames.JAVA_LANG_INTEGER, "min", "max").parameterCount(2), - CallMatcher.staticCall(CommonClassNames.JAVA_LANG_LONG, "min", "max").parameterCount(2), - CallMatcher.staticCall(CommonClassNames.JAVA_LANG_FLOAT, "min", "max").parameterCount(2), - CallMatcher.staticCall(CommonClassNames.JAVA_LANG_DOUBLE, "min", "max").parameterCount(2), - CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_STRING, "replace").parameterCount(2) + CallMatcher.staticCall(JavaClassNames.JAVA_LANG_MATH, "min", "max").parameterCount(2), + CallMatcher.staticCall(JavaClassNames.JAVA_LANG_INTEGER, "min", "max").parameterCount(2), + CallMatcher.staticCall(JavaClassNames.JAVA_LANG_LONG, "min", "max").parameterCount(2), + CallMatcher.staticCall(JavaClassNames.JAVA_LANG_FLOAT, "min", "max").parameterCount(2), + CallMatcher.staticCall(JavaClassNames.JAVA_LANG_DOUBLE, "min", "max").parameterCount(2), + CallMatcher.instanceCall(JavaClassNames.JAVA_LANG_STRING, "replace").parameterCount(2) ); @Override + @RequiredReadAction public DfaInstructionState[] visitAssign(AssignInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) { PsiExpression left = instruction.getLExpression(); if (left != null && !Boolean.FALSE.equals(mySameValueAssigned.get(left))) { @@ -75,12 +77,12 @@ public DfaInstructionState[] visitAssign(AssignInstruction instruction, DataFlow DfaValue value = memState.peek(); DfaValue target = memState.getStackValue(1); DfType dfType = memState.getDfType(value); - if (target != null && memState.areEqual(value, target) && - !(dfType instanceof DfConstantType && isFloatingZero(((DfConstantType)dfType).getValue())) && + if (target != null && memState.areEqual(value, target) + && !(dfType instanceof DfConstantType && isFloatingZero(((DfConstantType)dfType).getValue())) // Reporting strings is skipped because string reassignment might be intentionally used to deduplicate the heap objects // (we compare strings by contents) - !(TypeUtils.isJavaLangString(left.getType()) && !memState.isNull(value)) && - !isAssignmentToDefaultValueInConstructor(instruction, runner, target)) { + && !(TypeUtils.isJavaLangString(left.getType()) && !memState.isNull(value)) + && !isAssignmentToDefaultValueInConstructor(instruction, runner, target)) { mySameValueAssigned.merge(left, Boolean.TRUE, Boolean::logicalAnd); } else { @@ -99,21 +101,22 @@ protected void beforeConditionalJump(ConditionalGotoInstruction instruction, boo } } + @RequiredReadAction private static boolean isAssignmentToDefaultValueInConstructor(AssignInstruction instruction, DataFlowRunner runner, DfaValue target) { - if (!(target instanceof DfaVariableValue)) { + if (!(target instanceof DfaVariableValue varValue)) { return false; } - DfaVariableValue var = (DfaVariableValue)target; - if (!(var.getPsiVariable() instanceof PsiField) || var.getQualifier() == null || - !(var.getQualifier().getDescriptor() instanceof DfaExpressionFactory.ThisDescriptor)) { + if (!(varValue.getPsiVariable() instanceof PsiField) + || varValue.getQualifier() == null + || !(varValue.getQualifier().getDescriptor() instanceof DfaExpressionFactory.ThisDescriptor)) { return false; } // chained assignment like this.a = this.b = 0; is also supported PsiExpression rExpression = instruction.getRExpression(); - while (rExpression instanceof PsiAssignmentExpression && - ((PsiAssignmentExpression)rExpression).getOperationTokenType().equals(JavaTokenType.EQ)) { - rExpression = ((PsiAssignmentExpression)rExpression).getRExpression(); + while (rExpression instanceof PsiAssignmentExpression rAssignment + && rAssignment.getOperationTokenType().equals(JavaTokenType.EQ)) { + rExpression = rAssignment.getRExpression(); } DfaValue dest = runner.getFactory().createValue(rExpression); if (dest == null) { @@ -121,7 +124,7 @@ private static boolean isAssignmentToDefaultValueInConstructor(AssignInstruction } DfType dfType = dest.getDfType(); - PsiType type = var.getType(); + PsiType type = varValue.getType(); boolean isDefaultValue = DfConstantType.isConst(dfType, PsiTypesUtil.getDefaultValue(type)) || DfConstantType.isConst(dfType, 0) && TypeConversionUtil.isIntegralNumberType(type); if (!isDefaultValue) { @@ -134,11 +137,12 @@ private static boolean isAssignmentToDefaultValueInConstructor(AssignInstruction // Reporting of floating zero is skipped, because this produces false-positives on the code like // if(x == -0.0) x = 0.0; private static boolean isFloatingZero(Object value) { - if (value instanceof Double) { - return ((Double)value).doubleValue() == 0.0; + if (value instanceof Double doubleValue) { + return doubleValue == 0.0; } - if (value instanceof Float) { - return ((Float)value).floatValue() == 0.0f; + //noinspection SimplifiableIfStatement + if (value instanceof Float floatValue) { + return floatValue == 0.0f; } return false; } @@ -160,7 +164,7 @@ StreamEx> problems() { return StreamEx.ofKeys(myStateInfos, StateInfo::shouldReport); } - public Map> getArrayStoreProblems() { + public Map> getArrayStoreProblems() { return myArrayStoreProblems; } @@ -210,10 +214,10 @@ StreamEx alwaysFailingCalls() { } boolean isAlwaysReturnsNotNull(Instruction[] instructions) { - return myAlwaysReturnsNotNull && - ContainerUtil.exists( + return myAlwaysReturnsNotNull + && ContainerUtil.exists( instructions, - i -> i instanceof ReturnInstruction && ((ReturnInstruction)i).getAnchor() instanceof PsiReturnStatement + i -> i instanceof ReturnInstruction returnInsn && returnInsn.getAnchor() instanceof PsiReturnStatement ); } @@ -222,8 +226,9 @@ public boolean isInstanceofRedundant(InstanceofInstruction instruction) { if (expression == null || myUsefulInstanceofs.contains(instruction) || !myReachable.contains(instruction)) { return false; } - ConstantResult result = expression instanceof PsiMethodReferenceExpression ? - myMethodReferenceResults.get(expression) : myConstantExpressions.get(new ExpressionChunk(expression, null)); + ConstantResult result = expression instanceof PsiMethodReferenceExpression + ? myMethodReferenceResults.get(expression) + : myConstantExpressions.get(new ExpressionChunk(expression, null)); return result != ConstantResult.TRUE && result != ConstantResult.FALSE; } @@ -235,16 +240,16 @@ protected void beforeExpressionPush( @Nonnull DfaMemoryState memState ) { if (!expression.isPhysical()) { - Application application = ApplicationManager.getApplication(); + Application application = Application.get(); if (application.isEAP() || application.isInternal() || application.isUnitTestMode()) { throw new IllegalStateException("Non-physical expression is passed"); } } expression.accept(new ExpressionVisitor(value, memState)); PsiElement parent = PsiUtil.skipParenthesizedExprUp(expression.getParent()); - if (parent instanceof PsiTypeCastExpression) { + if (parent instanceof PsiTypeCastExpression typeCastExpr) { TypeConstraint fact = TypeConstraint.fromDfType(memState.getDfType(value)); - myRealOperandTypes.merge((PsiTypeCastExpression)parent, fact, TypeConstraint::join); + myRealOperandTypes.merge(typeCastExpr, fact, TypeConstraint::join); } reportConstantExpressionValue(value, memState, expression, range); } @@ -268,6 +273,7 @@ protected void onMethodCall( } @Override + @RequiredReadAction protected void beforeMethodReferenceResultPush( @Nonnull DfaValue value, @Nonnull PsiMethodReferenceExpression methodRef, @@ -309,7 +315,7 @@ protected void processArrayAccess(PsiArrayAccessExpression expression, boolean a @Override protected void processArrayStoreTypeMismatch(PsiAssignmentExpression assignmentExpression, PsiType fromType, PsiType toType) { if (assignmentExpression != null) { - myArrayStoreProblems.put(assignmentExpression, Pair.create(fromType, toType)); + myArrayStoreProblems.put(assignmentExpression, Couple.of(fromType, toType)); } } @@ -361,11 +367,11 @@ protected boolean checkNotNullable( @Override protected void reportMutabilityViolation(boolean receiver, @Nonnull PsiElement anchor) { if (receiver) { - if (anchor instanceof PsiMethodReferenceExpression) { - anchor = ((PsiMethodReferenceExpression)anchor).getReferenceNameElement(); + if (anchor instanceof PsiMethodReferenceExpression methodRefExpr) { + anchor = methodRefExpr.getReferenceNameElement(); } - else if (anchor instanceof PsiMethodCallExpression) { - anchor = ((PsiMethodCallExpression)anchor).getMethodExpression().getReferenceNameElement(); + else if (anchor instanceof PsiMethodCallExpression methodCall) { + anchor = methodCall.getMethodExpression().getReferenceNameElement(); } if (anchor != null) { myReceiverMutabilityViolation.add(anchor); @@ -417,7 +423,7 @@ private class ExpressionVisitor extends JavaElementVisitor { } @Override - public void visitMethodCallExpression(PsiMethodCallExpression call) { + public void visitMethodCallExpression(@Nonnull PsiMethodCallExpression call) { super.visitMethodCallExpression(call); if (OptionalUtil.OPTIONAL_OF_NULLABLE.test(call)) { processOfNullableResult(myValue, myMemState, call.getArgumentList().getExpressions()[0]); @@ -425,7 +431,7 @@ public void visitMethodCallExpression(PsiMethodCallExpression call) { } @Override - public void visitCallExpression(PsiCallExpression call) { + public void visitCallExpression(@Nonnull PsiCallExpression call) { super.visitCallExpression(call); Boolean isFailing = myFailingCalls.get(call); if (isFailing != null || hasNonTrivialFailingContracts(call)) { @@ -466,6 +472,7 @@ public int hashCode() { } @Override + @RequiredReadAction public String toString() { String text = myExpression.getText(); return myRange == null ? text : myRange.substring(text); diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/DfaOptionalSupport.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/DfaOptionalSupport.java index ba6a165464..31b2c85a3d 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/DfaOptionalSupport.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/DfaOptionalSupport.java @@ -7,29 +7,29 @@ import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.util.PsiUtil; import com.siyeh.ig.psiutils.ExpressionUtils; +import consulo.annotation.access.RequiredReadAction; +import consulo.java.language.module.util.JavaClassNames; import consulo.language.editor.inspection.LocalQuickFix; import consulo.language.editor.inspection.ProblemDescriptor; -import consulo.language.editor.intention.CommonQuickFixBundle; +import consulo.language.editor.localize.CommonQuickFixLocalize; import consulo.language.psi.PsiElement; import consulo.language.psi.util.PsiTreeUtil; import consulo.project.Project; import jakarta.annotation.Nonnull; - import jakarta.annotation.Nullable; /** * @author anet, peter */ public final class DfaOptionalSupport { - @Nullable public static LocalQuickFix registerReplaceOptionalOfWithOfNullableFix(@Nonnull PsiExpression qualifier) { - final PsiMethodCallExpression call = findCallExpression(qualifier); - final PsiMethod method = call == null ? null : call.resolveMethod(); - final PsiClass containingClass = method == null ? null : method.getContainingClass(); + PsiMethodCallExpression call = findCallExpression(qualifier); + PsiMethod method = call == null ? null : call.resolveMethod(); + PsiClass containingClass = method == null ? null : method.getContainingClass(); if (containingClass != null && "of".equals(method.getName())) { - final String qualifiedName = containingClass.getQualifiedName(); - if (CommonClassNames.JAVA_UTIL_OPTIONAL.equals(qualifiedName)) { + String qualifiedName = containingClass.getQualifiedName(); + if (JavaClassNames.JAVA_UTIL_OPTIONAL.equals(qualifiedName)) { return new ReplaceOptionalCallFix("ofNullable", false); } if (OptionalUtil.GUAVA_OPTIONAL.equals(qualifiedName)) { @@ -40,11 +40,10 @@ public static LocalQuickFix registerReplaceOptionalOfWithOfNullableFix(@Nonnull } private static PsiMethodCallExpression findCallExpression(@Nonnull PsiElement anchor) { - final PsiElement argList = PsiUtil.skipParenthesizedExprUp(anchor).getParent(); - if (argList instanceof PsiExpressionList) { - final PsiElement parent = argList.getParent(); - if (parent instanceof PsiMethodCallExpression) { - return (PsiMethodCallExpression)parent; + if (PsiUtil.skipParenthesizedExprUp(anchor).getParent() instanceof PsiExpressionList argList) { + PsiElement parent = argList.getParent(); + if (parent instanceof PsiMethodCallExpression methodCall) { + return methodCall; } } return null; @@ -52,7 +51,7 @@ private static PsiMethodCallExpression findCallExpression(@Nonnull PsiElement an @Nullable public static LocalQuickFix createReplaceOptionalOfNullableWithEmptyFix(@Nonnull PsiElement anchor) { - final PsiMethodCallExpression parent = findCallExpression(anchor); + PsiMethodCallExpression parent = findCallExpression(anchor); if (parent == null) { return null; } @@ -62,7 +61,7 @@ public static LocalQuickFix createReplaceOptionalOfNullableWithEmptyFix(@Nonnull @Nullable public static LocalQuickFix createReplaceOptionalOfNullableWithOfFix(@Nonnull PsiElement anchor) { - final PsiMethodCallExpression parent = findCallExpression(anchor); + PsiMethodCallExpression parent = findCallExpression(anchor); if (parent == null) { return null; } @@ -85,7 +84,7 @@ private static class ReplaceOptionalCallFix implements LocalQuickFix { private final String myTargetMethodName; private final boolean myClearArguments; - ReplaceOptionalCallFix(final String targetMethodName, boolean clearArguments) { + ReplaceOptionalCallFix(String targetMethodName, boolean clearArguments) { myTargetMethodName = targetMethodName; myClearArguments = clearArguments; } @@ -93,12 +92,13 @@ private static class ReplaceOptionalCallFix implements LocalQuickFix { @Nonnull @Override public String getFamilyName() { - return CommonQuickFixBundle.message("fix.replace.with.x", "." + myTargetMethodName + "()"); + return CommonQuickFixLocalize.fixReplaceWithX("." + myTargetMethodName + "()").get(); } @Override + @RequiredReadAction public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) { - final PsiMethodCallExpression + PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiMethodCallExpression.class); if (methodCallExpression != null) { ExpressionUtils.bindCallTo(methodCallExpression, myTargetMethodName); diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/inference/ParameterNullityInferenceKt.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/inference/ParameterNullityInferenceKt.java index e6abf20fa5..453f7f5cfb 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/inference/ParameterNullityInferenceKt.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/inference/ParameterNullityInferenceKt.java @@ -2,11 +2,10 @@ import com.intellij.java.language.impl.psi.impl.source.JavaLightTreeUtil; import com.intellij.java.language.impl.psi.impl.source.tree.ElementType; -import com.intellij.java.language.psi.CommonClassNames; import com.intellij.java.language.psi.JavaTokenType; +import consulo.java.language.module.util.JavaClassNames; import consulo.language.ast.*; import consulo.util.collection.ContainerUtil; - import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; @@ -184,10 +183,10 @@ else if (ElementType.JAVA_STATEMENT_BIT_SET.contains(type)) { "Exception", "RuntimeException", "NullPointerException", - CommonClassNames.JAVA_LANG_THROWABLE, - CommonClassNames.JAVA_LANG_EXCEPTION, - CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION, - CommonClassNames.JAVA_LANG_NULL_POINTER_EXCEPTION + JavaClassNames.JAVA_LANG_THROWABLE, + JavaClassNames.JAVA_LANG_EXCEPTION, + JavaClassNames.JAVA_LANG_RUNTIME_EXCEPTION, + JavaClassNames.JAVA_LANG_NULL_POINTER_EXCEPTION ); private static boolean canCatchNpe(LighterAST tree, @Nullable LighterASTNode type) { diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/inference/PurityInferenceResult.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/inference/PurityInferenceResult.java index f1e7caa431..57431abb0a 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/inference/PurityInferenceResult.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/inference/PurityInferenceResult.java @@ -20,6 +20,7 @@ import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.util.PsiUtil; import consulo.annotation.access.RequiredReadAction; +import consulo.java.language.module.util.JavaClassNames; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiReference; import consulo.language.psi.scope.LocalSearchScope; @@ -28,6 +29,7 @@ import jakarta.annotation.Nullable; import java.util.List; +import java.util.Objects; import java.util.function.Supplier; /** @@ -43,6 +45,7 @@ class PurityInferenceResult { this.singleCall = singleCall; } + @RequiredReadAction public boolean isPure(PsiMethod method, Supplier body) { return !mutatesNonLocals(method, body) && callsOnlyPureMethods(method, body); } @@ -77,17 +80,14 @@ private boolean callsOnlyPureMethods(PsiMethod currentMethod, Supplier null") + @RequiredReadAction DfaValue getExpressionDfaValue(@Nullable PsiExpression expression) { if (expression == null) { return null; } - if (expression instanceof PsiParenthesizedExpression) { - return getExpressionDfaValue(((PsiParenthesizedExpression)expression).getExpression()); + if (expression instanceof PsiParenthesizedExpression parenthesized) { + return getExpressionDfaValue(parenthesized.getExpression()); } - if (expression instanceof PsiArrayAccessExpression) { - PsiExpression arrayExpression = ((PsiArrayAccessExpression)expression).getArrayExpression(); + if (expression instanceof PsiArrayAccessExpression arrayAccess) { + PsiExpression arrayExpression = arrayAccess.getArrayExpression(); DfaValue qualifier = getQualifierValue(arrayExpression); - if (qualifier != null) { - Object index = ExpressionUtils.computeConstantExpression(((PsiArrayAccessExpression)expression).getIndexExpression()); - if (index instanceof Integer) { - DfaValue arrayElementValue = getArrayElementValue(qualifier, (Integer)index); - if (arrayElementValue != null) { - return arrayElementValue; - } + if (qualifier != null + && ExpressionUtils.computeConstantExpression(arrayAccess.getIndexExpression()) instanceof Integer index1) { + DfaValue arrayElementValue = getArrayElementValue(qualifier, index1); + if (arrayElementValue != null) { + return arrayElementValue; } } PsiType type = expression.getType(); @@ -75,23 +76,23 @@ DfaValue getExpressionDfaValue(@Nullable PsiExpression expression) { } } - if (expression instanceof PsiMethodCallExpression) { - return createReferenceValue(((PsiMethodCallExpression)expression).getMethodExpression()); + if (expression instanceof PsiMethodCallExpression methodCall) { + return createReferenceValue(methodCall.getMethodExpression()); } - if (expression instanceof PsiReferenceExpression) { - return createReferenceValue((PsiReferenceExpression)expression); + if (expression instanceof PsiReferenceExpression refExpr) { + return createReferenceValue(refExpr); } - if (expression instanceof PsiLiteralExpression) { - return myFactory.fromDfType(DfaPsiUtil.fromLiteral((PsiLiteralExpression)expression)); + if (expression instanceof PsiLiteralExpression literal) { + return myFactory.fromDfType(DfaPsiUtil.fromLiteral(literal)); } if (expression instanceof PsiNewExpression || expression instanceof PsiLambdaExpression) { return myFactory.getObjectType(expression.getType(), Nullability.NOT_NULL); } - final Object value = JavaConstantExpressionEvaluator.computeConstantExpression(expression, false); + Object value = JavaConstantExpressionEvaluator.computeConstantExpression(expression, false); if (value != null) { PsiType type = expression.getType(); if (type != null) { @@ -115,15 +116,13 @@ DfaValue getExpressionDfaValue(@Nullable PsiExpression expression) { return null; } + @RequiredReadAction private DfaValue createReferenceValue(@Nonnull PsiReferenceExpression refExpr) { PsiElement target = refExpr.resolve(); - if (target instanceof PsiVariable) { - PsiVariable variable = (PsiVariable)target; - if (!PsiUtil.isAccessedForWriting(refExpr)) { - DfaValue constValue = myFactory.getConstantFromVariable(variable); - if (constValue != null && !maybeUninitializedConstant(constValue, refExpr, variable)) { - return constValue; - } + if (target instanceof PsiVariable variable && !PsiUtil.isAccessedForWriting(refExpr)) { + DfaValue constValue = myFactory.getConstantFromVariable(variable); + if (constValue != null && !maybeUninitializedConstant(constValue, refExpr, variable)) { + return constValue; } } VariableDescriptor var = getAccessedVariableOrGetter(target); @@ -148,14 +147,15 @@ private DfaValue createReferenceValue(@Nonnull PsiReferenceExpression refExpr) { * @return a qualifier variable or null if qualifier is unnecessary or cannot be represented as a variable */ @Nullable + @RequiredReadAction public DfaValue getQualifierOrThisValue(PsiReferenceExpression refExpr) { PsiExpression qualifierExpression = refExpr.getQualifierExpression(); if (qualifierExpression == null) { PsiElement element = refExpr.resolve(); - if (element instanceof PsiMember && !((PsiMember)element).hasModifierProperty(PsiModifier.STATIC)) { + if (element instanceof PsiMember member && !member.isStatic()) { PsiClass currentClass; currentClass = ClassUtils.getContainingClass(refExpr); - PsiClass memberClass = ((PsiMember)element).getContainingClass(); + PsiClass memberClass = member.getContainingClass(); if (memberClass != null && currentClass != null) { PsiClass target; if (currentClass == memberClass || InheritanceUtil.isInheritorOrSelf(currentClass, memberClass, true)) { @@ -172,6 +172,7 @@ public DfaValue getQualifierOrThisValue(PsiReferenceExpression refExpr) { } @Nullable + @RequiredReadAction private DfaValue getQualifierValue(PsiExpression qualifierExpression) { DfaValue qualifierValue = getExpressionDfaValue(qualifierExpression); if (qualifierValue == null) { @@ -195,6 +196,7 @@ private static boolean maybeUninitializedConstant( if (!DfConstantType.isConst(constValue.getDfType(), var)) { return false; } + //noinspection SimplifiableIfStatement if (!(var instanceof PsiField) || var instanceof PsiEnumConstant) { return false; } @@ -203,16 +205,15 @@ private static boolean maybeUninitializedConstant( @Contract("null -> null") @Nullable - public static VariableDescriptor getAccessedVariableOrGetter(final PsiElement target) { + public static VariableDescriptor getAccessedVariableOrGetter(PsiElement target) { SpecialField sf = SpecialField.findSpecialField(target); if (sf != null) { return sf; } - if (target instanceof PsiVariable) { - return new PlainDescriptor((PsiVariable)target); + if (target instanceof PsiVariable variable) { + return new PlainDescriptor(variable); } - if (target instanceof PsiMethod) { - PsiMethod method = (PsiMethod)target; + if (target instanceof PsiMethod method) { if (method.getParameterList().isEmpty() && ( PropertyUtilBase.isSimplePropertyGetter(method) @@ -241,6 +242,7 @@ private static boolean isContractAllowedForGetter(PsiMethod method) { } @Nonnull + @RequiredReadAction private DfaValue getAdvancedExpressionDfaValue(@Nullable PsiExpression expression, @Nullable PsiType targetType) { if (expression == null) { return myFactory.getUnknown(); @@ -249,29 +251,31 @@ private DfaValue getAdvancedExpressionDfaValue(@Nullable PsiExpression expressio if (value != null) { return DfaUtil.boxUnbox(value, targetType); } - if (expression instanceof PsiConditionalExpression) { - return getAdvancedExpressionDfaValue(((PsiConditionalExpression)expression).getThenExpression(), targetType).unite( - getAdvancedExpressionDfaValue(((PsiConditionalExpression)expression).getElseExpression(), targetType)); + if (expression instanceof PsiConditionalExpression conditionalExpr) { + return getAdvancedExpressionDfaValue(conditionalExpr.getThenExpression(), targetType) + .unite(getAdvancedExpressionDfaValue(conditionalExpr.getElseExpression(), targetType)); } PsiType type = expression.getType(); - if (expression instanceof PsiArrayInitializerExpression) { - int length = ((PsiArrayInitializerExpression)expression).getInitializers().length; + if (expression instanceof PsiArrayInitializerExpression arrayInitializer) { + int length = arrayInitializer.getInitializers().length; return myFactory.fromDfType(SpecialField.ARRAY_LENGTH.asDfType(DfTypes.intValue(length), type)); } DfType dfType = DfTypes.typedObject(type, NullabilityUtil.getExpressionNullability(expression)); - if (type instanceof PsiPrimitiveType && targetType instanceof PsiPrimitiveType && !type.equals(targetType)) { - if (TypeConversionUtil.isIntegralNumberType(targetType)) { + if (type instanceof PsiPrimitiveType primitiveType + && targetType instanceof PsiPrimitiveType targetPrimitiveType + && !primitiveType.equals(targetPrimitiveType)) { + if (TypeConversionUtil.isIntegralNumberType(targetPrimitiveType)) { LongRangeSet range = DfLongType.extractRange(dfType); - return myFactory.fromDfType(rangeClamped(range.castTo((PsiPrimitiveType)targetType), PsiType.LONG.equals(targetType))); + return myFactory.fromDfType(rangeClamped(range.castTo(targetPrimitiveType), PsiType.LONG.equals(targetPrimitiveType))); } - return myFactory.fromDfType(DfTypes.typedObject(targetType, Nullability.UNKNOWN)); + return myFactory.fromDfType(DfTypes.typedObject(targetPrimitiveType, Nullability.UNKNOWN)); } return DfaUtil.boxUnbox(myFactory.fromDfType(dfType), targetType); } @Nonnull public DfaValue getArrayElementValue(DfaValue array, LongRangeSet indexSet) { - if (!(array instanceof DfaVariableValue)) { + if (!(array instanceof DfaVariableValue arrayDfaVar)) { return myFactory.getUnknown(); } if (indexSet.isEmpty()) { @@ -283,14 +287,11 @@ public DfaValue getArrayElementValue(DfaValue array, LongRangeSet indexSet) { DfaValue value = getArrayElementValue(array, (int)min); return value == null ? myFactory.getUnknown() : value; } - DfaVariableValue arrayDfaVar = (DfaVariableValue)array; - PsiModifierListOwner arrayPsiVar = arrayDfaVar.getPsiVariable(); - if (!(arrayPsiVar instanceof PsiVariable)) { + if (!(arrayDfaVar.getPsiVariable() instanceof PsiVariable arrayVar)) { return myFactory.getUnknown(); } - PsiType arrayType = ((PsiVariable)arrayPsiVar).getType(); - PsiType targetType = arrayType instanceof PsiArrayType ? ((PsiArrayType)arrayType).getComponentType() : null; - PsiExpression[] elements = ExpressionUtils.getConstantArrayElements((PsiVariable)arrayPsiVar); + PsiType targetType = arrayVar.getType() instanceof PsiArrayType arrayType ? arrayType.getComponentType() : null; + PsiExpression[] elements = ExpressionUtils.getConstantArrayElements(arrayVar); if (elements == null || elements.length == 0) { return myFactory.getUnknown(); } @@ -308,20 +309,16 @@ public DfaValue getArrayElementValue(DfaValue array, LongRangeSet indexSet) { @Contract("null, _ -> null") @Nullable + @RequiredReadAction public DfaValue getArrayElementValue(DfaValue array, int index) { - if (!(array instanceof DfaVariableValue)) { - return null; - } - DfaVariableValue arrayDfaVar = (DfaVariableValue)array; - PsiType type = arrayDfaVar.getType(); - if (!(type instanceof PsiArrayType)) { + if (!(array instanceof DfaVariableValue arrayDfaVar) || !(arrayDfaVar.getType() instanceof PsiArrayType arrayType)) { return null; } PsiModifierListOwner arrayPsiVar = arrayDfaVar.getPsiVariable(); - if (arrayPsiVar instanceof PsiVariable) { - PsiExpression constantArrayElement = ExpressionUtils.getConstantArrayElement((PsiVariable)arrayPsiVar, index); + if (arrayPsiVar instanceof PsiVariable arrayVar) { + PsiExpression constantArrayElement = ExpressionUtils.getConstantArrayElement(arrayVar, index); if (constantArrayElement != null) { - return getAdvancedExpressionDfaValue(constantArrayElement, ((PsiArrayType)type).getComponentType()); + return getAdvancedExpressionDfaValue(constantArrayElement, arrayType.getComponentType()); } } ArrayElementDescriptor indexVariable = getArrayIndexVariable(index); @@ -341,8 +338,8 @@ private ArrayElementDescriptor getArrayIndexVariable(int index) { @Nonnull private static PsiSubstitutor getSubstitutor(PsiElement member, @Nullable DfaVariableValue qualifier) { - if (member instanceof PsiMember && qualifier != null) { - PsiClass fieldClass = ((PsiMember)member).getContainingClass(); + if (member instanceof PsiMember psiMember && qualifier != null) { + PsiClass fieldClass = psiMember.getContainingClass(); PsiClassType classType = ObjectUtil.tryCast(qualifier.getType(), PsiClassType.class); if (classType != null && InheritanceUtil.isInheritorOrSelf(classType.resolve(), fieldClass, true)) { return TypeConversionUtil.getSuperClassSubstitutor(fieldClass, classType); @@ -389,6 +386,7 @@ static final class PlainDescriptor implements VariableDescriptor { @Nonnull @Override + @RequiredReadAction public String toString() { return String.valueOf(myVariable.getName()); } @@ -396,8 +394,8 @@ public String toString() { @Override public PsiType getType(@Nullable DfaVariableValue qualifier) { PsiType type = myVariable.getType(); - if (type instanceof PsiEllipsisType) { - type = ((PsiEllipsisType)type).toArrayType(); + if (type instanceof PsiEllipsisType ellipsisType) { + type = ellipsisType.toArrayType(); } return getSubstitutor(myVariable, qualifier).substitute(type); } @@ -419,34 +417,35 @@ public DfaValue createValue(@Nonnull DfaValueFactory factory, @Nullable DfaValue PsiType type = getType(ObjectUtil.tryCast(qualifier, DfaVariableValue.class)); return factory.getObjectType(type, DfaPsiUtil.getElementNullability(type, myVariable)); } - if (PsiUtil.isJvmLocalVariable(myVariable) || - (myVariable instanceof PsiField && myVariable.hasModifierProperty(PsiModifier.STATIC) && - (!myVariable.hasModifierProperty(PsiModifier.FINAL) || !DfaUtil.hasInitializationHacks((PsiField)myVariable)))) { + if (PsiUtil.isJvmLocalVariable(myVariable) + || (myVariable instanceof PsiField field && field.isStatic() + && (!field.isFinal() || !DfaUtil.hasInitializationHacks(field)))) { return factory.getVarFactory().createVariableValue(this); } return VariableDescriptor.super.createValue(factory, qualifier, forAccessor); } @Override + @RequiredReadAction public int hashCode() { return Objects.hashCode(myVariable.getName()); } @Override public boolean equals(Object obj) { - return obj == this || obj instanceof PlainDescriptor && ((PlainDescriptor)obj).myVariable == myVariable; + return obj == this || obj instanceof PlainDescriptor plainDescriptor && plainDescriptor.myVariable == myVariable; } } public static final class GetterDescriptor implements VariableDescriptor { private static final CallMatcher STABLE_METHODS = CallMatcher.anyOf( - CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_OBJECT, "getClass").parameterCount(0), + CallMatcher.instanceCall(JavaClassNames.JAVA_LANG_OBJECT, "getClass").parameterCount(0), CallMatcher.instanceCall("java.lang.reflect.Member", "getName", "getModifiers", "getDeclaringClass", "isSynthetic"), CallMatcher.instanceCall("java.lang.reflect.Executable", "getParameterCount", "isVarArgs"), CallMatcher.instanceCall("java.lang.reflect.Field", "getType"), CallMatcher.instanceCall("java.lang.reflect.Method", "getReturnType"), CallMatcher.instanceCall( - CommonClassNames.JAVA_LANG_CLASS, + JavaClassNames.JAVA_LANG_CLASS, "getName", "isInterface", "isArray", @@ -473,7 +472,7 @@ public GetterDescriptor(@Nonnull PsiMethod getter) { } else { PsiField field = PsiUtil.canBeOverridden(getter) ? null : PropertyUtil.getFieldOfGetter(getter); - myStable = field != null && field.hasModifierProperty(PsiModifier.FINAL); + myStable = field != null && field.isFinal(); } } @@ -508,7 +507,7 @@ public boolean isCall() { @Nonnull @Override public DfaValue createValue(@Nonnull DfaValueFactory factory, @Nullable DfaValue qualifier, boolean forAccessor) { - if (myGetter.hasModifierProperty(PsiModifier.STATIC)) { + if (myGetter.isStatic()) { return factory.getVarFactory().createVariableValue(this); } return VariableDescriptor.super.createValue(factory, qualifier, forAccessor); @@ -521,7 +520,7 @@ public int hashCode() { @Override public boolean equals(Object obj) { - return obj == this || (obj instanceof GetterDescriptor && ((GetterDescriptor)obj).myGetter == myGetter); + return obj == this || (obj instanceof GetterDescriptor getterDescr && getterDescr.myGetter == myGetter); } } @@ -542,8 +541,7 @@ public PsiType getType(@Nullable DfaVariableValue qualifier) { if (qualifier == null) { return null; } - PsiType qualifierType = qualifier.getType(); - return qualifierType instanceof PsiArrayType ? ((PsiArrayType)qualifierType).getComponentType() : null; + return qualifier.getType() instanceof PsiArrayType arrayType ? arrayType.getComponentType() : null; } @Nonnull @@ -568,6 +566,7 @@ public static final class ThisDescriptor implements VariableDescriptor { @Nonnull @Override + @RequiredReadAction public String toString() { return myQualifier.getName() + ".this"; } @@ -595,7 +594,7 @@ public int hashCode() { @Override public boolean equals(Object obj) { - return this == obj || obj instanceof ThisDescriptor && ((ThisDescriptor)obj).myQualifier == myQualifier; + return this == obj || obj instanceof ThisDescriptor thisDescr && thisDescr.myQualifier == myQualifier; } } } diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/value/DfaValueFactory.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/value/DfaValueFactory.java index 953b063a34..0244624cf0 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/value/DfaValueFactory.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/dataFlow/value/DfaValueFactory.java @@ -14,7 +14,9 @@ import com.intellij.java.language.psi.util.PsiUtil; import com.siyeh.ig.callMatcher.CallMatcher; import com.siyeh.ig.psiutils.ExpressionUtils; +import consulo.annotation.access.RequiredReadAction; import consulo.application.util.CachedValueProvider; +import consulo.java.language.module.util.JavaClassNames; import consulo.language.pattern.ElementPattern; import consulo.language.psi.PsiCompiledElement; import consulo.language.psi.PsiElement; @@ -26,11 +28,9 @@ import consulo.util.collection.FList; import consulo.util.collection.FactoryMap; import consulo.util.lang.Pair; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NonNls; - import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; +import org.jetbrains.annotations.Contract; import java.util.*; @@ -39,19 +39,15 @@ import static consulo.language.pattern.StandardPatterns.or; public class DfaValueFactory { - private final @Nonnull - List myValues = new ArrayList<>(); + private final List myValues = new ArrayList<>(); private final boolean myUnknownMembersAreNullable; - private final @Nonnull - FieldChecker myFieldChecker; - private final + private final FieldChecker myFieldChecker; @Nonnull - Project myProject; - private + private final Project myProject; @Nullable - DfaVariableValue myAssertionDisabled; + private DfaVariableValue myAssertionDisabled; /** * @param project a project in which context the analysis is performed @@ -116,6 +112,7 @@ public DfaValue getValue(int id) { @Nullable @Contract("null -> null") + @RequiredReadAction public DfaValue createValue(PsiExpression psiExpression) { return myExpressionFactory.getExpressionDfaValue(psiExpression); } @@ -179,6 +176,7 @@ public DfaTypeValue getConstant(Object value, @Nonnull PsiType type) { * @return a value that represents a constant created from variable; null if variable cannot be represented as a constant */ @Nullable + @RequiredReadAction public DfaValue getConstantFromVariable(PsiVariable variable) { if (!variable.hasModifierProperty(PsiModifier.FINAL) || DfaUtil.ignoreInitializer(variable)) { return null; @@ -196,10 +194,10 @@ public DfaValue getConstantFromVariable(PsiVariable variable) { } PsiExpression initializer = PsiFieldImpl.getDetachedInitializer(variable); initializer = PsiUtil.skipParenthesizedExprDown(initializer); - if (initializer instanceof PsiLiteralExpression && initializer.textMatches(PsiKeyword.NULL)) { + if (initializer instanceof PsiLiteralExpression literal && literal.textMatches(PsiKeyword.NULL)) { return getNull(); } - if (variable instanceof PsiField && variable.hasModifierProperty(PsiModifier.STATIC) && ExpressionUtils.isNewObject(initializer)) { + if (variable instanceof PsiField field && field.isStatic() && ExpressionUtils.isNewObject(initializer)) { return getConstant(variable, type); } return null; @@ -213,15 +211,16 @@ public Project getProject() { } @Nullable - private static Boolean computeJavaLangBooleanFieldReference(final PsiVariable variable) { - if (!(variable instanceof PsiField)) { + @RequiredReadAction + private static Boolean computeJavaLangBooleanFieldReference(PsiVariable variable) { + if (!(variable instanceof PsiField field)) { return null; } - PsiClass psiClass = ((PsiField)variable).getContainingClass(); - if (psiClass == null || !CommonClassNames.JAVA_LANG_BOOLEAN.equals(psiClass.getQualifiedName())) { + PsiClass psiClass = field.getContainingClass(); + if (psiClass == null || !JavaClassNames.JAVA_LANG_BOOLEAN.equals(psiClass.getQualifiedName())) { return null; } - @NonNls String name = variable.getName(); + String name = variable.getName(); return "TRUE".equals(name) ? Boolean.TRUE : "FALSE".equals(name) ? Boolean.FALSE : null; } @@ -275,6 +274,7 @@ public DfaBinOpValue.Factory getBinOpFactory() { } @Nonnull + @RequiredReadAction public DfaValue createCommonValue(@Nonnull PsiExpression[] expressions, PsiType targetType) { DfaValue loopElement = null; for (PsiExpression expression : expressions) { @@ -292,20 +292,22 @@ public DfaValue createCommonValue(@Nonnull PsiExpression[] expressions, PsiType private static class ClassInitializationInfo { private static final CallMatcher SAFE_CALLS = - CallMatcher.staticCall(CommonClassNames.JAVA_UTIL_OBJECTS, "requireNonNull"); + CallMatcher.staticCall(JavaClassNames.JAVA_UTIL_OBJECTS, "requireNonNull"); final boolean myCanInstantiateItself; final boolean myCtorsCallMethods; final boolean mySuperCtorsCallMethods; + @RequiredReadAction ClassInitializationInfo(@Nonnull PsiClass psiClass) { // Indirect instantiation via other class is still possible, but hopefully unlikely boolean canInstantiateItself = false; for (PsiElement child = psiClass.getFirstChild(); child != null; child = child.getNextSibling()) { - if (child instanceof PsiMember && ((PsiMember)child).hasModifierProperty(PsiModifier.STATIC) && - SyntaxTraverser.psiTraverser(child).filter(PsiNewExpression.class) - .filterMap(PsiNewExpression::getClassReference) - .find(classRef -> classRef.isReferenceTo(psiClass)) != null) { + if (child instanceof PsiMember member && member.isStatic() + && SyntaxTraverser.psiTraverser(child) + .filter(PsiNewExpression.class) + .filterMap(PsiNewExpression::getClassReference) + .find(classRef -> classRef.isReferenceTo(psiClass)) != null) { canInstantiateItself = true; break; } @@ -316,18 +318,18 @@ private static class ClassInitializationInfo { myCtorsCallMethods = canCallMethodsInConstructors(psiClass, false); } + @RequiredReadAction private static boolean canCallMethodsInConstructors(@Nonnull PsiClass aClass, boolean virtual) { boolean inByteCode = false; if (aClass instanceof PsiCompiledElement) { inByteCode = true; - PsiElement navigationElement = aClass.getNavigationElement(); - if (navigationElement instanceof PsiClass) { - aClass = (PsiClass)navigationElement; + if (aClass.getNavigationElement() instanceof PsiClass navigationClass) { + aClass = navigationClass; } } for (PsiMethod constructor : aClass.getConstructors()) { - if (inByteCode && JavaMethodContractUtil.isPure(constructor) && - !JavaMethodContractUtil.hasExplicitContractAnnotation(constructor)) { + if (inByteCode && JavaMethodContractUtil.isPure(constructor) + && !JavaMethodContractUtil.hasExplicitContractAnnotation(constructor)) { // While pure constructor may call pure overridable method, our current implementation // of bytecode inference will not infer the constructor purity in this case. // So if we inferred a constructor purity from bytecode we can currently rely that @@ -374,17 +376,22 @@ private static class FieldChecker { FieldChecker(PsiElement context) { PsiMethod method = context instanceof PsiClass ? null : PsiTreeUtil.getParentOfType(context, PsiMethod.class); - PsiClass contextClass = method != null ? method.getContainingClass() : context instanceof PsiClass ? (PsiClass)context : null; + PsiClass contextClass = method != null ? method.getContainingClass() : context instanceof PsiClass psiClass ? psiClass : null; myClass = contextClass; if (method == null || myClass == null) { myTrustDirectFieldInitializers = myTrustFieldInitializersInConstructors = myCanInstantiateItself = false; return; } // Indirect instantiation via other class is still possible, but hopefully unlikely - ClassInitializationInfo info = LanguageCachedValueUtil.getCachedValue(contextClass, () -> CachedValueProvider.Result - .create(new ClassInitializationInfo(contextClass), PsiModificationTracker.MODIFICATION_COUNT)); + ClassInitializationInfo info = LanguageCachedValueUtil.getCachedValue( + contextClass, + () -> CachedValueProvider.Result.create( + new ClassInitializationInfo(contextClass), + PsiModificationTracker.MODIFICATION_COUNT + ) + ); myCanInstantiateItself = info.myCanInstantiateItself; - if (method.hasModifierProperty(PsiModifier.STATIC) || method.isConstructor()) { + if (method.isStatic() || method.isConstructor()) { myTrustDirectFieldInitializers = true; myTrustFieldInitializersInConstructors = false; return; @@ -395,7 +402,8 @@ private static class FieldChecker { boolean canTrustFieldInitializer(PsiField field) { if (field.hasInitializer()) { - boolean staticField = field.hasModifierProperty(PsiModifier.STATIC); + boolean staticField = field.isStatic(); + //noinspection SimplifiableIfStatement if (staticField && myClass != null && field.getContainingClass() != myClass) { return true; } diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/java15api/Java15APIUsageInspection.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/java15api/Java15APIUsageInspection.java index a1f8d3bcb6..cb8d7a1978 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/java15api/Java15APIUsageInspection.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/java15api/Java15APIUsageInspection.java @@ -14,15 +14,13 @@ import com.intellij.java.language.psi.util.PsiUtil; import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; -import consulo.language.editor.inspection.InspectionsBundle; -import consulo.language.editor.inspection.LocalInspectionToolSession; -import consulo.language.editor.inspection.LocalQuickFix; -import consulo.language.editor.inspection.ProblemsHolder; +import consulo.java.language.module.util.JavaClassNames; +import consulo.language.editor.inspection.*; import consulo.language.editor.inspection.localize.InspectionLocalize; import consulo.language.editor.rawHighlight.HighlightDisplayLevel; import consulo.language.psi.*; import consulo.language.psi.util.PsiTreeUtil; -import consulo.language.util.ModuleUtilCore; +import consulo.localize.LocalizeValue; import consulo.logging.Logger; import consulo.module.Module; import consulo.ui.ex.awt.*; @@ -209,7 +207,7 @@ public HighlightDisplayLevel getDefaultLevel() { @Override public void readSettings(@Nonnull Element node) throws InvalidDataException { - final Element element = node.getChild(EFFECTIVE_LL); + Element element = node.getChild(EFFECTIVE_LL); if (element != null) { myEffectiveLanguageLevel = LanguageLevel.valueOf(element.getAttributeValue("value")); } @@ -218,7 +216,7 @@ public void readSettings(@Nonnull Element node) throws InvalidDataException { @Override public void writeSettings(@Nonnull Element node) throws WriteExternalException { if (myEffectiveLanguageLevel != null) { - final Element llElement = new Element(EFFECTIVE_LL); + Element llElement = new Element(EFFECTIVE_LL); llElement.setAttribute("value", myEffectiveLanguageLevel.toString()); node.addContent(llElement); } @@ -235,7 +233,7 @@ public PsiElementVisitor buildVisitorImpl( return new MyVisitor(holder, isOnTheFly); } - private static boolean isInProject(final PsiElement elt) { + private static boolean isInProject(PsiElement elt) { return elt.getManager().isInProject(elt); } @@ -247,28 +245,29 @@ private class MyVisitor extends JavaElementVisitor { private final ProblemsHolder myHolder; private final boolean myOnTheFly; - MyVisitor(final ProblemsHolder holder, boolean onTheFly) { + MyVisitor(ProblemsHolder holder, boolean onTheFly) { myHolder = holder; myOnTheFly = onTheFly; } @Override - public void visitDocComment(PsiDocComment comment) { + public void visitDocComment(@Nonnull PsiDocComment comment) { // No references inside doc comment are of interest. } @Override + @RequiredReadAction public void visitClass(PsiClass aClass) { // Don't go into classes (anonymous, locals). - if (!aClass.hasModifierProperty(PsiModifier.ABSTRACT) && !(aClass instanceof PsiTypeParameter)) { - final Module module = ModuleUtilCore.findModuleForPsiElement(aClass); - final LanguageLevel effectiveLanguageLevel = module != null ? getEffectiveLanguageLevel(module) : null; + if (!aClass.isAbstract() && !(aClass instanceof PsiTypeParameter)) { + Module module = aClass.getModule(); + LanguageLevel effectiveLanguageLevel = module != null ? getEffectiveLanguageLevel(module) : null; if (effectiveLanguageLevel != null && !effectiveLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) { - final JavaSdkVersion version = JavaVersionService.getInstance().getJavaSdkVersion(aClass); + JavaSdkVersion version = JavaVersionService.getInstance().getJavaSdkVersion(aClass); if (version != null && version.isAtLeast(JavaSdkVersion.JDK_1_8)) { - final List methods = new ArrayList<>(); + List methods = new ArrayList<>(); for (HierarchicalMethodSignature methodSignature : aClass.getVisibleSignatures()) { - final PsiMethod method = methodSignature.getMethod(); + PsiMethod method = methodSignature.getMethod(); if (ourDefaultMethods.contains(getSignature(method))) { methods.add(method); } @@ -278,23 +277,23 @@ public void visitClass(PsiClass aClass) { PsiElement element2Highlight = aClass.getNameIdentifier(); if (element2Highlight == null) { element2Highlight = - aClass instanceof PsiAnonymousClass ? ((PsiAnonymousClass)aClass).getBaseClassReference() : aClass; + aClass instanceof PsiAnonymousClass anonymousClass ? anonymousClass.getBaseClassReference() : aClass; } - myHolder.registerProblem( - element2Highlight, - methods.size() == 1 - ? InspectionsBundle.message( - "inspection.1.8.problem.single.descriptor", - methods.get(0).getName(), - getJdkName(effectiveLanguageLevel) - ) - : InspectionsBundle.message( - "inspection.1.8.problem.descriptor", - methods.size(), - getJdkName(effectiveLanguageLevel) - ), - QuickFixFactory.getInstance().createImplementMethodsFix(aClass) - ); + String descriptionTemplate = methods.size() == 1 + ? InspectionsBundle.message( + "inspection.1.8.problem.single.descriptor", + methods.get(0).getName(), + getJdkName(effectiveLanguageLevel) + ) + : InspectionsBundle.message( + "inspection.1.8.problem.descriptor", + methods.size(), + getJdkName(effectiveLanguageLevel) + ); + myHolder.newProblem(LocalizeValue.of(descriptionTemplate)) + .range(element2Highlight) + .withFixes(QuickFixFactory.getInstance().createImplementMethodsFix(aClass)) + .create(); } } } @@ -302,22 +301,23 @@ public void visitClass(PsiClass aClass) { } @Override - public void visitReferenceExpression(PsiReferenceExpression expression) { + @RequiredReadAction + public void visitReferenceExpression(@Nonnull PsiReferenceExpression expression) { visitReferenceElement(expression); } @Override @RequiredReadAction - public void visitNameValuePair(PsiNameValuePair pair) { + public void visitNameValuePair(@Nonnull PsiNameValuePair pair) { super.visitNameValuePair(pair); PsiReference reference = pair.getReference(); if (reference != null) { PsiElement resolve = reference.resolve(); - if (resolve instanceof PsiCompiledElement && resolve instanceof PsiAnnotationMethod) { - final Module module = ModuleUtilCore.findModuleForPsiElement(pair); + if (resolve instanceof PsiCompiledElement && resolve instanceof PsiAnnotationMethod annotationMethod) { + Module module = pair.getModule(); if (module != null) { - final LanguageLevel languageLevel = getEffectiveLanguageLevel(module); - LanguageLevel sinceLanguageLevel = getLastIncompatibleLanguageLevel((PsiMember)resolve, languageLevel); + LanguageLevel languageLevel = getEffectiveLanguageLevel(module); + LanguageLevel sinceLanguageLevel = getLastIncompatibleLanguageLevel(annotationMethod, languageLevel); if (sinceLanguageLevel != null) { registerError(ObjectUtil.notNull(pair.getNameIdentifier(), pair), sinceLanguageLevel); } @@ -327,18 +327,19 @@ public void visitNameValuePair(PsiNameValuePair pair) { } @Override - public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { + @RequiredReadAction + public void visitReferenceElement(@Nonnull PsiJavaCodeReferenceElement reference) { super.visitReferenceElement(reference); - final PsiElement resolved = reference.resolve(); + PsiElement resolved = reference.resolve(); - if (resolved instanceof PsiCompiledElement && resolved instanceof PsiMember) { - final Module module = ModuleUtilCore.findModuleForPsiElement(reference.getElement()); + if (resolved instanceof PsiCompiledElement && resolved instanceof PsiMember member) { + Module module = reference.getElement().getModule(); if (module != null) { - final LanguageLevel languageLevel = getEffectiveLanguageLevel(module); - LanguageLevel sinceLanguageLevel = getLastIncompatibleLanguageLevel((PsiMember)resolved, languageLevel); + LanguageLevel languageLevel = getEffectiveLanguageLevel(module); + LanguageLevel sinceLanguageLevel = getLastIncompatibleLanguageLevel(member, languageLevel); if (sinceLanguageLevel != null) { PsiClass psiClass = null; - final PsiElement qualifier = reference.getQualifier(); + PsiElement qualifier = reference.getQualifier(); if (qualifier != null) { if (qualifier instanceof PsiExpression) { psiClass = PsiUtil.resolveClassInType(((PsiExpression)qualifier).getType()); @@ -359,12 +360,12 @@ public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { } registerError(reference, sinceLanguageLevel); } - else if (resolved instanceof PsiClass && isInProject(reference) && !languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) { - final PsiReferenceParameterList parameterList = reference.getParameterList(); + else if (resolved instanceof PsiClass psiClass && isInProject(reference) && !languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) { + PsiReferenceParameterList parameterList = reference.getParameterList(); if (parameterList != null && parameterList.getTypeParameterElements().length > 0) { for (String generifiedClass : ourGenerifiedClasses) { - if (InheritanceUtil.isInheritor((PsiClass)resolved, generifiedClass) && - !isRawInheritance(generifiedClass, (PsiClass)resolved, new HashSet<>())) { + if (InheritanceUtil.isInheritor(psiClass, generifiedClass) + && !isRawInheritance(generifiedClass, psiClass, new HashSet<>())) { String message = InspectionsBundle.message("inspection.1.7.problem.descriptor", getJdkName(languageLevel)); myHolder.registerProblem(reference, message); @@ -382,8 +383,8 @@ private boolean isRawInheritance(String generifiedClassQName, PsiClass currentCl if (classType.isRaw()) { return true; } - final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics(); - final PsiClass superClass = resolveResult.getElement(); + PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics(); + PsiClass superClass = resolveResult.getElement(); if (visited.add(superClass) && InheritanceUtil.isInheritor(superClass, generifiedClassQName)) { if (isRawInheritance(generifiedClassQName, superClass, visited)) { return true; @@ -394,18 +395,18 @@ private boolean isRawInheritance(String generifiedClassQName, PsiClass currentCl } private boolean isIgnored(PsiClass psiClass) { - final String qualifiedName = psiClass.getQualifiedName(); + String qualifiedName = psiClass.getQualifiedName(); return qualifiedName != null && ourIgnored16ClassesAPI.get().contains(qualifiedName); } @Override @RequiredReadAction - public void visitNewExpression(@Nonnull final PsiNewExpression expression) { + public void visitNewExpression(@Nonnull PsiNewExpression expression) { super.visitNewExpression(expression); - final PsiMethod constructor = expression.resolveConstructor(); - final Module module = ModuleUtilCore.findModuleForPsiElement(expression); + PsiMethod constructor = expression.resolveConstructor(); + Module module = expression.getModule(); if (module != null) { - final LanguageLevel languageLevel = getEffectiveLanguageLevel(module); + LanguageLevel languageLevel = getEffectiveLanguageLevel(module); if (constructor instanceof PsiCompiledElement) { LanguageLevel sinceLanguageLevel = getLastIncompatibleLanguageLevel(constructor, languageLevel); if (sinceLanguageLevel != null) { @@ -420,13 +421,13 @@ public void visitNewExpression(@Nonnull final PsiNewExpression expression) { public void visitMethod(@Nonnull PsiMethod method) { super.visitMethod(method); PsiAnnotation annotation = !method.isConstructor() - ? AnnotationUtil.findAnnotation(method, CommonClassNames.JAVA_LANG_OVERRIDE) : null; + ? AnnotationUtil.findAnnotation(method, JavaClassNames.JAVA_LANG_OVERRIDE) : null; if (annotation != null) { - final Module module = ModuleUtilCore.findModuleForPsiElement(annotation); + Module module = annotation.getModule(); LanguageLevel sinceLanguageLevel = null; if (module != null) { - final LanguageLevel languageLevel = getEffectiveLanguageLevel(module); - final PsiMethod[] methods = method.findSuperMethods(); + LanguageLevel languageLevel = getEffectiveLanguageLevel(module); + PsiMethod[] methods = method.findSuperMethods(); for (PsiMethod superMethod : methods) { if (superMethod instanceof PsiCompiledElement) { sinceLanguageLevel = getLastIncompatibleLanguageLevel(superMethod, languageLevel); @@ -450,18 +451,16 @@ private LanguageLevel getEffectiveLanguageLevel(Module module) { return myEffectiveLanguageLevel != null ? myEffectiveLanguageLevel : EffectiveLanguageLevelUtil.getEffectiveLanguageLevel(module); } + @RequiredReadAction private void registerError(PsiElement reference, LanguageLevel api) { if (reference != null && isInProject(reference)) { - myHolder.registerProblem( - reference, - InspectionLocalize.inspection15ProblemDescriptor(getShortName(api)).get(), - myOnTheFly - ? new LocalQuickFix[]{ - (LocalQuickFix)QuickFixFactory.getInstance() - .createIncreaseLanguageLevelFix(LanguageLevel.values()[api.ordinal() + 1]) - } - : null - ); + ProblemBuilder builder = myHolder.newProblem(InspectionLocalize.inspection15ProblemDescriptor(getShortName(api))) + .range(reference); + if (myOnTheFly) { + QuickFixFactory factory = QuickFixFactory.getInstance(); + builder.withFix((LocalQuickFix)factory.createIncreaseLanguageLevelFix(LanguageLevel.values()[api.ordinal() + 1])); + } + builder.create(); } } } diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/nullable/NullableStuffInspectionBase.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/nullable/NullableStuffInspectionBase.java index e82397b779..46e4308383 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/nullable/NullableStuffInspectionBase.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/nullable/NullableStuffInspectionBase.java @@ -19,6 +19,7 @@ import consulo.annotation.access.RequiredReadAction; import consulo.application.util.registry.Registry; import consulo.java.analysis.impl.localize.JavaInspectionsLocalize; +import consulo.java.language.module.util.JavaClassNames; import consulo.language.editor.inspection.*; import consulo.language.editor.inspection.localize.InspectionLocalize; import consulo.language.psi.PsiElement; @@ -27,6 +28,7 @@ import consulo.language.psi.SyntaxTraverser; import consulo.language.psi.scope.GlobalSearchScope; import consulo.language.psi.util.PsiTreeUtil; +import consulo.localize.LocalizeValue; import consulo.logging.Logger; import consulo.project.Project; import consulo.project.content.GeneratedSourcesFilter; @@ -51,25 +53,28 @@ public abstract class NullableStuffInspectionBase extends AbstractBaseJavaLocalInspectionTool { private static final Logger LOG = Logger.getInstance(NullableStuffInspectionBase.class); - @Override @Nonnull + @Override + @RequiredReadAction public PsiElementVisitor buildVisitorImpl( @Nonnull final ProblemsHolder holder, boolean isOnTheFly, LocalInspectionToolSession session, NullableStuffInspectionState state ) { - final PsiFile file = holder.getFile(); + PsiFile file = holder.getFile(); if (!PsiUtil.isLanguageLevel5OrHigher(file) || nullabilityAnnotationsNotAvailable(file)) { return PsiElementVisitor.EMPTY_VISITOR; } return new JavaElementVisitor() { @Override + @RequiredReadAction public void visitMethod(@Nonnull PsiMethod method) { checkNullableStuffForMethod(method, holder, isOnTheFly, state); } @Override + @RequiredReadAction public void visitMethodReferenceExpression(@Nonnull PsiMethodReferenceExpression expression) { checkMethodReference(expression, holder, state); @@ -87,16 +92,16 @@ public void visitMethodReferenceExpression(@Nonnull PsiMethodReferenceExpression @Override @RequiredReadAction public void visitField(@Nonnull PsiField field) { - final PsiType type = field.getType(); - final Annotated annotated = check(field, holder, type); + PsiType type = field.getType(); + Annotated annotated = check(field, holder, type); if (TypeConversionUtil.isPrimitiveAndNotNull(type)) { return; } Project project = holder.getProject(); - final NullableNotNullManager manager = NullableNotNullManager.getInstance(project); + NullableNotNullManager manager = NullableNotNullManager.getInstance(project); if (annotated.isDeclaredNotNull ^ annotated.isDeclaredNullable) { - final String anno = annotated.isDeclaredNotNull ? manager.getDefaultNotNull() : manager.getDefaultNullable(); - final List annoToRemove = annotated.isDeclaredNotNull ? manager.getNullables() : manager.getNotNulls(); + String anno = annotated.isDeclaredNotNull ? manager.getDefaultNotNull() : manager.getDefaultNullable(); + List annoToRemove = annotated.isDeclaredNotNull ? manager.getNullables() : manager.getNotNulls(); if (!checkNonStandardAnnotations(field, annotated, manager, anno, holder)) { return; @@ -138,7 +143,8 @@ private List getExclusiveAnnotations(PsiTypeElement type) { ArrayUtil.remove(AnnotationTargetUtil.getTargetsForLocation(modifierList), PsiAnnotation.TargetType.TYPE_USE); annotations.addAll(ContainerUtil.filter( modifierList.getAnnotations(), - a -> AnnotationTargetUtil.isTypeAnnotation(a) && AnnotationTargetUtil.findAnnotationTarget(a, targets) == null + a -> AnnotationTargetUtil.isTypeAnnotation(a) + && AnnotationTargetUtil.findAnnotationTarget(a, targets) == null )); } } @@ -155,11 +161,12 @@ public void visitAnnotation(@Nonnull PsiAnnotation annotation) { if (value instanceof PsiClassObjectAccessExpression classObjectAccessExpression) { PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(classObjectAccessExpression.getOperand().getType()); if (psiClass != null && !hasStringConstructor(psiClass)) { - holder.registerProblem( - value, - "Custom exception class should have a constructor with a single message parameter of String type", - ProblemHighlightType.GENERIC_ERROR_OR_WARNING - ); + holder.newProblem(LocalizeValue.localizeTODO( + "Custom exception class should have a constructor with a single message parameter of String type" + )) + .range(value) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } } } @@ -168,7 +175,7 @@ private boolean hasStringConstructor(PsiClass aClass) { for (PsiMethod method : aClass.getConstructors()) { PsiParameterList list = method.getParameterList(); if (list.getParametersCount() == 1 && - list.getParameters()[0].getType().equalsToText(CommonClassNames.JAVA_LANG_STRING)) { + list.getParameters()[0].getType().equalsToText(JavaClassNames.JAVA_LANG_STRING)) { return true; } } @@ -206,11 +213,10 @@ private void checkNullableNotNullInstantiationConflict(PsiJavaCodeReferenceEleme if (DfaPsiUtil.getTypeNullability(JavaPsiFacade.getElementFactory(element.getProject()) .createType(typeParameters[i])) == Nullability.NOT_NULL && DfaPsiUtil.getTypeNullability(typeArguments[i].getType()) != Nullability.NOT_NULL) { - holder.registerProblem( - typeArguments[i], - "Non-null type argument is expected", - ProblemHighlightType.GENERIC_ERROR_OR_WARNING - ); + holder.newProblem(LocalizeValue.localizeTODO("Non-null type argument is expected")) + .range(typeArguments[i]) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } } } @@ -252,9 +258,8 @@ public void visitReturnStatement(@Nonnull PsiReturnStatement statement) { @Override public void visitLambdaExpression(@Nonnull PsiLambdaExpression lambda) { super.visitLambdaExpression(lambda); - PsiElement body = lambda.getBody(); - if (body instanceof PsiExpression) { - checkCollectionNullityOnAssignment(body, LambdaUtil.getFunctionalInterfaceReturnType(lambda), (PsiExpression)body); + if (lambda.getBody() instanceof PsiExpression body) { + checkCollectionNullityOnAssignment(body, LambdaUtil.getFunctionalInterfaceReturnType(lambda), body); } } @@ -297,11 +302,12 @@ private void checkCollectionNullityOnAssignment( @Nullable PsiType assignedType ) { if (isNullableNotNullCollectionConflict(expectedType, assignedType, new HashSet<>())) { - holder.registerProblem( - errorElement, - "Assigning a collection of nullable elements into a collection of non-null elements", - ProblemHighlightType.GENERIC_ERROR_OR_WARNING - ); + holder.newProblem(LocalizeValue.localizeTODO( + "Assigning a collection of nullable elements into a collection of non-null elements" + )) + .range(errorElement) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } } @@ -323,11 +329,11 @@ private boolean isNullableNotNullCollectionConflict( } for (int i = 0; i <= 1; i++) { - PsiType expectedArg = PsiUtil.substituteTypeParameter(expectedType, CommonClassNames.JAVA_UTIL_MAP, i, false); - PsiType assignedArg = PsiUtil.substituteTypeParameter(assignedType, CommonClassNames.JAVA_UTIL_MAP, i, false); - if (isNullityConflict(expectedArg, assignedArg) || - expectedArg != null && assignedArg != null - && isNullableNotNullCollectionConflict(expectedArg, assignedArg, visited)) { + PsiType expectedArg = PsiUtil.substituteTypeParameter(expectedType, JavaClassNames.JAVA_UTIL_MAP, i, false); + PsiType assignedArg = PsiUtil.substituteTypeParameter(assignedType, JavaClassNames.JAVA_UTIL_MAP, i, false); + if (isNullityConflict(expectedArg, assignedArg) + || expectedArg != null && assignedArg != null + && isNullableNotNullCollectionConflict(expectedArg, assignedArg, visited)) { return true; } } @@ -426,23 +432,23 @@ private void checkMethodReference( PsiElement refName = expression.getReferenceNameElement(); assert refName != null; if (isNullableOverridingNotNull(check(targetMethod, holder, expression.getType()), superMethod, state)) { - holder.registerProblem( - refName, - InspectionsBundle.message( + holder.newProblem(LocalizeValue.of(InspectionsBundle.message( "inspection.nullable.problems.Nullable.method.overrides.NotNull", getPresentableAnnoName(targetMethod), getPresentableAnnoName(superMethod) - ), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING - ); + ))) + .range(refName) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } else if (isNonAnnotatedOverridingNotNull(targetMethod, superMethod, state)) { - holder.registerProblem( - refName, - "Not annotated method is used as an override for a method annotated with " + getPresentableAnnoName(superMethod), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - createFixForNonAnnotatedOverridesNotNull(targetMethod, superMethod) - ); + holder.newProblem(LocalizeValue.localizeTODO( + "Not annotated method is used as an override for a method annotated with " + getPresentableAnnoName(superMethod) + )) + .range(refName) + .withFixes(createFixForNonAnnotatedOverridesNotNull(targetMethod, superMethod)) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } } @@ -450,10 +456,10 @@ protected LocalQuickFix createNavigateToNullParameterUsagesFix(PsiParameter para return null; } - private static boolean nullabilityAnnotationsNotAvailable(final PsiFile file) { - final Project project = file.getProject(); - final GlobalSearchScope scope = GlobalSearchScope.allScope(project); - final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); + private static boolean nullabilityAnnotationsNotAvailable(PsiFile file) { + Project project = file.getProject(); + GlobalSearchScope scope = GlobalSearchScope.allScope(project); + JavaPsiFacade facade = JavaPsiFacade.getInstance(project); return ContainerUtil.find( NullableNotNullManager.getInstance(project).getNullables(), s -> facade.findClass(s, scope) != null @@ -469,15 +475,18 @@ private static boolean checkNonStandardAnnotations( ) { if (!AnnotationUtil.isAnnotatingApplicable(field, anno)) { PsiAnnotation annotation = Objects.requireNonNull(annotated.isDeclaredNullable ? annotated.nullable : annotated.notNull); - String message = "Not \'" + annotation.getQualifiedName() + "\' but \'" + anno + "\' would be used for code generation."; - final PsiJavaCodeReferenceElement annotationNameReferenceElement = annotation.getNameReferenceElement(); - holder.registerProblem( - annotationNameReferenceElement != null && annotationNameReferenceElement.isPhysical() - ? annotationNameReferenceElement : field.getNameIdentifier(), - message, - ProblemHighlightType.WEAK_WARNING, - new ChangeNullableDefaultsFix(annotated.notNull, annotated.nullable, manager) - ); + PsiJavaCodeReferenceElement annotationNameReferenceElement = annotation.getNameReferenceElement(); + holder.newProblem(LocalizeValue.localizeTODO( + "Not \'" + annotation.getQualifiedName() + "\' but \'" + anno + "\' would be used for code generation." + )) + .range( + annotationNameReferenceElement != null && annotationNameReferenceElement.isPhysical() + ? annotationNameReferenceElement + : field.getNameIdentifier() + ) + .withFixes(new ChangeNullableDefaultsFix(annotated.notNull, annotated.nullable, manager)) + .highlightType(ProblemHighlightType.WEAK_WARNING) + .create(); return false; } return true; @@ -489,83 +498,82 @@ private void checkAccessors( Annotated annotated, Project project, NullableNotNullManager manager, - final String anno, - final List annoToRemove, + String anno, + List annoToRemove, @Nonnull ProblemsHolder holder, NullableStuffInspectionState state ) { String propName = JavaCodeStyleManager.getInstance(project).variableNameToPropertyName(field.getName(), VariableKind.FIELD); - final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC); - final PsiMethod getter = PropertyUtilBase.findPropertyGetter(field.getContainingClass(), propName, isStatic, false); - final PsiIdentifier nameIdentifier = getter == null ? null : getter.getNameIdentifier(); + boolean isStatic = field.isStatic(); + PsiMethod getter = PropertyUtilBase.findPropertyGetter(field.getContainingClass(), propName, isStatic, false); + PsiIdentifier nameIdentifier = getter == null ? null : getter.getNameIdentifier(); if (nameIdentifier != null && nameIdentifier.isPhysical()) { if (PropertyUtil.getFieldOfGetter(getter) == field) { AnnotateMethodFix getterAnnoFix = new AnnotateMethodFix(anno, ArrayUtil.toStringArray(annoToRemove)); if (state.REPORT_NOT_ANNOTATED_GETTER) { if (!manager.hasNullability(getter) && !TypeConversionUtil.isPrimitiveAndNotNull(getter.getReturnType())) { - holder.registerProblem( - nameIdentifier, - InspectionLocalize.inspectionNullableProblemsAnnotatedFieldGetterNotAnnotated(getPresentableAnnoName(field)) - .get(), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - getterAnnoFix - ); + holder.newProblem(InspectionLocalize.inspectionNullableProblemsAnnotatedFieldGetterNotAnnotated( + getPresentableAnnoName(field) + )) + .range(nameIdentifier) + .withFixes(getterAnnoFix) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } } - if (annotated.isDeclaredNotNull && isNullableNotInferred(getter, false) || - annotated.isDeclaredNullable && isNotNullNotInferred(getter, false, false)) { - holder.registerProblem( - nameIdentifier, - InspectionLocalize.inspectionNullableProblemsAnnotatedFieldGetterConflict( + if (annotated.isDeclaredNotNull && isNullableNotInferred(getter, false) + || annotated.isDeclaredNullable && isNotNullNotInferred(getter, false, false)) { + holder.newProblem(InspectionLocalize.inspectionNullableProblemsAnnotatedFieldGetterConflict( getPresentableAnnoName(field), getPresentableAnnoName(getter) - ).get(), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - getterAnnoFix - ); + )) + .range(nameIdentifier) + .withFixes(getterAnnoFix) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } } } - final PsiClass containingClass = field.getContainingClass(); - final PsiMethod setter = PropertyUtilBase.findPropertySetter(containingClass, propName, isStatic, false); + PsiClass containingClass = field.getContainingClass(); + PsiMethod setter = PropertyUtilBase.findPropertySetter(containingClass, propName, isStatic, false); if (setter != null && setter.isPhysical() && PropertyUtil.getFieldOfSetter(setter) == field) { - final PsiParameter[] parameters = setter.getParameterList().getParameters(); + PsiParameter[] parameters = setter.getParameterList().getParameters(); assert parameters.length == 1 : setter.getText(); - final PsiParameter parameter = parameters[0]; + PsiParameter parameter = parameters[0]; LOG.assertTrue(parameter != null, setter.getText()); AddAnnotationPsiFix addAnnoFix = createAddAnnotationFix(anno, annoToRemove, parameter); - if (state.REPORT_NOT_ANNOTATED_GETTER && !manager.hasNullability(parameter) && !TypeConversionUtil.isPrimitiveAndNotNull( - parameter.getType())) { - final PsiIdentifier parameterName = parameter.getNameIdentifier(); + if (state.REPORT_NOT_ANNOTATED_GETTER && !manager.hasNullability(parameter) + && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) { + PsiIdentifier parameterName = parameter.getNameIdentifier(); assertValidElement(setter, parameter, parameterName); - holder.registerProblem( - parameterName, - InspectionLocalize.inspectionNullableProblemsAnnotatedFieldSetterParameterNotAnnotated(getPresentableAnnoName(field)) - .get(), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - addAnnoFix - ); + holder.newProblem(InspectionLocalize.inspectionNullableProblemsAnnotatedFieldSetterParameterNotAnnotated( + getPresentableAnnoName(field) + )) + .range(parameterName) + .withFixes(addAnnoFix) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } if (PropertyUtil.isSimpleSetter(setter)) { if (annotated.isDeclaredNotNull && isNullableNotInferred(parameter, false)) { - final PsiIdentifier parameterName = parameter.getNameIdentifier(); + PsiIdentifier parameterName = parameter.getNameIdentifier(); assertValidElement(setter, parameter, parameterName); - holder.registerProblem( - parameterName, - InspectionLocalize.inspectionNullableProblemsAnnotatedFieldSetterParameterConflict( + holder.newProblem(InspectionLocalize.inspectionNullableProblemsAnnotatedFieldSetterParameterConflict( getPresentableAnnoName(field), getPresentableAnnoName(parameter) - ).get(), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - addAnnoFix - ); + )) + .range(parameterName) + .withFixes(addAnnoFix) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } } } } @Nonnull + @RequiredReadAction private static AddAnnotationPsiFix createAddAnnotationFix(String anno, List annoToRemove, PsiParameter parameter) { return new AddAnnotationPsiFix(anno, parameter, PsiNameValuePair.EMPTY_ARRAY, ArrayUtil.toStringArray(annoToRemove)); } @@ -594,7 +602,7 @@ private void checkConstructorParameters( List notNullParams = new ArrayList<>(); - boolean isFinal = field.hasModifierProperty(PsiModifier.FINAL); + boolean isFinal = field.isFinal(); for (PsiExpression rhs : initializers) { if (rhs instanceof PsiReferenceExpression referenceExpression) { @@ -603,15 +611,15 @@ private void checkConstructorParameters( PsiParameter parameter = (PsiParameter)target; if (state.REPORT_NOT_ANNOTATED_GETTER && !manager.hasNullability(parameter) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) { - final PsiIdentifier nameIdentifier = parameter.getNameIdentifier(); + PsiIdentifier nameIdentifier = parameter.getNameIdentifier(); if (nameIdentifier != null && nameIdentifier.isPhysical()) { - holder.registerProblem( - nameIdentifier, - InspectionLocalize.inspectionNullableProblemsAnnotatedFieldConstructorParameterNotAnnotated( + holder.newProblem(InspectionLocalize.inspectionNullableProblemsAnnotatedFieldConstructorParameterNotAnnotated( getPresentableAnnoName(field) - ).get(), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, createAddAnnotationFix(anno, annoToRemove, parameter) - ); + )) + .range(nameIdentifier) + .withFixes(createAddAnnotationFix(anno, annoToRemove, parameter)) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); continue; } } @@ -632,12 +640,11 @@ ProblemHighlightType.GENERIC_ERROR_OR_WARNING, createAddAnnotationFix(anno, anno PsiIdentifier nameIdentifier = field.getNameIdentifier(); if (nameIdentifier.isPhysical()) { - holder.registerProblem( - nameIdentifier, - "@" + getPresentableAnnoName(field) + " field is always initialized not-null", - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - AddAnnotationPsiFix.createAddNotNullFix(field) - ); + holder.newProblem(LocalizeValue.localizeTODO("@" + getPresentableAnnoName(field) + " field is always initialized not-null")) + .range(nameIdentifier) + .withFixes(AddAnnotationPsiFix.createAddNotNullFix(field)) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } } @@ -686,7 +693,7 @@ static Annotated from(@Nonnull PsiModifierListOwner owner) { } } - private static Annotated check(final PsiModifierListOwner owner, final ProblemsHolder holder, PsiType type) { + private static Annotated check(PsiModifierListOwner owner, ProblemsHolder holder, PsiType type) { Annotated annotated = Annotated.from(owner); checkType(owner, holder, type, annotated.notNull, annotated.nullable); return annotated; @@ -725,22 +732,20 @@ private static void checkLoopParameterNullability( PsiParameter owner ) { if (notNull != null && expectedNullability == Nullability.NULLABLE) { - holder.registerProblem( - notNull, - "Parameter can be null", - new RemoveAnnotationQuickFix(notNull, null) - ); + holder.newProblem(LocalizeValue.localizeTODO("Parameter can be null")) + .range(notNull) + .withFixes(new RemoveAnnotationQuickFix(notNull, null)) + .create(); } else if (nullable != null && expectedNullability == Nullability.NOT_NULL) { if (nullable.getContainingFile() != owner.getContainingFile()) { return; } - holder.registerProblem( - nullable, - "Parameter is always not-null", - new RemoveAnnotationQuickFix(nullable, null) - ); + holder.newProblem(LocalizeValue.localizeTODO("Parameter is always not-null")) + .range(nullable) + .withFixes(new RemoveAnnotationQuickFix(nullable, null)) + .create(); } } @@ -749,12 +754,12 @@ private static void reportPrimitiveType( PsiAnnotation annotation, @Nullable PsiModifierListOwner listOwner ) { - holder.registerProblem( - !annotation.isPhysical() && listOwner != null ? listOwner.getNavigationElement() : annotation, - InspectionLocalize.inspectionNullableProblemsPrimitiveTypeAnnotation().get(), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - new RemoveAnnotationQuickFix(annotation, listOwner) - ); + PsiElement psiElement = !annotation.isPhysical() && listOwner != null ? listOwner.getNavigationElement() : annotation; + holder.newProblem(InspectionLocalize.inspectionNullableProblemsPrimitiveTypeAnnotation()) + .range(psiElement) + .withFixes(new RemoveAnnotationQuickFix(annotation, listOwner)) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } @Override @@ -775,9 +780,10 @@ public String getShortName() { return "NullableProblems"; } + @RequiredReadAction private void checkNullableStuffForMethod( PsiMethod method, - final ProblemsHolder holder, + ProblemsHolder holder, boolean isOnFly, NullableStuffInspectionState state ) { @@ -788,7 +794,7 @@ private void checkNullableStuffForMethod( MethodSignatureBackedByPsiMethod::getMethod ); - final NullableNotNullManager nullableManager = NullableNotNullManager.getInstance(holder.getProject()); + NullableNotNullManager nullableManager = NullableNotNullManager.getInstance(holder.getProject()); checkSupers(method, holder, annotated, superMethods, state); checkParameters(method, holder, superMethods, nullableManager, isOnFly, state); @@ -805,28 +811,27 @@ private void checkSupers( for (PsiMethod superMethod : superMethods) { if (isNullableOverridingNotNull(annotated, superMethod, state)) { PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, getNullityManager(method).getNullables(), true); - holder.registerProblem( - annotation != null ? annotation : method.getNameIdentifier(), - InspectionsBundle.message( + holder.newProblem(LocalizeValue.localizeTODO(InspectionsBundle.message( "inspection.nullable.problems.Nullable.method.overrides.NotNull", getPresentableAnnoName(method), getPresentableAnnoName(superMethod) - ), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING - ); + ))) + .range(annotation != null ? annotation : method.getNameIdentifier()) + .withFixes() + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); break; } if (isNonAnnotatedOverridingNotNull(method, superMethod, state)) { - holder.registerProblem( - method.getNameIdentifier(), - InspectionsBundle.message( + holder.newProblem(LocalizeValue.of(InspectionsBundle.message( "inspection.nullable.problems.method.overrides.NotNull", getPresentableAnnoName(superMethod) - ), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - createFixForNonAnnotatedOverridesNotNull(method, superMethod) - ); + ))) + .range(method.getNameIdentifier()) + .withFixes(createFixForNonAnnotatedOverridesNotNull(method, superMethod)) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); break; } } @@ -837,6 +842,7 @@ private static NullableNotNullManager getNullityManager(PsiMethod method) { } @Nullable + @RequiredReadAction private static LocalQuickFix createFixForNonAnnotatedOverridesNotNull( PsiMethod method, PsiMethod superMethod @@ -853,18 +859,19 @@ private boolean isNullableOverridingNotNull(Annotated methodInfo, PsiMethod supe } private boolean isNonAnnotatedOverridingNotNull(PsiMethod method, PsiMethod superMethod, NullableStuffInspectionState state) { - return state.REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL && - !(method.getReturnType() instanceof PsiPrimitiveType) && - !method.isConstructor() && - !getNullityManager(method).hasNullability(method) && - isNotNullNotInferred(superMethod, true, state.IGNORE_EXTERNAL_SUPER_NOTNULL) && - !hasInheritableNotNull(superMethod); + return state.REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL + && !(method.getReturnType() instanceof PsiPrimitiveType) + && !method.isConstructor() + && !getNullityManager(method).hasNullability(method) + && isNotNullNotInferred(superMethod, true, state.IGNORE_EXTERNAL_SUPER_NOTNULL) + && !hasInheritableNotNull(superMethod); } private static boolean hasInheritableNotNull(PsiModifierListOwner owner) { return AnnotationUtil.isAnnotated(owner, "javax.annotation.constraints.NotNull", CHECK_HIERARCHY | CHECK_TYPE); } + @RequiredReadAction private void checkParameters( PsiMethod method, ProblemsHolder holder, @@ -891,45 +898,43 @@ private void checkParameters( PsiParameter nullableSuper = findNullableSuperForNotNullParameter(parameter, superParameters, state); if (nullableSuper != null) { PsiAnnotation annotation = AnnotationUtil.findAnnotation(parameter, nullableManager.getNotNulls(), true); - holder.registerProblem( - annotation != null ? annotation : parameter.getNameIdentifier(), - InspectionsBundle.message( + holder.newProblem(LocalizeValue.of(InspectionsBundle.message( "inspection.nullable.problems.NotNull.parameter.overrides.Nullable", getPresentableAnnoName(parameter), getPresentableAnnoName(nullableSuper) - ), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING - ); + ))) + .range(annotation != null ? annotation : parameter.getNameIdentifier()) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } PsiParameter notNullSuper = findNotNullSuperForNonAnnotatedParameter(nullableManager, parameter, superParameters, state); if (notNullSuper != null) { LocalQuickFix fix = AnnotationUtil.isAnnotatingApplicable(parameter, nullableManager.getDefaultNotNull()) ? AddAnnotationPsiFix.createAddNotNullFix(parameter) : createChangeDefaultNotNullFix(nullableManager, notNullSuper); - holder.registerProblem( - parameter.getNameIdentifier(), - InspectionsBundle.message( + holder.newProblem(LocalizeValue.of(InspectionsBundle.message( "inspection.nullable.problems.parameter.overrides.NotNull", getPresentableAnnoName(notNullSuper) - ), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - fix - ); + ))) + .range(parameter.getNameIdentifier()) + .withFixes(fix) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } if (isNotNullParameterOverridingNonAnnotated(nullableManager, parameter, superParameters, state)) { NullabilityAnnotationInfo info = nullableManager.findOwnNullabilityInfo(parameter); assert info != null; PsiAnnotation notNullAnnotation = info.getAnnotation(); boolean physical = PsiTreeUtil.isAncestor(parameter, notNullAnnotation, true); - final LocalQuickFix fix = physical ? new RemoveAnnotationQuickFix(notNullAnnotation, parameter) : null; - holder.registerProblem( - physical ? notNullAnnotation : parameter.getNameIdentifier(), - JavaInspectionsLocalize.inspectionNullableProblemsNotnullParameterOverridesNotAnnotated( + LocalQuickFix fix = physical ? new RemoveAnnotationQuickFix(notNullAnnotation, parameter) : null; + PsiElement psiElement = physical ? notNullAnnotation : parameter.getNameIdentifier(); + holder.newProblem(JavaInspectionsLocalize.inspectionNullableProblemsNotnullParameterOverridesNotAnnotated( getPresentableAnnoName(parameter) - ).get(), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - fix - ); + )) + .range(psiElement) + .withFixes(fix) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } checkNullLiteralArgumentOfNotNullParameterUsages(method, holder, nullableManager, isOnFly, i, parameter, state); @@ -1006,17 +1011,17 @@ private void checkNullLiteralArgumentOfNotNullParameterUsages( return; } - holder.registerProblem( - elementToHighlight, - InspectionsBundle.message( + holder.newProblem(LocalizeValue.localizeTODO(InspectionsBundle.message( "inspection.nullable.problems.NotNull.parameter.receives.null.literal", getPresentableAnnoName(parameter) - ), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - createNavigateToNullParameterUsagesFix(parameter) - ); + ))) + .range(elementToHighlight) + .withFixes(createNavigateToNullParameterUsagesFix(parameter)) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } + @RequiredReadAction private void checkOverriders( @Nonnull PsiMethod method, @Nonnull ProblemsHolder holder, @@ -1039,10 +1044,9 @@ private void checkOverriders( boolean checkReturnType = annotated.isDeclaredNotNull && !hasInheritableNotNull(method) && !(method.getReturnType() instanceof PsiPrimitiveType); if (hasAnnotatedParameter || checkReturnType) { - final String defaultNotNull = nullableManager.getDefaultNotNull(); - final boolean superMethodApplicable = AnnotationUtil.isAnnotatingApplicable(method, defaultNotNull); - PsiMethod[] overridings = - OverridingMethodsSearch.search(method).toArray(PsiMethod.EMPTY_ARRAY); + String defaultNotNull = nullableManager.getDefaultNotNull(); + boolean superMethodApplicable = AnnotationUtil.isAnnotatingApplicable(method, defaultNotNull); + PsiMethod[] overridings = OverridingMethodsSearch.search(method).toArray(PsiMethod.EMPTY_ARRAY); boolean methodQuickFixSuggested = false; for (PsiMethod overriding : overridings) { if (shouldSkipOverriderAsGenerated(overriding)) { @@ -1056,7 +1060,7 @@ private void checkOverriders( && AddAnnotationPsiFix.isAvailable(overriding, defaultNotNull)) { PsiIdentifier identifier = method.getNameIdentifier();//load tree PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, nullableManager.getNotNulls()); - final String[] annotationsToRemove = ArrayUtil.toStringArray(nullableManager.getNullables()); + String[] annotationsToRemove = ArrayUtil.toStringArray(nullableManager.getNullables()); LocalQuickFix fix = AnnotationUtil.isAnnotatingApplicable(overriding, defaultNotNull) ? new MyAnnotateMethodFix(defaultNotNull, annotationsToRemove) @@ -1069,12 +1073,11 @@ private void checkOverriders( if (psiElement == null) { continue; } - holder.registerProblem( - psiElement, - InspectionLocalize.nullableStuffProblemsOverriddenMethodsAreNotAnnotated().get(), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - fix - ); + holder.newProblem(InspectionLocalize.nullableStuffProblemsOverriddenMethodsAreNotAnnotated()) + .range(psiElement) + .withFixes(fix) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); methodQuickFixSuggested = true; } if (hasAnnotatedParameter) { @@ -1101,12 +1104,11 @@ private void checkOverriders( LocalQuickFix fix = AnnotationUtil.isAnnotatingApplicable(parameter, defaultNotNull) ? new AnnotateOverriddenMethodParameterFix(defaultNotNull, nullableManager.getDefaultNullable()) : createChangeDefaultNotNullFix(nullableManager, parameters[i]); - holder.registerProblem( - psiElement, - InspectionLocalize.nullableStuffProblemsOverriddenMethodParametersAreNotAnnotated().get(), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - fix - ); + holder.newProblem(InspectionLocalize.nullableStuffProblemsOverriddenMethodParametersAreNotAnnotated()) + .range(psiElement) + .withFixes(fix) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); parameterQuickFixSuggested[i] = true; } } @@ -1152,14 +1154,14 @@ private static LocalQuickFix createChangeDefaultNotNullFix( NullableNotNullManager nullableManager, PsiModifierListOwner modifierListOwner ) { - final PsiAnnotation annotation = AnnotationUtil.findAnnotation(modifierListOwner, nullableManager.getNotNulls()); + PsiAnnotation annotation = AnnotationUtil.findAnnotation(modifierListOwner, nullableManager.getNotNulls()); if (annotation != null) { - final PsiJavaCodeReferenceElement referenceElement = annotation.getNameReferenceElement(); + PsiJavaCodeReferenceElement referenceElement = annotation.getNameReferenceElement(); if (referenceElement != null) { JavaResolveResult resolveResult = referenceElement.advancedResolve(false); - if (resolveResult.getElement() != null && - resolveResult.isValidResult() && - !nullableManager.getDefaultNotNull().equals(annotation.getQualifiedName())) { + if (resolveResult.getElement() != null + && resolveResult.isValidResult() + && !nullableManager.getDefaultNotNull().equals(annotation.getQualifiedName())) { return new ChangeNullableDefaultsFix(annotation.getQualifiedName(), null, nullableManager); } } @@ -1168,28 +1170,26 @@ private static LocalQuickFix createChangeDefaultNotNullFix( } private static void reportNullableNotNullConflict( - final ProblemsHolder holder, - final PsiModifierListOwner listOwner, - final PsiAnnotation declaredNullable, - final PsiAnnotation declaredNotNull + ProblemsHolder holder, + PsiModifierListOwner listOwner, + PsiAnnotation declaredNullable, + PsiAnnotation declaredNotNull ) { - final String bothNullableNotNullMessage = InspectionsBundle.message( + LocalizeValue bothNullableNotNullMessage = LocalizeValue.localizeTODO(InspectionsBundle.message( "inspection.nullable.problems.Nullable.NotNull.conflict", getPresentableAnnoName(declaredNullable), getPresentableAnnoName(declaredNotNull) - ); - holder.registerProblem( - declaredNotNull.isPhysical() ? declaredNotNull : listOwner.getNavigationElement(), - bothNullableNotNullMessage, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - new RemoveAnnotationQuickFix(declaredNotNull, listOwner) - ); - holder.registerProblem( - declaredNullable.isPhysical() ? declaredNullable : listOwner.getNavigationElement(), - bothNullableNotNullMessage, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - new RemoveAnnotationQuickFix(declaredNullable, listOwner) - ); + )); + holder.newProblem(bothNullableNotNullMessage) + .range(declaredNotNull.isPhysical() ? declaredNotNull : listOwner.getNavigationElement()) + .withFixes(new RemoveAnnotationQuickFix(declaredNotNull, listOwner)) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); + holder.newProblem(bothNullableNotNullMessage) + .range(declaredNullable.isPhysical() ? declaredNullable : listOwner.getNavigationElement()) + .withFixes(new RemoveAnnotationQuickFix(declaredNullable, listOwner)) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); } @Nonnull diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/psi/impl/source/resolve/reference/impl/JavaReflectionReferenceUtil.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/psi/impl/source/resolve/reference/impl/JavaReflectionReferenceUtil.java index 82ffe5f2ef..c0b1b20152 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/psi/impl/source/resolve/reference/impl/JavaReflectionReferenceUtil.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/psi/impl/source/resolve/reference/impl/JavaReflectionReferenceUtil.java @@ -10,9 +10,11 @@ import com.siyeh.ig.psiutils.DeclarationSearchUtils; import com.siyeh.ig.psiutils.ExpressionUtils; import com.siyeh.ig.psiutils.MethodCallUtils; +import consulo.annotation.access.RequiredReadAction; import consulo.application.util.RecursionGuard; import consulo.application.util.RecursionManager; import consulo.component.util.Iconable; +import consulo.java.language.module.util.JavaClassNames; import consulo.language.editor.completion.lookup.*; import consulo.language.icon.IconDescriptorUpdaters; import consulo.language.psi.PsiElement; @@ -97,26 +99,26 @@ public final class JavaReflectionReferenceUtil { private static final RecursionGuard ourGuard = RecursionManager.createGuard("JavaLangClassMemberReference"); @Contract("null -> null") + @RequiredReadAction public static ReflectiveType getReflectiveType(@Nullable PsiExpression context) { context = PsiUtil.skipParenthesizedExprDown(context); if (context == null) { return null; } - if (context instanceof PsiClassObjectAccessExpression) { - final PsiTypeElement operand = ((PsiClassObjectAccessExpression)context).getOperand(); + if (context instanceof PsiClassObjectAccessExpression classObjectAccess) { + PsiTypeElement operand = classObjectAccess.getOperand(); return ReflectiveType.create(operand.getType(), true); } - if (context instanceof PsiMethodCallExpression) { - final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)context; - final String methodReferenceName = methodCall.getMethodExpression().getReferenceName(); + if (context instanceof PsiMethodCallExpression methodCall) { + String methodReferenceName = methodCall.getMethodExpression().getReferenceName(); if (FOR_NAME.equals(methodReferenceName)) { - final PsiMethod method = methodCall.resolveMethod(); + PsiMethod method = methodCall.resolveMethod(); if (method != null && isJavaLangClass(method.getContainingClass())) { - final PsiExpression[] expressions = methodCall.getArgumentList().getExpressions(); + PsiExpression[] expressions = methodCall.getArgumentList().getExpressions(); if (expressions.length == 1) { - final PsiExpression argument = findDefinition(PsiUtil.skipParenthesizedExprDown(expressions[0])); - final String className = computeConstantExpression(argument, String.class); + PsiExpression argument = findDefinition(PsiUtil.skipParenthesizedExprDown(expressions[0])); + String className = computeConstantExpression(argument, String.class); if (className != null) { return ReflectiveType.create(findClass(className, context), true); } @@ -124,12 +126,12 @@ public static ReflectiveType getReflectiveType(@Nullable PsiExpression context) } } else if (GET_CLASS.equals(methodReferenceName) && methodCall.getArgumentList().isEmpty()) { - final PsiMethod method = methodCall.resolveMethod(); + PsiMethod method = methodCall.resolveMethod(); if (method != null && isJavaLangObject(method.getContainingClass())) { - final PsiExpression qualifier = + PsiExpression qualifier = PsiUtil.skipParenthesizedExprDown(methodCall.getMethodExpression().getQualifierExpression()); - if (qualifier instanceof PsiReferenceExpression) { - final PsiExpression definition = findVariableDefinition((PsiReferenceExpression)qualifier); + if (qualifier instanceof PsiReferenceExpression qRefExpr) { + PsiExpression definition = findVariableDefinition(qRefExpr); if (definition != null) { return getClassInstanceType(definition); } @@ -143,50 +145,42 @@ else if (GET_CLASS.equals(methodReferenceName) && methodCall.getArgumentList().i } } - if (context instanceof PsiReferenceExpression) { - PsiReferenceExpression reference = (PsiReferenceExpression)context; - final PsiElement resolved = reference.resolve(); - if (resolved instanceof PsiVariable) { - PsiVariable variable = (PsiVariable)resolved; - if (isJavaLangClass(PsiTypesUtil.getPsiClass(variable.getType()))) { - final PsiExpression definition = findVariableDefinition(reference, variable); - if (definition != null) { - ReflectiveType result = ourGuard.doPreventingRecursion(variable, false, () -> getReflectiveType(definition)); - if (result != null) { - return result; - } - } + if (context instanceof PsiReferenceExpression reference + && reference.resolve() instanceof PsiVariable variable + && isJavaLangClass(PsiTypesUtil.getPsiClass(variable.getType()))) { + PsiExpression definition = findVariableDefinition(reference, variable); + if (definition != null) { + ReflectiveType result = ourGuard.doPreventingRecursion(variable, false, () -> getReflectiveType(definition)); + if (result != null) { + return result; } } } - final PsiType type = context.getType(); - if (type instanceof PsiClassType) { - final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)type).resolveGenerics(); - final PsiClass resolvedElement = resolveResult.getElement(); + PsiType type = context.getType(); + if (type instanceof PsiClassType classType) { + PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics(); + PsiClass resolvedElement = resolveResult.getElement(); if (!isJavaLangClass(resolvedElement)) { return null; } - if (context instanceof PsiReferenceExpression && TYPE.equals(((PsiReferenceExpression)context).getReferenceName())) { - final PsiElement resolved = ((PsiReferenceExpression)context).resolve(); - if (resolved instanceof PsiField) { - final PsiField field = (PsiField)resolved; - if (field.hasModifierProperty(PsiModifier.FINAL) && field.hasModifierProperty(PsiModifier.STATIC)) { - final PsiType[] classTypeArguments = ((PsiClassType)type).getParameters(); - final PsiPrimitiveType unboxedType = classTypeArguments.length == 1 - ? PsiPrimitiveType.getUnboxedType(classTypeArguments[0]) : null; - if (unboxedType != null && field.getContainingClass() == PsiUtil.resolveClassInClassTypeOnly(classTypeArguments[0])) { - return ReflectiveType.create(unboxedType, true); - } - } + if (context instanceof PsiReferenceExpression refExpr + && TYPE.equals(refExpr.getReferenceName()) + && refExpr.resolve() instanceof PsiField field + && field.isFinal() && field.isStatic()) { + PsiType[] classTypeArguments = classType.getParameters(); + PsiPrimitiveType unboxedType = classTypeArguments.length == 1 + ? PsiPrimitiveType.getUnboxedType(classTypeArguments[0]) : null; + if (unboxedType != null && field.getContainingClass() == PsiUtil.resolveClassInClassTypeOnly(classTypeArguments[0])) { + return ReflectiveType.create(unboxedType, true); } } - final PsiTypeParameter[] parameters = resolvedElement.getTypeParameters(); + PsiTypeParameter[] parameters = resolvedElement.getTypeParameters(); if (parameters.length == 1) { - final PsiType typeArgument = resolveResult.getSubstitutor().substitute(parameters[0]); - final PsiType erasure = TypeConversionUtil.erasure(typeArgument); - final PsiClass argumentClass = PsiTypesUtil.getPsiClass(erasure); + PsiType typeArgument = resolveResult.getSubstitutor().substitute(parameters[0]); + PsiType erasure = TypeConversionUtil.erasure(typeArgument); + PsiClass argumentClass = PsiTypesUtil.getPsiClass(erasure); if (argumentClass != null && !isJavaLangObject(argumentClass)) { return ReflectiveType.create(argumentClass, false); } @@ -201,25 +195,24 @@ private static ReflectiveType getClassInstanceType(@Nullable PsiExpression expre if (expression == null) { return null; } - if (expression instanceof PsiMethodCallExpression) { - final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)expression; - final String methodReferenceName = methodCall.getMethodExpression().getReferenceName(); + if (expression instanceof PsiMethodCallExpression methodCall) { + String methodReferenceName = methodCall.getMethodExpression().getReferenceName(); if (NEW_INSTANCE.equals(methodReferenceName)) { - final PsiMethod method = methodCall.resolveMethod(); + PsiMethod method = methodCall.resolveMethod(); if (method != null) { - final PsiExpression[] arguments = methodCall.getArgumentList().getExpressions(); - if (arguments.length == 0 && isClassWithName(method.getContainingClass(), CommonClassNames.JAVA_LANG_CLASS)) { - final PsiExpression qualifier = methodCall.getMethodExpression().getQualifierExpression(); + PsiExpression[] arguments = methodCall.getArgumentList().getExpressions(); + if (arguments.length == 0 && isClassWithName(method.getContainingClass(), JavaClassNames.JAVA_LANG_CLASS)) { + PsiExpression qualifier = methodCall.getMethodExpression().getQualifierExpression(); if (qualifier != null) { return ourGuard.doPreventingRecursion(qualifier, false, () -> getReflectiveType(qualifier)); } } else if (arguments.length > 1 - && isClassWithName(method.getContainingClass(), CommonClassNames.JAVA_LANG_REFLECT_ARRAY)) { - final PsiExpression typeExpression = arguments[0]; + && isClassWithName(method.getContainingClass(), JavaClassNames.JAVA_LANG_REFLECT_ARRAY)) { + PsiExpression typeExpression = arguments[0]; if (typeExpression != null) { - final ReflectiveType itemType = + ReflectiveType itemType = ourGuard.doPreventingRecursion(typeExpression, false, () -> getReflectiveType(typeExpression)); return ReflectiveType.arrayOf(itemType); } @@ -234,32 +227,36 @@ && isClassWithName(method.getContainingClass(), CommonClassNames.JAVA_LANG_REFLE @Nullable public static T computeConstantExpression(@Nullable PsiExpression expression, @Nonnull Class expectedType) { expression = PsiUtil.skipParenthesizedExprDown(expression); - final Object computed = JavaConstantExpressionEvaluator.computeConstantExpression(expression, false); + Object computed = JavaConstantExpressionEvaluator.computeConstantExpression(expression, false); return ObjectUtil.tryCast(computed, expectedType); } @Nullable + @RequiredReadAction public static ReflectiveClass getReflectiveClass(PsiExpression context) { - final ReflectiveType reflectiveType = getReflectiveType(context); + ReflectiveType reflectiveType = getReflectiveType(context); return reflectiveType != null ? reflectiveType.getReflectiveClass() : null; } @Nullable + @RequiredReadAction public static PsiExpression findDefinition(@Nullable PsiExpression expression) { int preventEndlessLoop = 5; - while (expression instanceof PsiReferenceExpression) { + while (expression instanceof PsiReferenceExpression refExpr) { if (--preventEndlessLoop == 0) { return null; } - expression = findVariableDefinition((PsiReferenceExpression)expression); + expression = findVariableDefinition(refExpr); } return expression; } @Nullable + @RequiredReadAction private static PsiExpression findVariableDefinition(@Nonnull PsiReferenceExpression referenceExpression) { - final PsiElement resolved = referenceExpression.resolve(); - return resolved instanceof PsiVariable ? findVariableDefinition(referenceExpression, (PsiVariable)resolved) : null; + return referenceExpression.resolve() instanceof PsiVariable variable + ? findVariableDefinition(referenceExpression, variable) + : null; } @Nullable @@ -268,12 +265,12 @@ private static PsiExpression findVariableDefinition( @Nonnull PsiVariable variable ) { if (variable.hasModifierProperty(PsiModifier.FINAL)) { - final PsiExpression initializer = variable.getInitializer(); + PsiExpression initializer = variable.getInitializer(); if (initializer != null) { return initializer; } - if (variable instanceof PsiField) { - return findFinalFieldDefinition(referenceExpression, (PsiField)variable); + if (variable instanceof PsiField field) { + return findFinalFieldDefinition(referenceExpression, field); } } return DeclarationSearchUtils.findDefinition(referenceExpression, variable); @@ -281,24 +278,24 @@ private static PsiExpression findVariableDefinition( @Nullable private static PsiExpression findFinalFieldDefinition(@Nonnull PsiReferenceExpression referenceExpression, @Nonnull PsiField field) { - if (!field.hasModifierProperty(PsiModifier.FINAL)) { + if (!field.isFinal()) { return null; } - final PsiClass psiClass = ObjectUtil.tryCast(field.getParent(), PsiClass.class); + PsiClass psiClass = ObjectUtil.tryCast(field.getParent(), PsiClass.class); if (psiClass != null) { - final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC); - final List initializers = ContainerUtil.filter( + boolean isStatic = field.isStatic(); + List initializers = ContainerUtil.filter( psiClass.getInitializers(), - initializer -> initializer.hasModifierProperty(PsiModifier.STATIC) == isStatic + initializer -> initializer.isStatic() == isStatic ); for (PsiClassInitializer initializer : initializers) { - final PsiExpression assignedExpression = getAssignedExpression(initializer, field); + PsiExpression assignedExpression = getAssignedExpression(initializer, field); if (assignedExpression != null) { return assignedExpression; } } if (!isStatic) { - final PsiMethod[] constructors = psiClass.getConstructors(); + PsiMethod[] constructors = psiClass.getConstructors(); if (constructors.length == 1) { return getAssignedExpression(constructors[0], field); } @@ -314,25 +311,25 @@ private static PsiExpression findFinalFieldDefinition(@Nonnull PsiReferenceExpre @Nullable private static PsiExpression getAssignedExpression(@Nonnull PsiMember maybeContainsAssignment, @Nonnull PsiField field) { - final PsiAssignmentExpression assignment = SyntaxTraverser.psiTraverser(maybeContainsAssignment) + PsiAssignmentExpression assignment = SyntaxTraverser.psiTraverser(maybeContainsAssignment) .filter(PsiAssignmentExpression.class) .find(expression -> ExpressionUtils.isReferenceTo(expression.getLExpression(), field)); return assignment != null ? assignment.getRExpression() : null; } private static PsiClass findClass(@Nonnull String qualifiedName, @Nonnull PsiElement context) { - final Project project = context.getProject(); + Project project = context.getProject(); return JavaPsiFacade.getInstance(project).findClass(qualifiedName, GlobalSearchScope.allScope(project)); } @Contract("null -> false") public static boolean isJavaLangClass(@Nullable PsiClass aClass) { - return isClassWithName(aClass, CommonClassNames.JAVA_LANG_CLASS); + return isClassWithName(aClass, JavaClassNames.JAVA_LANG_CLASS); } @Contract("null -> false") public static boolean isJavaLangObject(@Nullable PsiClass aClass) { - return isClassWithName(aClass, CommonClassNames.JAVA_LANG_OBJECT); + return isClassWithName(aClass, JavaClassNames.JAVA_LANG_OBJECT); } @Contract("null, _ -> false") @@ -346,30 +343,30 @@ public static boolean isRegularMethod(@Nullable PsiMethod method) { } public static boolean isPublic(@Nonnull PsiMember member) { - return member.hasModifierProperty(PsiModifier.PUBLIC); + return member.isPublic(); } public static boolean isAtomicallyUpdateable(@Nonnull PsiField field) { - if (field.hasModifierProperty(PsiModifier.STATIC) || !field.hasModifierProperty(PsiModifier.VOLATILE)) { + if (field.isStatic() || !field.hasModifierProperty(PsiModifier.VOLATILE)) { return false; } - final PsiType type = field.getType(); + PsiType type = field.getType(); return !(type instanceof PsiPrimitiveType) || PsiType.INT.equals(type) || PsiType.LONG.equals(type); } @Nullable public static String getParameterTypesText(@Nonnull PsiMethod method) { - final StringJoiner joiner = new StringJoiner(", "); + StringJoiner joiner = new StringJoiner(", "); for (PsiParameter parameter : method.getParameterList().getParameters()) { - final String typeText = getTypeText(parameter.getType()); + String typeText = getTypeText(parameter.getType()); joiner.add(typeText + ".class"); } return joiner.toString(); } public static void shortenArgumentsClassReferences(@Nonnull InsertionContext context) { - final PsiElement parameter = PsiUtilCore.getElementAtOffset(context.getFile(), context.getStartOffset()); - final PsiExpressionList parameterList = PsiTreeUtil.getParentOfType(parameter, PsiExpressionList.class); + PsiElement parameter = PsiUtilCore.getElementAtOffset(context.getFile(), context.getStartOffset()); + PsiExpressionList parameterList = PsiTreeUtil.getParentOfType(parameter, PsiExpressionList.class); if (parameterList != null && parameterList.getParent() instanceof PsiMethodCallExpression) { JavaCodeStyleManager.getInstance(context.getProject()).shortenClassReferences(parameterList); } @@ -391,26 +388,28 @@ public static int getMethodSortOrder(@Nonnull PsiMethod method) { @Nullable public static String getMemberType(@Nullable PsiElement element) { - final PsiMethodCallExpression methodCall = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class); + PsiMethodCallExpression methodCall = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class); return methodCall != null ? methodCall.getMethodExpression().getReferenceName() : null; } @Nullable + @RequiredReadAction public static LookupElement lookupMethod(@Nonnull PsiMethod method, @Nullable InsertHandler insertHandler) { - final ReflectiveSignature signature = getMethodSignature(method); + ReflectiveSignature signature = getMethodSignature(method); return signature != null ? LookupElementBuilder.create(signature, method.getName()) - .withIcon(signature.getIcon()) - .withTailText(signature.getShortArgumentTypes()) - .withInsertHandler(insertHandler) + .withIcon(signature.getIcon()) + .withTailText(signature.getShortArgumentTypes()) + .withInsertHandler(insertHandler) : null; } + @RequiredReadAction public static void replaceText(@Nonnull InsertionContext context, @Nonnull String text) { - final PsiElement newElement = PsiUtilCore.getElementAtOffset(context.getFile(), context.getStartOffset()); - final PsiElement params = newElement.getParent().getParent(); - final int end = params.getTextRange().getEndOffset() - 1; - final int start = Math.min(newElement.getTextRange().getEndOffset(), end); + PsiElement newElement = PsiUtilCore.getElementAtOffset(context.getFile(), context.getStartOffset()); + PsiElement params = newElement.getParent().getParent(); + int end = params.getTextRange().getEndOffset() - 1; + int start = Math.min(newElement.getTextRange().getEndOffset(), end); context.getDocument().replaceString(start, end, text); context.commitDocument(); @@ -419,28 +418,30 @@ public static void replaceText(@Nonnull InsertionContext context, @Nonnull Strin @Nonnull public static String getTypeText(@Nonnull PsiType type) { - final ReflectiveType reflectiveType = ReflectiveType.create(type, false); + ReflectiveType reflectiveType = ReflectiveType.create(type, false); return reflectiveType.getQualifiedName(); } @Nullable + @RequiredReadAction public static String getTypeText(@Nullable PsiExpression argument) { - final ReflectiveType reflectiveType = getReflectiveType(argument); + ReflectiveType reflectiveType = getReflectiveType(argument); return reflectiveType != null ? reflectiveType.getQualifiedName() : null; } @Contract("null -> null") @Nullable + @RequiredReadAction public static ReflectiveSignature getMethodSignature(@Nullable PsiMethod method) { if (method != null) { - final List types = new ArrayList<>(); - final PsiType returnType = method.getReturnType(); + List types = new ArrayList<>(); + PsiType returnType = method.getReturnType(); types.add(getTypeText(returnType != null ? returnType : PsiType.VOID)); // null return type means it's a constructor for (PsiParameter parameter : method.getParameterList().getParameters()) { types.add(getTypeText(parameter.getType())); } - final Image icon = IconDescriptorUpdaters.getIcon(method, Iconable.ICON_FLAG_VISIBILITY); + Image icon = IconDescriptorUpdaters.getIcon(method, Iconable.ICON_FLAG_VISIBILITY); return ReflectiveSignature.create(icon, types); } return null; @@ -448,7 +449,7 @@ public static ReflectiveSignature getMethodSignature(@Nullable PsiMethod method) @Nonnull public static String getMethodTypeExpressionText(@Nonnull ReflectiveSignature signature) { - final String types = signature.getText(true, type -> type + ".class"); + String types = signature.getText(true, type -> type + ".class"); return JAVA_LANG_INVOKE_METHOD_TYPE + "." + METHOD_TYPE + types; } @@ -457,7 +458,7 @@ public static boolean isCallToMethod( @Nonnull String className, @Nonnull String methodName ) { - return MethodCallUtils.isCallToMethod(methodCall, className, null, methodName, (PsiType[])null); + return MethodCallUtils.isCallToMethod(methodCall, className, null, methodName); } /** @@ -468,23 +469,24 @@ public static boolean isCallToMethod( * returns null if nothing is known. */ @Nullable + @RequiredReadAction public static List getVarargs(@Nullable PsiExpression maybeArray) { if (ExpressionUtils.isNullLiteral(maybeArray)) { return Collections.emptyList(); } if (isVarargAsArray(maybeArray)) { - final PsiExpression argumentsDefinition = findDefinition(maybeArray); - if (argumentsDefinition instanceof PsiArrayInitializerExpression) { - return Arrays.asList(((PsiArrayInitializerExpression)argumentsDefinition).getInitializers()); + PsiExpression argumentsDefinition = findDefinition(maybeArray); + if (argumentsDefinition instanceof PsiArrayInitializerExpression arrayInitializer) { + return Arrays.asList(arrayInitializer.getInitializers()); } - if (argumentsDefinition instanceof PsiNewExpression) { - final PsiArrayInitializerExpression arrayInitializer = ((PsiNewExpression)argumentsDefinition).getArrayInitializer(); + if (argumentsDefinition instanceof PsiNewExpression newExpr) { + PsiArrayInitializerExpression arrayInitializer = newExpr.getArrayInitializer(); if (arrayInitializer != null) { return Arrays.asList(arrayInitializer.getInitializers()); } - final PsiExpression[] dimensions = ((PsiNewExpression)argumentsDefinition).getArrayDimensions(); + PsiExpression[] dimensions = newExpr.getArrayDimensions(); if (dimensions.length == 1) { // new Object[length] or new Class[length] - final Integer itemCount = computeConstantExpression(findDefinition(dimensions[0]), Integer.class); + Integer itemCount = computeConstantExpression(findDefinition(dimensions[0]), Integer.class); if (itemCount != null && itemCount >= 0 && itemCount < 256) { return Collections.nCopies(itemCount, null); } @@ -496,10 +498,10 @@ public static List getVarargs(@Nullable PsiExpression maybeArray) @Contract("null -> false") public static boolean isVarargAsArray(@Nullable PsiExpression maybeArray) { - final PsiType type = maybeArray != null ? maybeArray.getType() : null; - return type instanceof PsiArrayType && - type.getArrayDimensions() == 1 && - type.getDeepComponentType() instanceof PsiClassType; + return maybeArray != null + && maybeArray.getType() instanceof PsiArrayType arrayType + && arrayType.getArrayDimensions() == 1 + && arrayType.getDeepComponentType() instanceof PsiClassType; } /** @@ -507,11 +509,11 @@ public static boolean isVarargAsArray(@Nullable PsiExpression maybeArray) { * from arguments of MethodType.methodType(Class...) and MethodType.genericMethodType(int, boolean?) */ @Nullable + @RequiredReadAction public static ReflectiveSignature composeMethodSignature(@Nullable PsiExpression methodTypeExpression) { - final PsiExpression typeDefinition = findDefinition(methodTypeExpression); - if (typeDefinition instanceof PsiMethodCallExpression) { - final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)typeDefinition; - final String referenceName = methodCallExpression.getMethodExpression().getReferenceName(); + PsiExpression typeDefinition = findDefinition(methodTypeExpression); + if (typeDefinition instanceof PsiMethodCallExpression methodCallExpression) { + String referenceName = methodCallExpression.getMethodExpression().getReferenceName(); Function composer = null; if (METHOD_TYPE.equals(referenceName)) { @@ -522,11 +524,11 @@ else if (GENERIC_METHOD_TYPE.equals(referenceName)) { } if (composer != null) { - final PsiMethod method = methodCallExpression.resolveMethod(); + PsiMethod method = methodCallExpression.resolveMethod(); if (method != null) { - final PsiClass psiClass = method.getContainingClass(); + PsiClass psiClass = method.getContainingClass(); if (psiClass != null && JAVA_LANG_INVOKE_METHOD_TYPE.equals(psiClass.getQualifiedName())) { - final PsiExpression[] arguments = methodCallExpression.getArgumentList().getExpressions(); + PsiExpression[] arguments = methodCallExpression.getArgumentList().getExpressions(); return composer.apply(arguments); } } @@ -537,7 +539,7 @@ else if (GENERIC_METHOD_TYPE.equals(referenceName)) { @Nullable private static ReflectiveSignature composeMethodSignatureFromTypes(@Nonnull PsiExpression[] returnAndParameterTypes) { - final List typeTexts = ContainerUtil.map(returnAndParameterTypes, JavaReflectionReferenceUtil::getTypeText); + List typeTexts = ContainerUtil.map(returnAndParameterTypes, JavaReflectionReferenceUtil::getTypeText); return ReflectiveSignature.create(typeTexts); } @@ -547,8 +549,8 @@ public static Pair.NonNull getGenericSignature(@Nonnull PsiExp return null; } - final Integer objectArgCount = computeConstantExpression(genericSignatureShape[0], Integer.class); - final Boolean finalArray = // there's an additional parameter which is an ellipsis or an array + Integer objectArgCount = computeConstantExpression(genericSignatureShape[0], Integer.class); + Boolean finalArray = // there's an additional parameter which is an ellipsis or an array genericSignatureShape.length > 1 ? computeConstantExpression(genericSignatureShape[1], Boolean.class) : false; if (objectArgCount == null || objectArgCount < 0 || objectArgCount > 255) { @@ -565,21 +567,21 @@ public static Pair.NonNull getGenericSignature(@Nonnull PsiExp */ @Nullable private static ReflectiveSignature composeGenericMethodSignature(@Nonnull PsiExpression[] genericSignatureShape) { - final Pair.NonNull signature = getGenericSignature(genericSignatureShape); + Pair.NonNull signature = getGenericSignature(genericSignatureShape); if (signature == null) { return null; } - final int objectArgCount = signature.getFirst(); - final boolean finalArray = signature.getSecond(); + int objectArgCount = signature.getFirst(); + boolean finalArray = signature.getSecond(); - final List typeNames = new ArrayList<>(); - typeNames.add(CommonClassNames.JAVA_LANG_OBJECT); // return type + List typeNames = new ArrayList<>(); + typeNames.add(JavaClassNames.JAVA_LANG_OBJECT); // return type for (int i = 0; i < objectArgCount; i++) { - typeNames.add(CommonClassNames.JAVA_LANG_OBJECT); + typeNames.add(JavaClassNames.JAVA_LANG_OBJECT); } if (finalArray) { - typeNames.add(CommonClassNames.JAVA_LANG_OBJECT + "[]"); + typeNames.add(JavaClassNames.JAVA_LANG_OBJECT + "[]"); } return ReflectiveSignature.create(typeNames); } @@ -636,11 +638,7 @@ public ReflectiveClass getReflectiveClass() { @Nullable public ReflectiveType getArrayComponentType() { - if (myType instanceof PsiArrayType) { - PsiType componentType = ((PsiArrayType)myType).getComponentType(); - return new ReflectiveType(componentType, myIsExact); - } - return null; + return myType instanceof PsiArrayType arrayType ? new ReflectiveType(arrayType.getComponentType(), myIsExact) : null; } @Nullable @@ -661,7 +659,7 @@ public static ReflectiveType create(@Nullable PsiType originalType, boolean isEx @Nullable public static ReflectiveType create(@Nullable PsiClass psiClass, boolean isExact) { if (psiClass != null) { - final PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); return new ReflectiveType(factory.createType(psiClass), isExact); } return null; @@ -678,9 +676,9 @@ public static ReflectiveType arrayOf(@Nullable ReflectiveType itemType) { @Nonnull private static PsiType erasure(@Nonnull PsiType type) { - final PsiType erasure = TypeConversionUtil.erasure(type); - if (erasure instanceof PsiEllipsisType) { - return ((PsiEllipsisType)erasure).toArrayType(); + PsiType erasure = TypeConversionUtil.erasure(type); + if (erasure instanceof PsiEllipsisType ellipsisType) { + return ellipsisType.toArrayType(); } return erasure; } @@ -701,7 +699,7 @@ public PsiClass getPsiClass() { } public boolean isExact() { - return myIsExact || myPsiClass.hasModifierProperty(PsiModifier.FINAL); + return myIsExact || myPsiClass.isFinal(); } } @@ -723,7 +721,7 @@ public static ReflectiveSignature create(@Nonnull List typeTexts) { @Nullable public static ReflectiveSignature create(@Nullable Image icon, @Nonnull List typeTexts) { if (!typeTexts.isEmpty() && !typeTexts.contains(null)) { - final String[] argumentTypes = ArrayUtil.toStringArray(typeTexts.subList(1, typeTexts.size())); + String[] argumentTypes = ArrayUtil.toStringArray(typeTexts.subList(1, typeTexts.size())); return new ReflectiveSignature(icon, typeTexts.get(0), argumentTypes); } return null; @@ -740,7 +738,7 @@ public String getText(boolean withReturnType, @Nonnull Function transformation) { - final StringJoiner joiner = new StringJoiner(", ", withParentheses ? "(" : "", withParentheses ? ")" : ""); + StringJoiner joiner = new StringJoiner(", ", withParentheses ? "(" : "", withParentheses ? ")" : ""); if (withReturnType) { joiner.add(transformation.apply(myReturnType)); } @@ -780,15 +778,10 @@ public int compareTo(@Nonnull ReflectiveSignature other) { @Override public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof ReflectiveSignature)) { - return false; - } - final ReflectiveSignature other = (ReflectiveSignature)o; - return Objects.equals(myReturnType, other.myReturnType) && - Arrays.equals(myArgumentTypes, other.myArgumentTypes); + return o == this + || o instanceof ReflectiveSignature that + && Objects.equals(myReturnType, that.myReturnType) + && Arrays.equals(myArgumentTypes, that.myArgumentTypes); } @Override