blob: bfac2ba62c557879bc2d1a7d44a82e831de098dd [file] [log] [blame]
/*
* Copyright 2005 Sascha Weinreuter
*
* 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 org.intellij.lang.xpath.xslt.refactoring;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import org.intellij.lang.xpath.XPathFile;
import org.intellij.lang.xpath.psi.XPathExpression;
import org.intellij.lang.xpath.xslt.XsltSupport;
import org.intellij.lang.xpath.xslt.util.XsltCodeInsightUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public abstract class BaseIntroduceAction<Settings extends RefactoringOptions> extends XsltRefactoringActionBase {
protected abstract String getCommandName();
protected abstract Settings getSettings(XPathExpression expression, Set<XPathExpression> matchingExpressions);
protected abstract boolean extractImpl(XPathExpression expression, Set<XPathExpression> matchingExpressions, List<XmlTag> otherMatches, Settings settings);
public String getErrorMessage(Editor editor, PsiFile file, XmlAttribute context) {
if (context != null) {
if (XsltSupport.isPatternAttribute(context)) {
return "Match patterns may not contain variable references.";
}
if (XsltSupport.isXPathAttribute(context) && editor.getSelectionModel().hasSelection()) {
return "Please select a complete XPath expression to extract.";
}
}
return super.getErrorMessage(editor, file, context);
}
protected boolean actionPerformedImpl(PsiFile file, Editor editor, XmlAttribute context, int offset) {
if (!(file instanceof XPathFile)) return false;
// pattern attribute may not reference variables
if (XsltSupport.isPatternAttribute(context)) return false;
final SelectionModel selectionModel = editor.getSelectionModel();
final boolean hasSelection = selectionModel.hasSelection();
final int start = selectionModel.getSelectionStart();
final int end = selectionModel.getSelectionEnd();
if (hasSelection) {
final PsiElement xpathElement = file.findElementAt(start);
if (xpathElement != null) {
XPathExpression expression = PsiTreeUtil.getParentOfType(xpathElement, XPathExpression.class);
while (expression != null) {
if (expression.getTextRange().getStartOffset() == start) {
final int diff = expression.getTextRange().getEndOffset() - end;
if (diff == 0) {
extractFromExpression(editor, expression);
return true;
} else if (diff > 0) {
break;
}
}
expression = PsiTreeUtil.getParentOfType(expression, XPathExpression.class);
}
}
} else {
final XPathExpression expression = PsiTreeUtil.getChildOfType(file, XPathExpression.class);
if (expression != null) {
final PsiFile containingFile = expression.getContainingFile();
assert containingFile != null;
final TextRange range = expression.getTextRange();
editor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset());
extractFromExpression(editor, expression);
return true;
}
}
return false;
}
private void extractFromExpression(Editor e, final XPathExpression expression) {
final Editor editor = (e instanceof EditorWindow) ? ((EditorWindow)e).getDelegate() : e;
final HighlightManager highlightManager = HighlightManager.getInstance(expression.getProject());
final Set<XPathExpression> matchingExpressions = RefactoringUtil.collectMatchingExpressions(expression);
final List<XmlTag> otherMatches = new ArrayList<XmlTag>(matchingExpressions.size());
final ArrayList<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>(matchingExpressions.size() + 1);
if (matchingExpressions.size() > 0) {
final SelectionModel selectionModel = editor.getSelectionModel();
highlightManager.addRangeHighlight(editor, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd(),
EditorColors.SEARCH_RESULT_ATTRIBUTES.getDefaultAttributes(), false, highlighters);
for (XPathExpression expr : matchingExpressions) {
final TextRange range = XsltCodeInsightUtil.getRangeInsideHostingFile(expr);
highlightManager.addRangeHighlight(editor, range.getStartOffset(), range.getEndOffset(),
EditorColors.SEARCH_RESULT_ATTRIBUTES.getDefaultAttributes(), false, highlighters);
final XmlTag tag = PsiTreeUtil.getContextOfType(expr, XmlTag.class, true);
assert tag != null;
otherMatches.add(tag);
}
}
final Settings dlg = getSettings(expression, matchingExpressions);
if (dlg == null || dlg.isCanceled()) return;
if (getCommandName() != null) {
new WriteCommandAction.Simple(e.getProject(), getCommandName()) {
protected void run() throws Throwable {
if (extractImpl(expression, matchingExpressions, otherMatches, dlg)) {
for (RangeHighlighter highlighter : highlighters) {
highlighter.dispose();
}
}
}
}.execute();
} else {
extractImpl(expression, matchingExpressions, otherMatches, dlg);
}
}
}