From a4d6d0024372ae154171d57f91e15c8ac3cc0e85 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Tue, 9 Jun 2020 13:09:50 +0700 Subject: [PATCH] NotNull, diagnostics for EA-232099 GitOrigin-RevId: b4c746caff6dd1d79269a8e2d352955437d07377 --- .../IntroduceVariableBase.java | 20 ++++++- .../JavaVariableInplaceIntroducer.java | 5 +- .../introduceVariable/VariableExtractor.java | 53 ++++++++++--------- 3 files changed, 49 insertions(+), 29 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java index 13a2b818c45b..5a18e8a52be6 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -17,6 +17,7 @@ import com.intellij.lang.refactoring.RefactoringSupportProvider; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.diagnostic.Attachment; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -64,10 +65,12 @@ import com.intellij.util.containers.MultiMap; import com.siyeh.ig.psiutils.CommentTracker; import com.siyeh.ig.psiutils.VariableAccessUtils; import com.siyeh.ipp.psiutils.ErrorUtil; +import one.util.streamex.EntryStream; import one.util.streamex.StreamEx; import org.jetbrains.annotations.*; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -712,6 +715,21 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase { JavaReplaceChoice finalChoice = settings.getReplaceChoice(); PsiExpression[] selectedOccurrences = finalChoice.filter(occurrenceManager); final PsiElement chosenAnchor = getAnchor(selectedOccurrences); + if (chosenAnchor == null) { + String text = file.getText(); + String textWithOccurrences = StreamEx.of(selectedOccurrences) + .map(e -> getPhysicalElement(e).getTextRange()) + .flatMapToEntry(range -> EntryStream.of(range.getStartOffset(), "[", range.getEndOffset(), "]").toMap()) + .sortedBy(Map.Entry::getKey) + .prepend(0, "") + .append(text.length(), "") + .map(Function.identity()) + .pairMap((prev, next) -> text.substring(prev.getKey(), next.getKey()) + next.getValue()) + .joining(); + LOG.error("Unable to find anchor for a new variable; selectedOccurrences.length = "+selectedOccurrences.length, + new Attachment("source.java", textWithOccurrences)); + return; + } final RefactoringEventData beforeData = new RefactoringEventData(); beforeData.addElement(expr); @@ -750,7 +768,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase { boolean inFinalContext = occurrenceManager.isInFinalContext(); PsiExpression expr = occurrenceManager.getMainOccurence(); PsiExpression[] selectedOccurrences = choice.filter(occurrenceManager); - final InputValidator validator = new InputValidator(IntroduceVariableBase.this, project, occurrenceManager); + final InputValidator validator = new InputValidator(this, project, occurrenceManager); final TypeSelectorManagerImpl typeSelectorManager = new TypeSelectorManagerImpl(project, originalType, expr, selectedOccurrences); typeSelectorManager.setAllOccurrences(true); diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java index 6650cc0cd232..345303e3cc09 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java @@ -469,8 +469,9 @@ public class JavaVariableInplaceIntroducer extends AbstractJavaInplaceIntroducer @Nullable protected PsiVariable introduceVariable() { - PsiVariable variable = VariableExtractor - .introduce(myProject, myExpr, myEditor, myChosenAnchor.getElement(), getOccurrences(), mySettings); + PsiElement anchor = myChosenAnchor.getElement(); + if (anchor == null) return null; + PsiVariable variable = VariableExtractor.introduce(myProject, myExpr, myEditor, anchor, getOccurrences(), mySettings); SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(myProject); if (variable instanceof PsiField || variable instanceof PsiResourceVariable) { myPointer = smartPointerManager.createSmartPsiElementPointer(variable); diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableExtractor.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableExtractor.java index 46e4e230c88e..f9b061f34f45 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableExtractor.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableExtractor.java @@ -42,23 +42,23 @@ import java.util.Set; class VariableExtractor { private static final Logger LOG = Logger.getInstance(VariableExtractor.class); - private final Project myProject; - private final Editor myEditor; - private final IntroduceVariableSettings mySettings; - private final PsiExpression myExpression; + private final @NotNull Project myProject; + private final @Nullable Editor myEditor; + private final @NotNull IntroduceVariableSettings mySettings; + private final @NotNull PsiExpression myExpression; private @NotNull PsiElement myAnchor; private final PsiElement myContainer; - private final PsiExpression[] myOccurrences; + private final PsiExpression @NotNull [] myOccurrences; private final boolean myReplaceSelf; - private final FieldConflictsResolver myFieldConflictsResolver; - private final LogicalPosition myPosition; + private final @NotNull FieldConflictsResolver myFieldConflictsResolver; + private final @Nullable LogicalPosition myPosition; - private VariableExtractor(final Project project, - final PsiExpression expression, - final Editor editor, - final PsiElement anchorStatement, - final PsiExpression[] occurrences, - final IntroduceVariableSettings settings) { + private VariableExtractor(final @NotNull Project project, + final @NotNull PsiExpression expression, + final @Nullable Editor editor, + final @NotNull PsiElement anchorStatement, + final PsiExpression @NotNull [] occurrences, + final @NotNull IntroduceVariableSettings settings) { myProject = project; myExpression = expression; myEditor = editor; @@ -100,6 +100,7 @@ class VariableExtractor { ExpressionUtils.isReferenceTo(((PsiExpressionStatement)myAnchor).getExpression(), var)) { commentTracker.deleteAndRestoreComments(myAnchor); if (myEditor != null) { + assert myPosition != null; myEditor.getCaretModel().moveToLogicalPosition(myPosition); myEditor.getCaretModel().moveToOffset(var.getTextRange().getEndOffset()); myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); @@ -140,7 +141,7 @@ class VariableExtractor { } } - private void highlight(PsiVariable var) { + private void highlight(@NotNull PsiVariable var) { if (myEditor != null) { PsiElement[] occurrences = PsiTreeUtil.collectElements(myContainer, e -> e instanceof PsiReference && ((PsiReference)e).isReferenceTo(var)); @@ -175,7 +176,7 @@ class VariableExtractor { } } - private PsiVariable addVariable(PsiElement declaration, PsiExpression initializer) { + private @NotNull PsiVariable addVariable(PsiElement declaration, @NotNull PsiExpression initializer) { declaration = addDeclaration(declaration, initializer, myAnchor); declaration = JavaCodeStyleManager.getInstance(myProject).shortenClassReferences(declaration); return (PsiVariable)(declaration instanceof PsiDeclarationStatement @@ -240,8 +241,8 @@ class VariableExtractor { return parent.addBefore(declaration, anchor); } - @NotNull - private static PsiType stripNullabilityAnnotationsFromTargetType(SmartTypePointer selectedType, final PsiExpression expression) { + private static @NotNull PsiType stripNullabilityAnnotationsFromTargetType(@NotNull SmartTypePointer selectedType, + @NotNull PsiExpression expression) { PsiType type = selectedType.getType(); if (type == null) { throw new IncorrectOperationException("Unexpected empty type pointer"); @@ -250,7 +251,7 @@ class VariableExtractor { PsiDeclarationStatement probe = JavaPsiFacade.getElementFactory(expression.getProject()) .createVariableDeclarationStatement("x", TypeUtils.getObjectType(expression), null, expression); Project project = expression.getProject(); - NullabilityAnnotationInfo nullabilityAnnotationInfo = + NullabilityAnnotationInfo nullabilityAnnotationInfo = NullableNotNullManager.getInstance(project).findExplicitNullability((PsiLocalVariable)probe.getDeclaredElements()[0]); NullabilityAnnotationInfo info = DfaPsiUtil.getTypeNullabilityInfo(type); if (info != null && nullabilityAnnotationInfo != null && info.getNullability() != nullabilityAnnotationInfo.getNullability() && @@ -263,9 +264,9 @@ class VariableExtractor { } @NotNull - private static PsiElement correctAnchor(PsiExpression expr, + private static PsiElement correctAnchor(@NotNull PsiExpression expr, @NotNull PsiElement anchor, - PsiExpression[] occurrences) { + PsiExpression @NotNull [] occurrences) { if (!expr.isPhysical()) { expr = ObjectUtils.tryCast(expr.getUserData(ElementToWorkOn.PARENT), PsiExpression.class); if (expr == null) return anchor; @@ -356,12 +357,12 @@ class VariableExtractor { } @Nullable - public static PsiVariable introduce(final Project project, - final PsiExpression expr, - final Editor editor, - final PsiElement anchorStatement, - final PsiExpression[] occurrences, - final IntroduceVariableSettings settings) { + public static PsiVariable introduce(final @NotNull Project project, + final @NotNull PsiExpression expr, + final @Nullable Editor editor, + final @NotNull PsiElement anchorStatement, + final PsiExpression @NotNull [] occurrences, + final @NotNull IntroduceVariableSettings settings) { Computable> computation = new VariableExtractor(project, expr, editor, anchorStatement, occurrences, settings)::extractVariable; SmartPsiElementPointer pointer = ApplicationManager.getApplication().runWriteAction(computation);