| /* |
| * 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.introduceParameter; |
| |
| import org.intellij.lang.xpath.psi.XPathExpression; |
| import org.intellij.lang.xpath.psi.XPathVariableReference; |
| import org.intellij.lang.xpath.psi.impl.XPathChangeUtil; |
| import org.intellij.lang.xpath.xslt.XsltSupport; |
| import org.intellij.lang.xpath.xslt.psi.XsltElementFactory; |
| import org.intellij.lang.xpath.xslt.psi.XsltTemplate; |
| import org.intellij.lang.xpath.xslt.refactoring.RefactoringUtil; |
| import org.intellij.lang.xpath.xslt.util.XsltCodeInsightUtil; |
| |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.psi.PsiElement; |
| import com.intellij.psi.PsiReference; |
| import com.intellij.psi.search.searches.ReferencesSearch; |
| import com.intellij.psi.util.PsiTreeUtil; |
| import com.intellij.psi.xml.XmlAttribute; |
| import com.intellij.psi.xml.XmlDocument; |
| import com.intellij.psi.xml.XmlTag; |
| import com.intellij.refactoring.BaseRefactoringProcessor; |
| import com.intellij.refactoring.ui.UsageViewDescriptorAdapter; |
| import com.intellij.usageView.UsageInfo; |
| import com.intellij.usageView.UsageViewDescriptor; |
| import com.intellij.util.IncorrectOperationException; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.*; |
| |
| class IntroduceParameterProcessor extends BaseRefactoringProcessor { |
| private final XPathExpression myExpression; |
| private final Set<XPathExpression> myOtherExpressions; |
| private final IntroduceParameterOptions mySettings; |
| |
| private final XsltTemplate myTemplate; |
| |
| public IntroduceParameterProcessor(Project project, XPathExpression expression, Set<XPathExpression> otherExpressions, IntroduceParameterOptions settings) { |
| super(project); |
| mySettings = settings; |
| myExpression = expression; |
| myOtherExpressions = settings.isReplaceAll() ? otherExpressions : Collections.<XPathExpression>emptySet(); |
| |
| final XmlTag templateTag = XsltCodeInsightUtil.getTemplateTag(myExpression, true, true); |
| myTemplate = templateTag != null ? XsltElementFactory.getInstance().wrapElement(templateTag, XsltTemplate.class) : null; |
| |
| setPreviewUsages(settings.isPreview()); |
| } |
| |
| |
| @NotNull |
| protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usageInfos) { |
| return new MyUsageViewDescriptorAdapter(); |
| } |
| |
| @NotNull |
| protected UsageInfo[] findUsages() { |
| int usageCount = myOtherExpressions.size() + 1; |
| |
| final List<PsiElement> callsToUpdate; |
| if (!mySettings.isCreateDefault()) { |
| assert myTemplate != null; |
| |
| final Collection<PsiReference> references = ReferencesSearch.search(myTemplate, myTemplate.getUseScope(), false).findAll(); |
| callsToUpdate = new ArrayList<PsiElement>(references.size()); |
| for (PsiReference reference : references) { |
| final PsiElement e = reference.getElement(); |
| final XmlTag tag = PsiTreeUtil.getContextOfType(e, XmlTag.class, true); |
| if (tag != null && XsltSupport.isTemplateCall(tag)) { |
| callsToUpdate.add(tag); |
| } |
| } |
| usageCount += callsToUpdate.size(); |
| } else { |
| //noinspection unchecked |
| callsToUpdate = Collections.emptyList(); |
| } |
| |
| final UsageInfo[] usageInfos = new UsageInfo[usageCount]; |
| usageInfos[0] = XPathUsageInfo.create(myExpression); |
| |
| int i = 1; |
| for (XPathExpression expression : myOtherExpressions) { |
| usageInfos[i++] = XPathUsageInfo.create(expression); |
| } |
| for (PsiElement o : callsToUpdate) { |
| usageInfos[i++] = new UsageInfo(o, false); |
| } |
| return usageInfos; |
| } |
| |
| protected void refreshElements(PsiElement[] psiElements) { |
| // TODO When's that called? What should it do? |
| } |
| |
| protected void performRefactoring(UsageInfo[] usageInfos) { |
| XmlTag tag; |
| if (myTemplate != null) { |
| tag = myTemplate.getTag(); |
| } else if ((tag = XsltCodeInsightUtil.getTemplateTag(myExpression, true, false)) == null) { |
| final XmlDocument document = PsiTreeUtil.getContextOfType(myExpression, XmlDocument.class, true); |
| assert document != null; |
| tag = document.getRootTag(); |
| } |
| assert tag != null; |
| |
| final XmlTag param = tag.createChildTag("param", XsltSupport.XSLT_NS, null, false); |
| try { |
| param.setAttribute("name", mySettings.getName()); |
| |
| if (mySettings.isCreateDefault()) { |
| param.setAttribute("select", myExpression.getText()); |
| } |
| |
| XmlTag anchorParam = null; |
| for (UsageInfo info : usageInfos) { |
| if (info instanceof XPathUsageInfo) { |
| final XPathUsageInfo x = (XPathUsageInfo)info; |
| final XPathVariableReference variableReference = XPathChangeUtil.createVariableReference(x.getExpression(), mySettings.getName()); |
| final XmlAttribute attribute = x.getAttribute(); |
| assert attribute != null; |
| |
| x.getExpression().replace(variableReference); |
| |
| if (XsltSupport.isParam(attribute.getParent())) { |
| if (anchorParam == null) { |
| anchorParam = attribute.getParent(); |
| } else if (attribute.getParent().getTextOffset() < anchorParam.getTextOffset()) { |
| anchorParam = attribute.getParent(); |
| } |
| } |
| } else { |
| final XmlTag t = (XmlTag)info.getElement(); |
| if (t != null) { |
| final XmlTag p = t.createChildTag("with-param", t.getNamespace(), null, false); |
| p.setAttribute("name", mySettings.getName()); |
| p.setAttribute("select", myExpression.getText()); |
| t.add(p); |
| } |
| } |
| } |
| |
| if (anchorParam != null) { |
| RefactoringUtil.addParameter(tag, param, PsiTreeUtil.getPrevSiblingOfType(anchorParam, XmlTag.class)); |
| } else { |
| RefactoringUtil.addParameter(tag, param); |
| } |
| } catch (IncorrectOperationException e) { |
| Logger.getInstance(getClass().getName()).error(e); |
| } |
| } |
| |
| protected String getCommandName() { |
| return XsltIntroduceParameterAction.COMMAND_NAME; |
| } |
| |
| private class MyUsageViewDescriptorAdapter extends UsageViewDescriptorAdapter { |
| |
| @NotNull |
| public PsiElement[] getElements() { |
| return new PsiElement[]{ myTemplate }; |
| } |
| |
| public String getProcessedElementsHeader() { |
| return "Adding parameter to template"; |
| } |
| } |
| } |