diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/BaseElementAtCaretIntentionAction.java b/platform/lang-api/src/com/intellij/codeInsight/intention/BaseElementAtCaretIntentionAction.java new file mode 100644 index 000000000000..6934d89b6e4f --- /dev/null +++ b/platform/lang-api/src/com/intellij/codeInsight/intention/BaseElementAtCaretIntentionAction.java @@ -0,0 +1,99 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.intellij.codeInsight.intention; + +import com.intellij.codeInsight.intention.impl.BaseIntentionAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Danila Ponomarenko + */ +public abstract class BaseElementAtCaretIntentionAction extends BaseIntentionAction { + private volatile boolean useElementToTheLeft = false; + + @Override + public final boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + if (!file.getManager().isInProject(file)) return false; + + final PsiElement elementToTheRight = getElementToTheRight(editor, file); + if (elementToTheRight == null) { + return false; + } + + if (isAvailable(project, editor, elementToTheRight)) { + return true; + } + + final PsiElement elementToTheLeft = getElementToTheLeft(editor, file); + if (elementToTheLeft != null && isAvailable(project, editor, elementToTheLeft)) { + useElementToTheLeft = true; + return true; + } + + return false; + } + + /** + * Checks whether this intention is available at a caret offset in file. + * If this method returns true, a light bulb for this intention is shown. + * + * @param project the project in which the availability is checked. + * @param editor the editor in which the intention will be invoked. + * @param element the element under caret. + * @return true if the intention is available, false otherwise. + */ + public abstract boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element); + + @Override + public final void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + final PsiElement element = useElementToTheLeft ? getElementToTheLeft(editor, file) : getElementToTheRight(editor,file); + if (element == null){ + return; + } + + invoke(project, editor, element); + } + + /** + * Invokes intention action for the element under cursor. + * + * @param project the project in which the file is opened. + * @param editor the editor for the file. + * @param element the element under cursor. + * @throws com.intellij.util.IncorrectOperationException + * + */ + public abstract void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException; + + @Nullable + protected static PsiElement getElementToTheRight(Editor editor, @NotNull PsiFile file) { + return file.findElementAt(editor.getCaretModel().getOffset()); + } + + @Nullable + protected static PsiElement getElementToTheLeft(Editor editor, @NotNull PsiFile file) { + return file.findElementAt(editor.getCaretModel().getOffset() - 1); + } + + +} \ No newline at end of file diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java b/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java index e06bfcec20c6..0a237b0e65d9 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java +++ b/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java @@ -27,6 +27,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** + * To solve "caret after last symbol" problem consider using {@link com.intellij.codeInsight.intention.BaseElementAtCaretIntentionAction} + * * @author Anna Kozlova * @author Konstantin Bulenkov */ diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/Intention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/Intention.java index fb29c3ddd144..52f025f8e211 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/Intention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/Intention.java @@ -15,7 +15,7 @@ */ package com.siyeh.ipp.base; -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; +import com.intellij.codeInsight.intention.BaseElementAtCaretIntentionAction; import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; @@ -34,7 +34,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public abstract class Intention extends PsiElementBaseIntentionAction { +public abstract class Intention extends BaseElementAtCaretIntentionAction { private final PsiElementPredicate predicate;