[java-completion] IDEA-339251 IDEA: make Postfix templates dumb aware

GitOrigin-RevId: 082102197a4a06457685b5d6cd94e7296e51d8db
This commit is contained in:
Tagir Valeev
2024-01-12 18:46:51 +00:00
committed by intellij-monorepo-bot
parent 96cab71873
commit fc3e5df389
69 changed files with 442 additions and 257 deletions
@@ -21,6 +21,7 @@ import com.intellij.codeInspection.dataFlow.memory.DfaMemoryState;
import com.intellij.codeInspection.dataFlow.memory.DfaMemoryStateImpl;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
@@ -36,6 +37,7 @@ import com.intellij.util.BitUtil;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.indexing.DumbModeAccessType;
import com.siyeh.ig.callMatcher.CallMatcher;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NotNull;
@@ -295,7 +297,8 @@ public final class GuessManagerImpl extends GuessManager {
PsiManager manager = PsiManager.getInstance(myProject);
PsiElementProcessor.CollectElementsWithLimit<PsiClass> processor = new PsiElementProcessor.CollectElementsWithLimit<>(5);
ClassInheritorsSearch.search(refClass).forEach(new PsiElementProcessorAdapter<>(processor));
DumbModeAccessType.RELIABLE_DATA_ONLY.ignoreDumbMode(
() -> ClassInheritorsSearch.search(refClass).forEach(new PsiElementProcessorAdapter<>(processor)));
if (processor.isOverflow()) return;
for (PsiClass derivedClass : processor.getCollection()) {
@@ -425,27 +428,33 @@ public final class GuessManagerImpl extends GuessManager {
PsiExpression place = PsiUtil.skipParenthesizedExprDown(expr);
if (place == null) return Collections.emptyList();
List<PsiType> result = null;
if (!ControlFlowAnalyzer.inlinerMayInferPreciseType(place)) {
GuessTypeVisitor visitor = tryGuessingTypeWithoutDfa(place, honorAssignments);
if (!visitor.isDfaNeeded()) {
result = visitor.mySpecificType == null ?
Collections.emptyList() : Collections.singletonList(DfaPsiUtil.tryGenerify(expr, visitor.mySpecificType));
DumbService dumbService = DumbService.getInstance(myProject);
PsiType type = dumbService.computeWithAlternativeResolveEnabled(() -> {
if (!ControlFlowAnalyzer.inlinerMayInferPreciseType(place)) {
GuessTypeVisitor visitor = tryGuessingTypeWithoutDfa(place, honorAssignments);
if (!visitor.isDfaNeeded()) return visitor.mySpecificType;
}
return getTypeFromDataflow(expr, honorAssignments);
});
return dumbService.computeWithAlternativeResolveEnabled(() -> postFilter(expr, type));
}
@NotNull
private static List<PsiType> flattenAndGenerify(@NotNull PsiExpression expr, PsiType psiType) {
if (psiType instanceof PsiIntersectionType intersection) {
return ContainerUtil.mapNotNull(intersection.getConjuncts(), type -> DfaPsiUtil.tryGenerify(expr, type));
}
if (result == null) {
PsiType psiType = getTypeFromDataflow(expr, honorAssignments);
if (psiType instanceof PsiIntersectionType intersection) {
result = ContainerUtil.mapNotNull(intersection.getConjuncts(), type -> DfaPsiUtil.tryGenerify(expr, type));
}
else if (psiType != null) {
result = Collections.singletonList(DfaPsiUtil.tryGenerify(expr, psiType));
}
else {
result = Collections.emptyList();
}
else if (psiType != null) {
return Collections.singletonList(DfaPsiUtil.tryGenerify(expr, psiType));
}
result = ContainerUtil.filter(result, t -> {
else {
return Collections.emptyList();
}
}
@NotNull
private static List<PsiType> postFilter(@NotNull PsiExpression expr, PsiType type) {
List<PsiType> result = ContainerUtil.filter(flattenAndGenerify(expr, type), t -> {
PsiClass typeClass = PsiUtil.resolveClassInType(t);
return typeClass == null || PsiUtil.isAccessible(typeClass, expr, null);
});
@@ -5,6 +5,7 @@ import com.intellij.codeInsight.JavaPsiEquivalenceUtil;
import com.intellij.codeInsight.Nullability;
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.augment.PsiAugmentProvider;
@@ -89,6 +90,7 @@ public final class NullabilityUtil {
expression.getType() instanceof PsiPrimitiveType) {
return Nullability.NOT_NULL;
}
boolean dumb = DumbService.isDumb(expression.getProject());
if (expression instanceof PsiConditionalExpression) {
PsiExpression thenExpression = ((PsiConditionalExpression)expression).getThenExpression();
PsiExpression elseExpression = ((PsiConditionalExpression)expression).getElseExpression();
@@ -104,7 +106,7 @@ public final class NullabilityUtil {
if (ref != null && JavaPsiEquivalenceUtil.areExpressionsEquivalent(ref, thenExpression)) {
return getExpressionNullability(elseExpression, useDataflow);
}
if (useDataflow) {
if (useDataflow && !dumb) {
return DfaNullability.toNullability(DfaNullability.fromDfType(CommonDataflow.getDfType(expression)));
}
Nullability left = getExpressionNullability(thenExpression, false);
@@ -121,7 +123,7 @@ public final class NullabilityUtil {
}
return Nullability.NOT_NULL;
}
if (useDataflow) {
if (useDataflow && !dumb) {
return DfaNullability.toNullability(DfaNullability.fromDfType(CommonDataflow.getDfType(expression)));
}
if (expression instanceof PsiReferenceExpression ref) {
@@ -129,6 +131,7 @@ public final class NullabilityUtil {
if (target instanceof PsiPatternVariable) {
return Nullability.NOT_NULL; // currently all pattern variables are not-null
}
if (dumb) return Nullability.UNKNOWN;
if (target instanceof PsiLocalVariable || target instanceof PsiParameter) {
PsiElement block = PsiUtil.getVariableCodeBlock((PsiVariable)target, null);
// Do not trust the declared nullability of local variable/parameter if it's reassigned as nullability designates
@@ -138,6 +141,7 @@ public final class NullabilityUtil {
return DfaPsiUtil.getElementNullabilityIgnoringParameterInference(expression.getType(), (PsiModifierListOwner)target);
}
if (expression instanceof PsiMethodCallExpression || expression instanceof PsiTemplateExpression) {
if (dumb) return Nullability.UNKNOWN;
PsiMethod method = ((PsiCall)expression).resolveMethod();
return method != null ? DfaPsiUtil.getElementNullability(expression.getType(), method) : Nullability.UNKNOWN;
}
@@ -7,6 +7,7 @@ import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.NlsContexts;
@@ -53,7 +54,8 @@ public abstract class AbstractJavaInplaceIntroducer extends AbstractInplaceIntro
final String propertyName = variable != null
? JavaCodeStyleManager.getInstance(myProject).variableNameToPropertyName(variable.getName(), VariableKind.LOCAL_VARIABLE)
: null;
mySuggestedNameInfo = suggestNames(defaultType, propertyName);
mySuggestedNameInfo =
DumbService.getInstance(myProject).computeWithAlternativeResolveEnabled(() -> suggestNames(defaultType, propertyName));
final String[] names = mySuggestedNameInfo.names;
if (propertyName != null && names.length > 1) {
final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(myProject);
@@ -92,7 +94,7 @@ public abstract class AbstractJavaInplaceIntroducer extends AbstractInplaceIntro
@Override
protected void restoreState(@NotNull PsiVariable psiField) {
final SmartTypePointer typePointer = SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(getType());
super.restoreState(psiField);
DumbService.getInstance(myProject).withAlternativeResolveEnabled(() -> super.restoreState(psiField));
for (PsiExpression occurrence : myOccurrences) {
if (!occurrence.isValid()) return;
}
@@ -4,6 +4,7 @@ package com.intellij.refactoring.introduceField;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NlsContexts;
import com.intellij.openapi.vfs.VirtualFile;
@@ -112,20 +113,23 @@ public abstract class AbstractInplaceIntroduceFieldPopup extends AbstractJavaInp
}
protected void performIntroduce(BaseExpressionToFieldHandler.Settings settings) {
WriteCommandAction.writeCommandAction(myProject).withName(getCommandName()).withGroupId(getCommandName()).run(() -> {
if (getLocalVariable() != null) {
final LocalToFieldHandler.IntroduceFieldRunnable fieldRunnable =
new LocalToFieldHandler.IntroduceFieldRunnable(false, (PsiLocalVariable)getLocalVariable(), getParentClass(), settings, myOccurrences);
fieldRunnable.run();
updateVariable(fieldRunnable.getField());
}
else {
final BaseExpressionToFieldHandler.ConvertToFieldRunnable convertToFieldRunnable =
new BaseExpressionToFieldHandler.ConvertToFieldRunnable(myExpr, settings, settings.getForcedType(), myOccurrences,
getAnchorElementIfAll(), getAnchorElement(), myEditor, getParentClass());
convertToFieldRunnable.run();
updateVariable(convertToFieldRunnable.getField());
}
});
WriteCommandAction.writeCommandAction(myProject).withName(getCommandName()).withGroupId(getCommandName()).run(
() -> DumbService.getInstance(myProject).runWithAlternativeResolveEnabled(() -> {
if (getLocalVariable() != null) {
final LocalToFieldHandler.IntroduceFieldRunnable fieldRunnable =
new LocalToFieldHandler.IntroduceFieldRunnable(false, (PsiLocalVariable)getLocalVariable(), getParentClass(), settings,
myOccurrences);
fieldRunnable.run();
updateVariable(fieldRunnable.getField());
}
else {
final BaseExpressionToFieldHandler.ConvertToFieldRunnable convertToFieldRunnable =
new BaseExpressionToFieldHandler.ConvertToFieldRunnable(myExpr, settings, settings.getForcedType(), myOccurrences,
getAnchorElementIfAll(), getAnchorElement(), myEditor,
getParentClass());
convertToFieldRunnable.run();
updateVariable(convertToFieldRunnable.getField());
}
}));
}
}
@@ -2,8 +2,8 @@
package com.intellij.refactoring.introduceField;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.SuggestedNameInfo;
@@ -72,7 +72,7 @@ public class InplaceIntroduceFieldPopup extends AbstractInplaceIntroduceFieldPop
protected PsiField createFieldToStartTemplateOn(final String[] names,
final PsiType defaultType) {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
final PsiField field = WriteAction.compute(() -> {
final PsiField field = WriteAction.compute(() -> DumbService.getInstance(myProject).computeWithAlternativeResolveEnabled(() -> {
PsiField field1 = elementFactory.createField(chooseName(names, getParentClass().getLanguage()), defaultType);
PsiUtil.setModifierProperty(field1, PsiModifier.FINAL, myIntroduceFieldPanel.isDeclareFinal());
PsiUtil.setModifierProperty(field1, PsiModifier.STATIC, myStatic);
@@ -86,7 +86,7 @@ public class InplaceIntroduceFieldPopup extends AbstractInplaceIntroduceFieldPop
}
updateVariable(field1);
return field1;
});
}));
PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(myEditor.getDocument());
return field;
}
@@ -5,6 +5,7 @@ import com.intellij.codeInsight.TestFrameworks;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
@@ -149,7 +150,7 @@ public class IntroduceFieldPopupPanel extends IntroduceFieldCentralPanel {
myInitialisersPlaceModel.addElement(BaseExpressionToFieldHandler.InitializationPlace.IN_CURRENT_METHOD);
myInitialisersPlaceModel.addElement(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION);
myInitialisersPlaceModel.addElement(BaseExpressionToFieldHandler.InitializationPlace.IN_CONSTRUCTOR);
if (TestFrameworks.getInstance().isTestClass(myParentClass)) {
if (!DumbService.isDumb(myParentClass.getProject()) && TestFrameworks.getInstance().isTestClass(myParentClass)) {
myInitialisersPlaceModel.addElement(BaseExpressionToFieldHandler.InitializationPlace.IN_SETUP_METHOD);
}
initializeInitializerPlace(myInitializerExpression, IntroduceFieldDialog.ourLastInitializerPlace);
@@ -22,6 +22,7 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
@@ -324,7 +325,9 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
}
final PsiType originalType = CommonJavaRefactoringUtil.getTypeByExpressionWithExpectedType(expr);
DumbService dumbService = DumbService.getInstance(project);
final PsiType originalType =
dumbService.computeWithAlternativeResolveEnabled(() -> CommonJavaRefactoringUtil.getTypeByExpressionWithExpectedType(expr));
if (originalType == null || LambdaUtil.notInferredType(originalType)) {
String message = RefactoringBundle.getCannotRefactorMessage(JavaRefactoringBundle.message("unknown.expression.type"));
showErrorMessage(project, editor, message);
@@ -401,7 +404,8 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
}
else {
SlowOperations.allowSlowOperations(
() -> inplaceIntroduce(project, editor, choice, targetContainer, occurrenceManager, originalType, dialogIntroduce));
() -> dumbService.runWithAlternativeResolveEnabled(
() -> inplaceIntroduce(project, editor, choice, targetContainer, occurrenceManager, originalType, dialogIntroduce)));
}
}
@@ -915,7 +919,8 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
if (parent == null) return null;
PsiType type = expression.getType();
PsiLambdaExpression lambda = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class, true, PsiStatement.class);
ChainCallExtractor extractor = ChainCallExtractor.findExtractor(lambda, expression, type);
ChainCallExtractor extractor = DumbService.getInstance(expression.getProject())
.computeWithAlternativeResolveEnabled(() -> ChainCallExtractor.findExtractor(lambda, expression, type));
if (extractor == null) return null;
PsiParameter parameter = lambda.getParameterList().getParameters()[0];
if (!ReferencesSearch.search(parameter).forEach((Processor<PsiReference>)ref ->
@@ -17,6 +17,7 @@ import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NlsContexts;
import com.intellij.openapi.util.Pair;
@@ -333,7 +334,7 @@ public class JavaVariableInplaceIntroducer extends AbstractJavaInplaceIntroducer
}
}
if (psiVariable != null && psiVariable.isValid()) {
createCastInVariableDeclaration(project, psiVariable);
DumbService.getInstance(project).runWithAlternativeResolveEnabled(() -> createCastInVariableDeclaration(project, psiVariable));
}
}
@@ -11,6 +11,7 @@ import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.VisualPosition;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Disposer;
@@ -132,7 +133,7 @@ public final class ReassignVariableUtil {
scope instanceof PsiClassInitializer) break;
scope = scope.getParent();
}
if (scope == null) return proc;
if (scope == null || DumbService.isDumb(scope.getProject())) return proc;
PsiScopesUtil.treeWalkUp(proc, declaration, scope);
return proc;
}
@@ -15,6 +15,7 @@ import com.intellij.openapi.diagnostic.RuntimeExceptionWithAttachments;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
@@ -296,18 +297,20 @@ final class VariableExtractor {
if (type == null) {
throw new IncorrectOperationException("Unexpected empty type pointer");
}
PsiDeclarationStatement probe = JavaPsiFacade.getElementFactory(expression.getProject())
.createVariableDeclarationStatement("x", TypeUtils.getObjectType(expression), null, expression);
Project project = expression.getProject();
NullabilityAnnotationInfo nullabilityAnnotationInfo =
NullableNotNullManager.getInstance(project).findExplicitNullability((PsiLocalVariable)probe.getDeclaredElements()[0]);
NullabilityAnnotationInfo info = DfaPsiUtil.getTypeNullabilityInfo(type);
if (info != null && nullabilityAnnotationInfo != null && info.getNullability() != nullabilityAnnotationInfo.getNullability() &&
// The type nullability could be inherited from hierarchy. E.g. if the type is type parameter T,
// which is defined as <T extends @NotNull Foo>. In this case we should not add @NotNull explicitly
ArrayUtil.contains(info.getAnnotation(), type.getAnnotations())) {
return type.annotate(TypeAnnotationProvider.Static.create(new PsiAnnotation[]{info.getAnnotation()}));
if (!DumbService.isDumb(expression.getProject())) {
// NullableNotNullManager doesn't work well in dumb mode
PsiDeclarationStatement probe = JavaPsiFacade.getElementFactory(expression.getProject())
.createVariableDeclarationStatement("x", TypeUtils.getObjectType(expression), null, expression);
Project project = expression.getProject();
NullabilityAnnotationInfo nullabilityAnnotationInfo =
NullableNotNullManager.getInstance(project).findExplicitNullability((PsiLocalVariable)probe.getDeclaredElements()[0]);
NullabilityAnnotationInfo info = DfaPsiUtil.getTypeNullabilityInfo(type);
if (info != null && nullabilityAnnotationInfo != null && info.getNullability() != nullabilityAnnotationInfo.getNullability() &&
// The type nullability could be inherited from hierarchy. E.g. if the type is type parameter T,
// which is defined as <T extends @NotNull Foo>. In this case we should not add @NotNull explicitly
ArrayUtil.contains(info.getAnnotation(), type.getAnnotations())) {
return type.annotate(TypeAnnotationProvider.Static.create(new PsiAnnotation[]{info.getAnnotation()}));
}
}
return type.annotate(TypeAnnotationProvider.EMPTY);
}
@@ -11,6 +11,7 @@ import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.codeInspection.dataFlow.DfaPsiUtil;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtilEx;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -84,7 +85,8 @@ class JavaClassNameInsertHandler implements InsertHandler<JavaPsiClassReferenceE
context.setAddCompletionChar(false);
}
PsiTypeLookupItem.addImportForItem(context, psiClass);
PsiClass finalPsiClass = psiClass;
DumbService.getInstance(project).runWithAlternativeResolveEnabled(() -> PsiTypeLookupItem.addImportForItem(context, finalPsiClass));
if (!context.getOffsetMap().containsOffset(refEnd)) {
return;
}
@@ -214,7 +216,8 @@ class JavaClassNameInsertHandler implements InsertHandler<JavaPsiClassReferenceE
final PsiElement prevElement = FilterPositionUtil.searchNonSpaceNonCommentBack(ref);
if (prevElement != null && prevElement.getParent() instanceof PsiNewExpression) {
return !isArrayTypeExpected((PsiExpression)prevElement.getParent());
return !DumbService.getInstance(position.getProject())
.computeWithAlternativeResolveEnabled(() -> isArrayTypeExpected((PsiExpression)prevElement.getParent()));
}
return false;
@@ -43,10 +43,7 @@ import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.util.*;
import com.intellij.psi.util.proximity.ReferenceListWeigher;
import com.intellij.ui.JBColor;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ObjectUtils;
import com.intellij.util.PairFunction;
import com.intellij.util.ThreeState;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.JBIterable;
import com.siyeh.ig.psiutils.SideEffectChecker;
@@ -660,7 +657,7 @@ public final class JavaCompletionUtil {
Document document = FileDocumentManager.getInstance().getDocument(file.getViewProvider().getVirtualFile());
PsiReference reference = file.findReferenceAt(startOffset);
if (reference != null && manager.areElementsEquivalent(psiClass, reference.resolve())) {
if (reference != null && manager.areElementsEquivalent(psiClass, resolve(project, reference))) {
return endOffset;
}
@@ -744,13 +741,20 @@ public final class JavaCompletionUtil {
return newEndOffset;
}
@Nullable
private static PsiElement resolve(Project project, PsiReference reference) {
return DumbService.getInstance(project).computeWithAlternativeResolveEnabled(reference::resolve);
}
@Nullable
static PsiElement resolveReference(PsiReference psiReference) {
if (psiReference instanceof PsiPolyVariantReference) {
ResolveResult[] results = ((PsiPolyVariantReference)psiReference).multiResolve(true);
if (results.length == 1) return results[0].getElement();
}
return psiReference.resolve();
return DumbService.getInstance(psiReference.getElement().getProject()).computeWithAlternativeResolveEnabled(() -> {
if (psiReference instanceof PsiPolyVariantReference) {
ResolveResult[] results = ((PsiPolyVariantReference)psiReference).multiResolve(true);
if (results.length == 1) return results[0].getElement();
}
return psiReference.resolve();
});
}
@Nullable
@@ -4,6 +4,7 @@ package com.intellij.codeInsight.generation.surroundWith;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.java.JavaBundle;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.TextRange;
@@ -14,6 +15,7 @@ import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ig.psiutils.VariableNameGenerator;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
@@ -41,15 +43,63 @@ public class JavaWithTryCatchSurrounder extends JavaStatementsSurrounder {
}
@Nullable
public TextRange doSurround(Project project, PsiElement container, PsiElement[] statements) {
public TextRange doSurround(Project project, PsiElement container, PsiElement[] origStatements) {
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
statements = SurroundWithUtil.moveDeclarationsOut(container, statements, true);
PsiElement[] statements = SurroundWithUtil.moveDeclarationsOut(container, origStatements, true);
if (statements.length == 0) {
return null;
}
return DumbService.getInstance(project).computeWithAlternativeResolveEnabled(() -> {
List<PsiClassType> exceptions = getExceptionTypes(container, statements, factory);
@NonNls StringBuilder buffer = new StringBuilder();
buffer.append("try{\n}");
for (PsiClassType ignored : exceptions) {
buffer.append("catch(Exception e){\n}");
}
if (myGenerateFinally) {
buffer.append("finally{\n}");
}
String text = buffer.toString();
PsiTryStatement tryStatement = (PsiTryStatement)factory.createStatementFromText(text, null);
tryStatement = (PsiTryStatement)CodeStyleManager.getInstance(project).reformat(tryStatement);
tryStatement = (PsiTryStatement)addAfter(tryStatement, container, statements);
PsiCodeBlock tryBlock = tryStatement.getTryBlock();
SurroundWithUtil.indentCommentIfNecessary(tryBlock, statements);
addRangeWithinContainer(tryBlock, container, statements, true);
PsiCatchSection[] catchSections = tryStatement.getCatchSections();
for (int i = 0; i < exceptions.size(); i++) {
PsiClassType exception = exceptions.get(i);
PsiClass target = exception.resolve();
if (target instanceof PsiTypeParameter) {
PsiClassType[] extendsListTypes = target.getExtendsListTypes();
if (extendsListTypes.length > 0) {
exception = extendsListTypes[0];
}
}
String name =
new VariableNameGenerator(tryBlock, VariableKind.PARAMETER).byName("e", "ex", "exc").byType(exception).generate(false);
PsiCatchSection catchSection = factory.createCatchSection(exception, name, tryBlock);
catchSection = (PsiCatchSection)catchSections[i].replace(catchSection);
codeStyleManager.shortenClassReferences(catchSection);
}
container.deleteChildRange(statements[0], statements[statements.length - 1]);
PsiCodeBlock firstCatch = tryStatement.getCatchBlocks()[0];
return SurroundWithUtil.getRangeToSelect(firstCatch);
});
}
@NotNull
private static List<PsiClassType> getExceptionTypes(PsiElement container, PsiElement[] statements, PsiElementFactory factory) {
List<PsiClassType> exceptions = ExceptionUtil.getUnhandledExceptions(statements);
if (exceptions.isEmpty()) {
exceptions = ExceptionUtil.getThrownExceptions(statements);
@@ -57,45 +107,6 @@ public class JavaWithTryCatchSurrounder extends JavaStatementsSurrounder {
exceptions = Collections.singletonList(factory.createTypeByFQClassName("java.lang.Exception", container.getResolveScope()));
}
}
@NonNls StringBuilder buffer = new StringBuilder();
buffer.append("try{\n}");
for (PsiClassType ignored : exceptions) {
buffer.append("catch(Exception e){\n}");
}
if (myGenerateFinally) {
buffer.append("finally{\n}");
}
String text = buffer.toString();
PsiTryStatement tryStatement = (PsiTryStatement)factory.createStatementFromText(text, null);
tryStatement = (PsiTryStatement)CodeStyleManager.getInstance(project).reformat(tryStatement);
tryStatement = (PsiTryStatement)addAfter(tryStatement, container, statements);
PsiCodeBlock tryBlock = tryStatement.getTryBlock();
SurroundWithUtil.indentCommentIfNecessary(tryBlock, statements);
addRangeWithinContainer(tryBlock, container, statements, true);
PsiCatchSection[] catchSections = tryStatement.getCatchSections();
for (int i = 0; i < exceptions.size(); i++) {
PsiClassType exception = exceptions.get(i);
PsiClass target = exception.resolve();
if (target instanceof PsiTypeParameter) {
PsiClassType[] extendsListTypes = target.getExtendsListTypes();
if (extendsListTypes.length > 0) {
exception = extendsListTypes[0];
}
}
String name = new VariableNameGenerator(tryBlock, VariableKind.PARAMETER).byName("e", "ex", "exc").byType(exception).generate(false);
PsiCatchSection catchSection = factory.createCatchSection(exception, name, tryBlock);
catchSection = (PsiCatchSection)catchSections[i].replace(catchSection);
codeStyleManager.shortenClassReferences(catchSection);
}
container.deleteChildRange(statements[0], statements[statements.length - 1]);
PsiCodeBlock firstCatch = tryStatement.getCatchBlocks()[0];
return SurroundWithUtil.getRangeToSelect(firstCatch);
return exceptions;
}
}
@@ -7,6 +7,8 @@ import com.intellij.diagnostic.CoreAttachmentFactory;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ClassConditionKey;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -216,14 +218,17 @@ public final class PsiTypeLookupItem extends LookupItem<Object> implements Typed
int bracketsCount,
boolean diamond,
InsertHandler<PsiTypeLookupItem> importFixer) {
if (type instanceof PsiClassType) {
PsiClassType.ClassResolveResult classResolveResult = ((PsiClassType)type).resolveGenerics();
if (type instanceof PsiClassType classType) {
PsiClassType.ClassResolveResult classResolveResult = classType.resolveGenerics();
final PsiClass psiClass = classResolveResult.getElement();
if (psiClass != null) {
String name = psiClass.getName();
if (name != null) {
PsiClass resolved = JavaPsiFacade.getInstance(psiClass.getProject()).getResolveHelper().resolveReferencedClass(name, context);
Project project = psiClass.getProject();
DumbService service = DumbService.getInstance(project);
PsiResolveHelper helper = JavaPsiFacade.getInstance(project).getResolveHelper();
PsiClass resolved = service.computeWithAlternativeResolveEnabled(() -> helper.resolveReferencedClass(name, context));
String[] allStrings;
if (!psiClass.getManager().areElementsEquivalent(resolved, psiClass)) {
// inner class name should be shown qualified if it's not accessible by single name
@@ -5,6 +5,8 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.lookup.LookupFocusDegree;
import com.intellij.codeInsight.template.*;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -54,11 +56,13 @@ public final class SuggestVariableNameMacro extends Macro {
}
private static String[] getNames (final ExpressionContext context) {
String[] names = ExpressionUtil.getNames(context);
Project project = context.getProject();
DumbService dumbService = DumbService.getInstance(project);
String[] names = dumbService.computeWithAlternativeResolveEnabled(() -> ExpressionUtil.getNames(context));
if (names == null || names.length == 0) return names;
PsiFile file = PsiDocumentManager.getInstance(context.getProject()).getPsiFile(context.getEditor().getDocument());
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(context.getEditor().getDocument());
PsiElement e = file.findElementAt(context.getStartOffset());
PsiVariable[] vars = MacroUtil.getVariablesVisibleAt(e, "");
PsiVariable[] vars = dumbService.computeWithAlternativeResolveEnabled(() -> MacroUtil.getVariablesVisibleAt(e, ""));
LinkedList<String> namesList = new LinkedList<>(Arrays.asList(names));
for (PsiVariable var : vars) {
if (e.equals(var.getNameIdentifier())) continue;
@@ -4,13 +4,14 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class ArgumentPostfixTemplate extends JavaEditablePostfixTemplate {
public class ArgumentPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public ArgumentPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("arg",
"$CALL$($EXPR$$END$)",
@@ -3,12 +3,13 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class AssertStatementPostfixTemplate extends JavaEditablePostfixTemplate {
public class AssertStatementPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public AssertStatementPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("assert", "assert $EXPR$;$END$", "assert expr",
Collections.singleton(new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateBooleanExpressionCondition()),
@@ -17,13 +17,14 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.generation.surroundWith.JavaWithCastSurrounder;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.DumbAware;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorAllExpressionsWithCurrentOffset;
public class CastExpressionPostfixTemplate extends PostfixTemplateWithExpressionSelector {
public class CastExpressionPostfixTemplate extends PostfixTemplateWithExpressionSelector implements DumbAware {
public CastExpressionPostfixTemplate() {
super("cast", "((SomeType) expr)", selectorAllExpressionsWithCurrentOffset(IS_NON_VOID));
}
@@ -11,6 +11,8 @@ import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.impl.ConstantNode;
import com.intellij.codeInsight.template.impl.MacroCallNode;
import com.intellij.codeInsight.template.macro.SuggestVariableNameMacro;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbService;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiFile;
@@ -27,7 +29,7 @@ import java.util.Set;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorTopmost;
public class CastVarPostfixTemplate extends StringBasedPostfixTemplate {
public class CastVarPostfixTemplate extends StringBasedPostfixTemplate implements DumbAware {
private static final String TYPE_VAR = "typeVar";
private static final @NonNls String VAR_NAME = "varName";
@@ -60,14 +62,21 @@ public class CastVarPostfixTemplate extends StringBasedPostfixTemplate {
}
private static void fill(@NotNull Template template, PsiType @NotNull [] suggestedTypes, @NotNull PsiElement context) {
Set<LookupElement> itemSet = new LinkedHashSet<>();
for (PsiType type : suggestedTypes) {
itemSet.add(PsiTypeLookupItem.createLookupItem(type, null));
}
Set<LookupElement> itemSet =
DumbService.getInstance(context.getProject()).computeWithAlternativeResolveEnabled(() -> createLookupItems(suggestedTypes));
final Result result = suggestedTypes.length > 0 ? new PsiTypeResult(suggestedTypes[0], context.getProject()) : null;
Expression expr = new ConstantNode(result).withLookupItems(itemSet.size() > 1 ? itemSet : Collections.emptyList());
template.addVariable(TYPE_VAR, expr, expr, true);
}
@NotNull
private static Set<LookupElement> createLookupItems(PsiType @NotNull [] suggestedTypes) {
Set<LookupElement> itemSet = new LinkedHashSet<>();
for (PsiType type : suggestedTypes) {
itemSet.add(PsiTypeLookupItem.createLookupItem(type, null));
}
return itemSet;
}
}
@@ -17,13 +17,14 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.generation.surroundWith.JavaWithIfExpressionSurrounder;
import com.intellij.lang.surroundWith.Surrounder;
import com.intellij.openapi.project.DumbAware;
import org.jetbrains.annotations.NotNull;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_BOOLEAN;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorTopmost;
public class ElseStatementPostfixTemplate extends ElseExpressionPostfixTemplateBase {
public class ElseStatementPostfixTemplate extends ElseExpressionPostfixTemplateBase implements DumbAware {
public ElseStatementPostfixTemplate() {
super(JAVA_PSI_INFO, selectorTopmost(IS_BOOLEAN));
}
@@ -7,6 +7,7 @@ import com.intellij.codeInsight.template.impl.TextExpression;
import com.intellij.codeInsight.template.macro.SuggestVariableNameMacro;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiElement;
@@ -18,7 +19,7 @@ import org.jetbrains.annotations.Nullable;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.*;
public abstract class ForIndexedPostfixTemplate extends JavaEditablePostfixTemplate {
public abstract class ForIndexedPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
protected ForIndexedPostfixTemplate(@NotNull String templateName, @NotNull String templateText, @NotNull String example,
@NotNull JavaPostfixTemplateProvider provider) {
super(templateName, templateText, example,
@@ -9,6 +9,7 @@ import com.intellij.codeInsight.template.macro.IterableComponentTypeMacro;
import com.intellij.codeInsight.template.macro.SuggestVariableNameMacro;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiElement;
@@ -16,7 +17,7 @@ import com.intellij.psi.codeStyle.JavaFileCodeStyleFacade;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
public class ForeachPostfixTemplate extends JavaEditablePostfixTemplate {
public class ForeachPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public ForeachPostfixTemplate(@NotNull String templateName, @NotNull JavaPostfixTemplateProvider provider) {
super(templateName, "for ($FINAL$$TYPE$ $NAME$ : $EXPR$) {\n $END$\n}", "for (T item : expr)",
ContainerUtil.newHashSet(new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateArrayExpressionCondition(),
@@ -3,13 +3,14 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.CommonClassNames;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class FormatPostfixTemplate extends JavaEditablePostfixTemplate {
public class FormatPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public FormatPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("format",
"String.format($EXPR$, $END$)",
@@ -17,17 +17,15 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.generation.surroundWith.JavaWithIfExpressionSurrounder;
import com.intellij.lang.surroundWith.Surrounder;
import com.intellij.openapi.project.DumbAware;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiParenthesizedExpression;
import com.intellij.util.CommonJavaRefactoringUtil;
import org.jetbrains.annotations.NotNull;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_BOOLEAN;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorTopmost;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.*;
public class IfStatementPostfixTemplate extends IfPostfixTemplateBase {
public class IfStatementPostfixTemplate extends IfPostfixTemplateBase implements DumbAware {
public IfStatementPostfixTemplate() {
super(JAVA_PSI_INFO, selectorTopmost(IS_BOOLEAN));
}
@@ -25,9 +25,11 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.introduceField.ElementToWorkOn;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
@@ -36,7 +38,7 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
public class InstanceofExpressionPostfixTemplate extends PostfixTemplate {
public class InstanceofExpressionPostfixTemplate extends PostfixTemplate implements DumbAware {
public InstanceofExpressionPostfixTemplate() {
this("instanceof");
@@ -48,7 +50,7 @@ public class InstanceofExpressionPostfixTemplate extends PostfixTemplate {
@Override
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
if (context instanceof PsiJavaToken && ((PsiJavaToken)context).getTokenType().equals(JavaTokenType.STRING_LITERAL)) {
if (PsiUtil.isJavaToken(context, JavaTokenType.STRING_LITERAL)) {
// Do not suggest inside String literals as it could be confusing if literal is interpreted as the reference
return false;
}
@@ -4,6 +4,7 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.lang.LanguageRefactoringSupport;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.DumbAware;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.introduceField.JavaIntroduceFieldHandlerBase;
import org.jetbrains.annotations.NotNull;
@@ -11,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorAllExpressionsWithCurrentOffset;
public class IntroduceFieldPostfixTemplate extends PostfixTemplateWithExpressionSelector {
public class IntroduceFieldPostfixTemplate extends PostfixTemplateWithExpressionSelector implements DumbAware {
public IntroduceFieldPostfixTemplate() {
super("field", "myField = expr", selectorAllExpressionsWithCurrentOffset(IS_NON_VOID));
}
@@ -6,6 +6,7 @@ import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.project.DumbAware;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
import com.intellij.refactoring.introduceVariable.JavaIntroduceVariableHandlerBase;
@@ -15,7 +16,7 @@ import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplate
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorAllExpressionsWithCurrentOffset;
// todo: support for int[].var (parses as .class access!)
public class IntroduceVariablePostfixTemplate extends PostfixTemplateWithExpressionSelector {
public class IntroduceVariablePostfixTemplate extends PostfixTemplateWithExpressionSelector implements DumbAware {
public IntroduceVariablePostfixTemplate() {
super("var", "T name = expr", selectorAllExpressionsWithCurrentOffset(IS_NON_VOID));
}
@@ -17,13 +17,14 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.generation.surroundWith.JavaWithIfExpressionSurrounder;
import com.intellij.lang.surroundWith.Surrounder;
import com.intellij.openapi.project.DumbAware;
import org.jetbrains.annotations.NotNull;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NOT_PRIMITIVE;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorTopmost;
public class IsNullCheckPostfixTemplate extends SurroundPostfixTemplateBase {
public class IsNullCheckPostfixTemplate extends SurroundPostfixTemplateBase implements DumbAware {
public IsNullCheckPostfixTemplate() {
super("null", "if (expr == null)", JAVA_PSI_INFO, selectorTopmost(IS_NOT_PRIMITIVE));
}
@@ -2,12 +2,13 @@
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class LambdaPostfixTemplate extends JavaEditablePostfixTemplate {
public class LambdaPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public LambdaPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("lambda", "() -> $EXPR$", "() -> expr",
Collections.emptySet(), LanguageLevel.JDK_1_8, true, provider);
@@ -7,6 +7,8 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.TextRange;
@@ -17,7 +19,7 @@ import org.jetbrains.annotations.Nullable;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorAllExpressionsWithCurrentOffset;
public class NewExpressionPostfixTemplate extends StringBasedPostfixTemplate {
public class NewExpressionPostfixTemplate extends StringBasedPostfixTemplate implements DumbAware {
private static final Condition<PsiElement> CONSTRUCTOR = expression -> {
PsiReferenceExpression ref = expression instanceof PsiMethodCallExpression call ? call.getMethodExpression() :
expression instanceof PsiReferenceExpression r ? r :
@@ -26,19 +28,21 @@ public class NewExpressionPostfixTemplate extends StringBasedPostfixTemplate {
PsiExpression qualifier = ref.getQualifierExpression();
JavaResolveResult result = ref.advancedResolve(true);
PsiElement element = result.getElement();
return DumbService.getInstance(ref.getProject()).computeWithAlternativeResolveEnabled(() -> {
JavaResolveResult result = ref.advancedResolve(true);
PsiElement element = result.getElement();
//todo implement proper support for Foo<Bar>, Foo.new Bar()
if (qualifier != null && (!(qualifier instanceof PsiReferenceExpression) || element == null)) return false;
//todo implement proper support for Foo<Bar>, Foo.new Bar()
if (qualifier != null && (!(qualifier instanceof PsiReferenceExpression) || element == null)) return false;
if (element == null) return true;
if (!(element instanceof PsiClass cls)) return false;
PsiMethod[] constructors = cls.getConstructors();
if (constructors.length == 0) return true;
PsiResolveHelper helper = JavaPsiFacade.getInstance(element.getProject()).getResolveHelper();
// Check whether there's at least one accessible constructor
return !ContainerUtil.and(constructors, m -> !helper.isAccessible(m, ref, cls));
if (element == null) return true;
if (!(element instanceof PsiClass cls)) return false;
PsiMethod[] constructors = cls.getConstructors();
if (constructors.length == 0) return true;
PsiResolveHelper helper = JavaPsiFacade.getInstance(element.getProject()).getResolveHelper();
// Check whether there's at least one accessible constructor
return !ContainerUtil.and(constructors, m -> !helper.isAccessible(m, ref, cls));
});
};
protected NewExpressionPostfixTemplate() {
@@ -15,11 +15,13 @@
*/
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.openapi.project.DumbAware;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_BOOLEAN;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorAllExpressionsWithCurrentOffset;
public class NotExpressionPostfixTemplate extends NotPostfixTemplate {
public class NotExpressionPostfixTemplate extends NotPostfixTemplate implements DumbAware {
public NotExpressionPostfixTemplate() {
super(JAVA_PSI_INFO, selectorAllExpressionsWithCurrentOffset(IS_BOOLEAN));
@@ -17,13 +17,14 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.generation.surroundWith.JavaWithIfExpressionSurrounder;
import com.intellij.lang.surroundWith.Surrounder;
import com.intellij.openapi.project.DumbAware;
import org.jetbrains.annotations.NotNull;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NOT_PRIMITIVE;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorTopmost;
public class NotNullCheckPostfixTemplate extends SurroundPostfixTemplateBase {
public class NotNullCheckPostfixTemplate extends SurroundPostfixTemplateBase implements DumbAware {
public NotNullCheckPostfixTemplate() {
this("notnull");
@@ -3,12 +3,13 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class ObjectsRequireNonNullPostfixTemplate extends JavaEditablePostfixTemplate {
public class ObjectsRequireNonNullPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public ObjectsRequireNonNullPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("reqnonnull",
"java.util.Objects.requireNonNull($EXPR$)",
@@ -7,13 +7,14 @@ import com.intellij.codeInsight.template.impl.TextExpression;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.codeInspection.dataFlow.NullabilityUtil;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class OptionalPostfixTemplate extends JavaEditablePostfixTemplate {
public class OptionalPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public OptionalPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("opt",
"java.util.$OPTIONAL_CLASS$.$OPTIONAL_METHOD$($EXPR$)",
@@ -15,11 +15,13 @@
*/
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.openapi.project.DumbAware;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorAllExpressionsWithCurrentOffset;
public class ParenthesizedExpressionPostfixTemplate extends ParenthesizedPostfixTemplate {
public class ParenthesizedExpressionPostfixTemplate extends ParenthesizedPostfixTemplate implements DumbAware {
public ParenthesizedExpressionPostfixTemplate() {
super(JAVA_PSI_INFO, selectorAllExpressionsWithCurrentOffset(IS_NON_VOID));
}
@@ -3,12 +3,13 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class ReturnStatementPostfixTemplate extends JavaEditablePostfixTemplate {
public class ReturnStatementPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public ReturnStatementPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("return",
"return $EXPR$;$END$",
@@ -3,12 +3,13 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class SerrPostfixTemplate extends JavaEditablePostfixTemplate {
public class SerrPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public SerrPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("serr",
"System.err.println($EXPR$);$END$",
@@ -3,12 +3,13 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class SoufPostfixTemplate extends JavaEditablePostfixTemplate {
public class SoufPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public SoufPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("souf",
"System.out.printf(\"$END$\", $EXPR$);",
@@ -3,12 +3,13 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class SoutPostfixTemplate extends JavaEditablePostfixTemplate {
public class SoutPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public SoutPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("sout",
"System.out.println($EXPR$);$END$",
@@ -4,13 +4,14 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class SoutvPostfixTemplate extends JavaEditablePostfixTemplate {
public class SoutvPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public SoutvPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("soutv",
"System.out.println(\"$EXPR_COPY$ = \" + $EXPR$);$END$",
@@ -16,6 +16,7 @@
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
@@ -23,7 +24,7 @@ import org.jetbrains.annotations.Nullable;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.selectorAllExpressionsWithCurrentOffset;
public class StreamPostfixTemplate extends StringBasedPostfixTemplate {
public class StreamPostfixTemplate extends StringBasedPostfixTemplate implements DumbAware {
private static final Condition<PsiElement> IS_SUPPORTED_ARRAY = element -> {
if (!(element instanceof PsiExpression)) return false;
@@ -20,10 +20,7 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.indexing.DumbModeAccessType;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -32,48 +29,30 @@ import static com.intellij.openapi.util.Conditions.and;
public class SwitchStatementPostfixTemplate extends SurroundPostfixTemplateBase implements DumbAware {
private static final Condition<PsiElement> SWITCH_TYPE = expression -> {
if (!(expression instanceof PsiExpression)) return false;
private static final Condition<PsiElement> SWITCH_TYPE = e -> {
if (!(e instanceof PsiExpression expression)) return false;
final PsiType type = getType((PsiExpression)expression);
return DumbService.getInstance(expression.getProject()).computeWithAlternativeResolveEnabled(() -> {
final PsiType type = expression.getType();
if (type == null) return false;
if (PsiTypes.intType().isAssignableFrom(type)) return true;
if (type instanceof PsiClassType) {
if (HighlightingFeature.PATTERNS_IN_SWITCH.isAvailable(expression)) return true;
if (type == null) return false;
if (PsiTypes.intType().isAssignableFrom(type)) return true;
if (type instanceof PsiClassType classType) {
if (HighlightingFeature.PATTERNS_IN_SWITCH.isAvailable(expression)) return true;
final PsiClass psiClass = getClassType(expression.getProject(), (PsiClassType)type);
if (psiClass != null && psiClass.isEnum()) return true;
}
final PsiClass psiClass = classType.resolve();
if (psiClass != null && psiClass.isEnum()) return true;
}
if (type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
PsiFile containingFile = expression.getContainingFile();
if (containingFile instanceof PsiJavaFile) {
LanguageLevel level = ((PsiJavaFile)containingFile).getLanguageLevel();
if (type.equalsToText(CommonClassNames.JAVA_LANG_STRING) && expression.getContainingFile() instanceof PsiJavaFile javaFile) {
LanguageLevel level = javaFile.getLanguageLevel();
if (level.isAtLeast(LanguageLevel.JDK_1_7)) return true;
}
}
return false;
return false;
});
};
@Contract(pure = true)
private static @Nullable PsiType getType(@NotNull PsiExpression expression) {
if (!DumbService.isDumb(expression.getProject())) {
return expression.getType();
}
return DumbModeAccessType.RELIABLE_DATA_ONLY.ignoreDumbMode(expression::getType);
}
@Contract(pure = true)
private static @Nullable PsiClass getClassType(@NotNull Project project, @NotNull PsiClassType type) {
if (!DumbService.isDumb(project)) {
return type.resolve();
}
return DumbModeAccessType.RELIABLE_DATA_ONLY.ignoreDumbMode(type::resolve);
}
public SwitchStatementPostfixTemplate() {
super("switch", "switch(expr)", JavaPostfixTemplatesUtils.JAVA_PSI_INFO, selectorTopmost(SWITCH_TYPE));
}
@@ -3,12 +3,13 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class SynchronizedStatementPostfixTemplate extends JavaEditablePostfixTemplate {
public class SynchronizedStatementPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public SynchronizedStatementPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("synchronized",
"synchronized ($EXPR$) {\n$END$\n}",
@@ -3,13 +3,14 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.CommonClassNames;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class ThrowExceptionPostfixTemplate extends JavaEditablePostfixTemplate {
public class ThrowExceptionPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public ThrowExceptionPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("throw",
"throw $EXPR$;$END$",
@@ -4,6 +4,8 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.generation.surroundWith.JavaWithTryCatchSurrounder;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
@@ -11,7 +13,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
public class TryStatementPostfixTemplate extends PostfixTemplate {
public class TryStatementPostfixTemplate extends PostfixTemplate implements DumbAware {
protected TryStatementPostfixTemplate() {
super("try", "try { exp } catch(Exception e)");
@@ -25,9 +27,9 @@ public class TryStatementPostfixTemplate extends PostfixTemplate {
if (statementParent instanceof PsiDeclarationStatement) return true;
if (statementParent instanceof PsiExpressionStatement) {
PsiExpression expression = ((PsiExpressionStatement)statementParent).getExpression();
return null != expression.getType();
if (statementParent instanceof PsiExpressionStatement statement) {
PsiExpression expression = statement.getExpression();
return DumbService.getInstance(context.getProject()).computeWithAlternativeResolveEnabled(expression::getType) != null;
}
return false;
@@ -11,6 +11,8 @@ import com.intellij.codeInsight.template.macro.SuggestVariableNameMacro;
import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.ProjectScope;
@@ -21,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.Collection;
public class TryWithResourcesPostfixTemplate extends PostfixTemplate {
public class TryWithResourcesPostfixTemplate extends PostfixTemplate implements DumbAware {
protected TryWithResourcesPostfixTemplate() {
super("twr", "try(Type f = new Type()) catch (Exception e)");
}
@@ -34,15 +36,14 @@ public class TryWithResourcesPostfixTemplate extends PostfixTemplate {
if (initializer == null) return false;
final PsiType type = initializer.getType();
if (!(type instanceof PsiClassType)) return false;
final PsiClass aClass = ((PsiClassType)type).resolve();
Project project = element.getProject();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
final PsiClass autoCloseable = facade.findClass(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, ProjectScope.getLibrariesScope(project));
if (!InheritanceUtil.isInheritorOrSelf(aClass, autoCloseable, true)) return false;
return true;
return DumbService.getInstance(initializer.getProject()).computeWithAlternativeResolveEnabled(() -> {
if (!(initializer.getType() instanceof PsiClassType classType)) return false;
final PsiClass aClass = classType.resolve();
Project project = element.getProject();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
final PsiClass autoCloseable = facade.findClass(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, ProjectScope.getLibrariesScope(project));
return InheritanceUtil.isInheritorOrSelf(aClass, autoCloseable, true);
});
}
@Override
@@ -60,7 +61,9 @@ public class TryWithResourcesPostfixTemplate extends PostfixTemplate {
template.addTextSegment("try (");
MacroCallNode name = new MacroCallNode(new SuggestVariableNameMacro());
template.addVariable("type", new TypeExpression(project, new PsiType[]{expression.getType()}), false);
DumbService dumbService = DumbService.getInstance(project);
PsiType type = dumbService.computeWithAlternativeResolveEnabled(expression::getType);
template.addVariable("type", new TypeExpression(project, new PsiType[]{type}), false);
template.addTextSegment(" ");
template.addVariable("name", name, name, true);
template.addTextSegment(" = ");
@@ -69,7 +72,7 @@ public class TryWithResourcesPostfixTemplate extends PostfixTemplate {
template.addEndVariable();
template.addTextSegment("\n}");
Collection<PsiClassType> unhandled = getUnhandled(expression);
Collection<PsiClassType> unhandled = dumbService.computeWithAlternativeResolveEnabled(() -> getUnhandled(expression));
for (PsiClassType exception : unhandled) {
MacroCallNode variable = new MacroCallNode(new SuggestVariableNameMacro());
template.addTextSegment("catch(");
@@ -3,12 +3,13 @@ package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class WhileStatementPostfixTemplate extends JavaEditablePostfixTemplate {
public class WhileStatementPostfixTemplate extends JavaEditablePostfixTemplate implements DumbAware {
public WhileStatementPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("while", "while ($EXPR$) {\n$END$\n}", "while (expr) {}",
Collections.singleton(new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateBooleanExpressionCondition()),
@@ -69,7 +69,8 @@ public class JavaEditablePostfixTemplate
@Override
protected List<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, int offset) {
if (DumbService.getInstance(context.getProject()).isDumb()) return Collections.emptyList();
DumbService dumbService = DumbService.getInstance(context.getProject());
if (dumbService.isDumb() && !DumbService.isDumbAware(this)) return Collections.emptyList();
if (!PsiUtil.getLanguageLevel(context).isAtLeast(myMinimumLanguageLevel)) {
return Collections.emptyList();
}
@@ -83,8 +84,9 @@ public class JavaEditablePostfixTemplate
}
return ContainerUtil.filter(expressions, Conditions.and(e -> PSI_ERROR_FILTER.value(e)
&& e instanceof PsiExpression && e.getTextRange().getEndOffset() == offset, getExpressionCompositeCondition()));
return dumbService.computeWithAlternativeResolveEnabled(() -> ContainerUtil.filter(expressions, Conditions.and(
e -> PSI_ERROR_FILTER.value(e) && e instanceof PsiExpression && e.getTextRange().getEndOffset() == offset,
getExpressionCompositeCondition())));
}
@NotNull
@@ -6,6 +6,7 @@ import com.intellij.codeInsight.template.postfix.templates.PostfixTemplateExpres
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplatePsiInfo;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -91,8 +92,6 @@ public final class JavaPostfixTemplatesUtils {
@NotNull
@Override
public List<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, int offset) {
if (DumbService.getInstance(context.getProject()).isDumb()) return Collections.emptyList();
List<PsiElement> expressions = super.getExpressions(context, document, offset);
if (!expressions.isEmpty()) return expressions;
@@ -120,30 +119,33 @@ public final class JavaPostfixTemplatesUtils {
@NotNull
@Override
public PsiExpression getNegatedExpression(@NotNull PsiElement element) {
assert element instanceof PsiExpression;
String negatedExpressionText = BoolUtils.getNegatedExpressionText((PsiExpression)element);
return JavaPsiFacade.getElementFactory(element.getProject()).createExpressionFromText(negatedExpressionText, element);
Project project = element.getProject();
String negatedExpressionText = DumbService.getInstance(project)
.computeWithAlternativeResolveEnabled(() -> BoolUtils.getNegatedExpressionText((PsiExpression)element));
return JavaPsiFacade.getElementFactory(project).createExpressionFromText(negatedExpressionText, element);
}
};
public static final Condition<PsiElement> IS_NUMBER =
element -> element instanceof PsiExpression && isNumber(((PsiExpression)element).getType());
@Nullable
private static PsiType getType(PsiExpression expression) {
return DumbService.getInstance(expression.getProject()).computeWithAlternativeResolveEnabled(expression::getType);
}
public static final Condition<PsiElement> IS_BOOLEAN =
element -> element instanceof PsiExpression && isBoolean(((PsiExpression)element).getType());
element -> element instanceof PsiExpression expression && isBoolean(getType(expression));
/**
* @deprecated use {@link #isThrowable(PsiType)}
*/
@Deprecated(forRemoval = true)
public static final Condition<PsiElement> IS_THROWABLE =
element -> element instanceof PsiExpression && isThrowable(((PsiExpression)element).getType());
element -> element instanceof PsiExpression expression && isThrowable(getType(expression));
public static final Condition<PsiElement> IS_NON_VOID =
element -> element instanceof PsiExpression && isNonVoid(((PsiExpression)element).getType());
element -> element instanceof PsiExpression expression && isNonVoid(getType(expression));
public static final Condition<PsiElement> IS_NOT_PRIMITIVE =
element -> element instanceof PsiExpression && isNotPrimitiveTypeExpression((PsiExpression)element);
element -> element instanceof PsiExpression expression && isNotPrimitiveTypeExpression(expression);
/**
* @deprecated use {@link #isIterable(PsiType)} / {@link #isArray(PsiType)}
@@ -152,7 +154,7 @@ public final class JavaPostfixTemplatesUtils {
public static final Condition<PsiElement> IS_ITERABLE_OR_ARRAY = element -> {
if (!(element instanceof PsiExpression)) return false;
PsiType type = ((PsiExpression)element).getType();
PsiType type = getType(((PsiExpression)element));
return isArray(type) || isIterable(type);
};
@@ -161,7 +163,7 @@ public final class JavaPostfixTemplatesUtils {
if (expression == null) {
return false;
}
PsiType type = expression.getType();
PsiType type = getType(expression);
return type != null && !(type instanceof PsiPrimitiveType);
}
@@ -182,7 +184,7 @@ public final class JavaPostfixTemplatesUtils {
@Contract("null -> false")
public static boolean isBoolean(@Nullable PsiType type) {
return type != null && (PsiTypes.booleanType().equals(type) || PsiTypes.booleanType().equals(PsiPrimitiveType.getUnboxedType(type)));
return type != null && (PsiTypes.booleanType().equals(type) || type.equalsToText(CommonClassNames.JAVA_LANG_BOOLEAN));
}
@Contract("null -> false")
@@ -199,8 +201,10 @@ public final class JavaPostfixTemplatesUtils {
return true;
}
PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type);
return PsiTypes.intType().equals(unboxedType) || PsiTypes.byteType().equals(unboxedType) || PsiTypes.longType().equals(unboxedType);
String canonicalText = type.getCanonicalText();
return CommonClassNames.JAVA_LANG_INTEGER.equals(canonicalText) ||
CommonClassNames.JAVA_LANG_LONG.equals(canonicalText) ||
CommonClassNames.JAVA_LANG_BYTE.equals(canonicalText);
}
@NotNull
@@ -9,6 +9,7 @@ import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.PsiUpdateModCommandQuickFix;
import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.text.StringUtil;
@@ -331,9 +332,9 @@ public final class LambdaCanBeMethodReferenceInspection extends AbstractBaseJava
expression instanceof PsiTypeCastExpression) {
return false;
}
if (expression instanceof PsiReferenceExpression && !(expression.getParent() instanceof PsiCallExpression)) {
PsiElement element = ((PsiReferenceExpression)expression).resolve();
if (element instanceof PsiField && !((PsiField)element).hasModifierProperty(PsiModifier.FINAL)) {
if (expression instanceof PsiReferenceExpression ref && !(expression.getParent() instanceof PsiCallExpression)) {
PsiElement element = ref.resolve();
if (element instanceof PsiField field && !field.hasModifierProperty(PsiModifier.FINAL)) {
return false;
}
@@ -4,6 +4,8 @@ package com.intellij.psi.impl.source.tree;
import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -35,13 +37,14 @@ public final class JavaTreeCopyHandler implements TreeCopyHandler {
elementType == JavaElementType.REFERENCE_EXPRESSION ||
elementType == JavaElementType.METHOD_REF_EXPRESSION) {
PsiJavaCodeReferenceElement ref = SourceTreeToPsiMap.treeToPsiNotNull(element);
Project project = ref.getProject();
PsiClass refClass = element.getCopyableUserData(JavaTreeGenerator.REFERENCED_CLASS_KEY);
if (refClass != null) {
element.putCopyableUserData(JavaTreeGenerator.REFERENCED_CLASS_KEY, null);
PsiManager manager = refClass.getManager();
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(refClass.getProject());
PsiElement refElement = ref.resolve();
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
PsiElement refElement = DumbService.getInstance(project).computeWithAlternativeResolveEnabled(ref::resolve);
try {
if (refClass != refElement && !manager.areElementsEquivalent(refClass, refElement)) {
if (((CompositeElement)element).findChildByRole(ChildRole.QUALIFIER) == null) {
@@ -64,7 +67,7 @@ public final class JavaTreeCopyHandler implements TreeCopyHandler {
if (refMember != null) {
LOG.assertTrue(ref instanceof PsiReferenceExpression);
element.putCopyableUserData(JavaTreeGenerator.REFERENCED_MEMBER_KEY, null);
PsiElement refElement = ref.resolve();
PsiElement refElement = DumbService.getInstance(project).computeWithAlternativeResolveEnabled(ref::resolve);
if (refMember != refElement && !refMember.getManager().areElementsEquivalent(refMember, refElement)) {
PsiClass containingClass = refMember.getContainingClass();
if (containingClass != null) {
@@ -190,7 +193,8 @@ public final class JavaTreeCopyHandler implements TreeCopyHandler {
IElementType originalType = original.getElementType();
if (originalType == JavaElementType.REFERENCE_EXPRESSION) {
PsiJavaCodeReferenceElement javaRefElement = SourceTreeToPsiMap.treeToPsiNotNull(original);
JavaResolveResult resolveResult = javaRefElement.advancedResolve(false);
JavaResolveResult resolveResult = DumbService.getInstance(javaRefElement.getProject()).computeWithAlternativeResolveEnabled(
() -> javaRefElement.advancedResolve(false));
PsiElement target = resolveResult.getElement();
if (target instanceof PsiClass &&
(original.getTreeParent().getElementType() == JavaElementType.REFERENCE_EXPRESSION ||
@@ -208,7 +212,8 @@ public final class JavaTreeCopyHandler implements TreeCopyHandler {
kind = ((PsiJavaCodeReferenceElementImpl)original).getKindEnum(((PsiJavaCodeReferenceElementImpl)original).getContainingFile());
switch (kind) {
case CLASS_NAME_KIND, CLASS_OR_PACKAGE_NAME_KIND, CLASS_IN_QUALIFIED_NEW_KIND -> {
PsiElement target = SourceTreeToPsiMap.<PsiJavaCodeReferenceElement>treeToPsiNotNull(original).resolve();
PsiJavaCodeReferenceElement element = SourceTreeToPsiMap.treeToPsiNotNull(original);
PsiElement target = DumbService.getInstance(element.getProject()).computeWithAlternativeResolveEnabled(element::resolve);
if (target instanceof PsiClass) {
ref.putCopyableUserData(JavaTreeGenerator.REFERENCED_CLASS_KEY, (PsiClass)target);
}
@@ -10,6 +10,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
@@ -22,6 +23,7 @@ import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.CommonJavaRefactoringUtil;
import com.intellij.util.concurrency.NonUrgentExecutor;
import com.intellij.util.indexing.DumbModeAccessType;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -85,10 +87,10 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
Ref<PsiType[]> mainTypes = new Ref<>();
Ref<PsiType[]> allTypes = new Ref<>();
Runnable calculateTypes = () -> ReadAction.run(() -> {
Runnable calculateTypes = () -> ReadAction.run(() -> DumbService.getInstance(project).runWithAlternativeResolveEnabled(() -> {
mainTypes.set(getTypesForMain());
allTypes.set(getTypesForAll(true));
});
}));
if (ApplicationManager.getApplication().isDispatchThread()) {
ProgressManager.getInstance().runProcessWithProgressSynchronously(calculateTypes, JavaBundle.message("progress.title.calculate.applicable.types"), false, project);
}
@@ -365,9 +367,9 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
public static void typeSelected(@NotNull final PsiType type, @Nullable final PsiType defaultType) {
if (defaultType == null) return;
ReadAction.nonBlocking(() -> {
ReadAction.nonBlocking(() -> DumbModeAccessType.RELIABLE_DATA_ONLY.ignoreDumbMode(() -> {
return type.isValid() && defaultType.isValid() ? new StatisticsInfo(getStatsKey(defaultType), serialize(type)) : null;
}).finishOnUiThread(ModalityState.nonModal(), stat -> {
})).finishOnUiThread(ModalityState.nonModal(), stat -> {
if (stat == null) return;
StatisticsManager.getInstance().incUseCount(stat);
}).submit(NonUrgentExecutor.getInstance());
@@ -11,6 +11,7 @@ import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.PackageIndex;
import com.intellij.openapi.util.Condition;
@@ -254,7 +255,8 @@ public final class CommonJavaRefactoringUtil {
PsiExpression expression = PsiTreeUtil.getParentOfType(elementAtCaret, PsiExpression.class);
while (expression != null) {
if (!expressions.contains(expression) && !(expression instanceof PsiParenthesizedExpression) && !(expression instanceof PsiSuperExpression) &&
(acceptVoid || !PsiTypes.voidType().equals(expression.getType()))) {
(acceptVoid || !PsiTypes.voidType().equals(DumbService.getInstance(file.getProject())
.computeWithAlternativeResolveEnabled(expression::getType)))) {
if (isExtractable(expression)) {
expressions.add(expression);
}
@@ -1,6 +1,7 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi.impl.smartPointers;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -27,7 +28,7 @@ public final class SmartTypePointerManagerImpl extends SmartTypePointerManager {
@Override
@NotNull
public SmartTypePointer createSmartTypePointer(@NotNull PsiType type) {
final SmartTypePointer pointer = type.accept(new SmartTypeCreatingVisitor());
final SmartTypePointer pointer = DumbService.getInstance(myProject).computeWithAlternativeResolveEnabled(() -> type.accept(new SmartTypeCreatingVisitor()));
return pointer != null ? pointer : NULL_POINTER;
}
@@ -0,0 +1,6 @@
public class Foo {
void m() {
Object o = "hello";
o.castvar<caret>
}
}
@@ -0,0 +1,6 @@
public class Foo {
void m() {
Object o = "hello";
String s = (String) o;<caret>
}
}
@@ -0,0 +1,7 @@
import java.util.List;
public class Foo {
void test(List<String> list) {
list.stream().anyMatch(s -> s.trim().var<caret>.isEmpty())
}
}
@@ -0,0 +1,7 @@
import java.util.List;
public class Foo {
void test(List<String> list) {
list.stream().anyMatch(s -> s.trim().var<caret>.isEmpty())
}
}
@@ -0,0 +1,7 @@
import java.util.List;
public class Foo {
void test(List<String> list) {
list.stream().map(String::trim).anyMatch(<caret>trim -> trim.isEmpty())
}
}
@@ -0,0 +1,10 @@
import java.util.List;
public class Foo {
void test(List<String> list) {
list.stream().anyMatch(s -> {
String <caret>trim = s.trim();
return trim.isEmpty();
})
}
}
@@ -4,11 +4,14 @@ package com.intellij.java.codeInsight.completion;
import com.intellij.TestAll;
import com.intellij.TestCaseLoader;
import com.intellij.java.codeInsight.completion.ml.JavaCompletionFeaturesTest;
import com.intellij.java.codeInsight.template.postfix.templates.*;
import com.intellij.testFramework.SkipSlowTestLocally;
import com.intellij.testFramework.TestIndexingModeSupporter;
import junit.framework.Test;
import junit.framework.TestSuite;
import java.util.List;
/**
* To run a separate test from this suite with needed IndexingMode in an IDE, comment in {@link #suite()}
* <pre>
@@ -32,8 +35,10 @@ public class JavaCompletionTestSuite extends TestSuite {
System.setProperty("intellij.build.test.groups", "JAVA_TESTS");
TestCaseLoader myTestCaseLoader = new TestCaseLoader(TestCaseLoader.COMMON_TEST_GROUPS_RESOURCE_NAME);
myTestCaseLoader.fillTestCases("", TestAll.getClassRoots());
for (Class<?> aClass : myTestCaseLoader.getClasses()) {
if (!aClass.getSimpleName().contains("Completion")) continue;
List<Class<?>> classes = myTestCaseLoader.getClasses();
for (Class<?> aClass : classes) {
if (!aClass.getSimpleName().contains("Completion") &&
!PostfixTemplateTestCase.class.isAssignableFrom(aClass)) continue;
// JavaCompletionFeaturesTest does not depend on indices
if (JavaCompletionFeaturesTest.class.equals(aClass)) continue;
// Exclude feature suggester tests
@@ -417,6 +417,7 @@ public class Normal8CompletionTest extends NormalCompletionTestCase {
checkResultByFile(getTestName(false) + "_after.java");
}
@NeedsIndex.ForStandardLibrary
public void test_intersection_type_members() {
myFixture.configureByText("a.java", "import java.util.*; class F { { (true ? new LinkedList<>() : new ArrayList<>()).<caret> }}");
myFixture.completeBasic();
@@ -460,6 +460,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
public void testArrayAccessIndex() { doTest(); }
@NeedsIndex.ForStandardLibrary(reason = "Need to resolve java.lang.String")
public void testThrowExceptionConstructor() { doTest('\n'); }
public void testJavadocThrows() { doTest(); }
@@ -2,6 +2,7 @@
package com.intellij.java.codeInsight.template.postfix.templates;
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.testFramework.NeedsIndex;
import org.jetbrains.annotations.NotNull;
public class CastVarPostfixTemplateTest extends PostfixTemplateTestCase {
@@ -12,10 +13,16 @@ public class CastVarPostfixTemplateTest extends PostfixTemplateTestCase {
return "castvar";
}
@NeedsIndex.SmartMode(reason = "DFA is necessary for smart-cast")
public void testSingleExpression() {
doTest();
}
public void testAssigned() {
doTest();
}
@NeedsIndex.SmartMode(reason = "DFA is necessary for smart-cast")
public void testFinalSingleExpression() {
JavaCodeStyleSettings customSettings = JavaCodeStyleSettings.getInstance(getProject());
customSettings.GENERATE_FINAL_LOCALS = true;
@@ -18,6 +18,7 @@ package com.intellij.java.codeInsight.template.postfix.templates;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.NeedsIndex;
import org.jetbrains.annotations.NotNull;
public class OptionalPostfixTemplateTest extends PostfixTemplateTestCase {
@@ -87,6 +88,7 @@ public class OptionalPostfixTemplateTest extends PostfixTemplateTestCase {
doTest();
}
@NeedsIndex.SmartMode(reason = "Requires nullability analysis")
public void testNotNullMethodCall() {
myFixture.addClass("package org.jetbrains.annotations;" +
"public @interface NotNull {}");
@@ -11,6 +11,7 @@ import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.NeedsIndex;
import com.intellij.util.LazyKt;
import kotlin.Lazy;
import org.jdom.Element;
@@ -54,6 +55,7 @@ public class OriginalElementPostfixTemplateTest extends PostfixTemplateTestCase
}
}
@NeedsIndex.SmartMode(reason = "Not created as DumbAware")
public void testOriginalElement() {
doTest();
}
@@ -7,6 +7,7 @@ import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.testFramework.NeedsIndex;
import com.intellij.util.LazyKt;
import kotlin.Lazy;
import org.jetbrains.annotations.NotNull;
@@ -34,10 +35,12 @@ public class SameKeyPostfixTemplatesTest extends PostfixTemplateTestCase {
PostfixTemplateStorage.getInstance().setTemplates(provider, asList(template1, template2));
}
@NeedsIndex.SmartMode(reason = "Not created as DumbAware")
public void testSameKeyInteger() {
doTest();
}
@NeedsIndex.SmartMode(reason = "Not created as DumbAware")
public void testSameKeyBoolean() {
doTest();
}
@@ -15,12 +15,22 @@
*/
package com.intellij.java.codeInsight.template.postfix.templates;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.ui.ChooserInterceptor;
import com.intellij.ui.UiInterceptors;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author ignatov
*/
public class VarPostfixTemplateTest extends PostfixTemplateTestCase {
@Override
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
return JAVA_LATEST_WITH_LATEST_JDK;
}
@NotNull
@Override
protected String getSuffix() {
@@ -35,6 +45,18 @@ public class VarPostfixTemplateTest extends PostfixTemplateTestCase {
doTest();
}
public void testStreamStep() {
UiInterceptors.register(new ChooserInterceptor(List.of("Create variable inside current lambda", "Extract as 'map' operation"),
"Create variable inside current lambda"));
doTest();
}
public void testStreamStep2() {
UiInterceptors.register(new ChooserInterceptor(List.of("Create variable inside current lambda", "Extract as 'map' operation"),
"Extract as 'map' operation"));
doTest();
}
public void testAnonymous() {
doTest();
}
@@ -4,6 +4,7 @@ package com.intellij.codeInsight.generation.surroundWith;
import com.intellij.lang.surroundWith.Surrounder;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
@@ -22,8 +23,8 @@ public abstract class JavaExpressionSurrounder implements Surrounder {
@Override
public boolean isApplicable(PsiElement @NotNull [] elements) {
return elements.length == 1 &&
elements[0] instanceof PsiExpression &&
isApplicable((PsiExpression)elements[0]);
elements[0] instanceof PsiExpression expr &&
DumbService.getInstance(expr.getProject()).computeWithAlternativeResolveEnabled(() -> isApplicable(expr));
}
/**