/* * Copyright 2012-2014 Sergey Ignatov * * 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.erlang.refactoring; import com.intellij.codeInsight.PsiEquivalenceUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Pass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiRecursiveElementVisitor; import com.intellij.psi.PsiWhiteSpace; import com.intellij.refactoring.IntroduceTargetChooser; import org.intellij.erlang.psi.*; import org.intellij.erlang.psi.impl.ErlangPsiImplUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class ErlangRefactoringUtil { private ErlangRefactoringUtil() { } @NotNull public static List<PsiElement> getOccurrences(@NotNull final PsiElement pattern, @Nullable PsiElement context) { if (context == null) { return Collections.emptyList(); } final List<PsiElement> occurrences = new ArrayList<>(); PsiRecursiveElementVisitor visitor = new PsiRecursiveElementVisitor() { public void visitElement(@NotNull PsiElement element) { if (PsiEquivalenceUtil.areElementsEquivalent(element, pattern)) { occurrences.add(element); return; } super.visitElement(element); } }; context.accept(visitor); return occurrences; } @NotNull public static Pair<PsiElement, PsiElement> selectionToElements(@NotNull PsiFile file, @NotNull SelectionModel selectionModel) { PsiElement element1 = file.findElementAt(selectionModel.getSelectionStart()); PsiElement element2 = file.findElementAt(selectionModel.getSelectionEnd() - 1); if (element1 instanceof PsiWhiteSpace) { element1 = file.findElementAt(element1.getTextRange().getEndOffset()); } if (element2 instanceof PsiWhiteSpace) { element2 = file.findElementAt(element2.getTextRange().getStartOffset() - 1); } return Pair.create(element1, element2); } public static String shorten(@NotNull ErlangExpression o, @NotNull String defaultValue) { VariableTextBuilder visitor = new VariableTextBuilder(); o.accept(visitor); return visitor.result(defaultValue); } @NotNull public static String shorten(@NotNull ErlangExpression o) { // maybe better to return List<String> VariableTextBuilder visitor = new VariableTextBuilder(); o.accept(visitor); return visitor.result(); } public static void smartIntroduce(@NotNull final Editor editor, @NotNull PsiFile file, @NotNull final Extractor extractor) { int offset = editor.getCaretModel().getOffset(); PsiElement element = file.findElementAt(offset); if (!extractor.checkContext(file, editor, element)) return; List<ErlangExpression> expressions = new ArrayList<>(); while (element != null) { if (element instanceof ErlangClauseBody) { break; } else if (element instanceof ErlangExpression && !(element instanceof ErlangAssignmentExpression)) { boolean isQualifiedFunCall = element instanceof ErlangFunctionCallExpression && element.getParent() instanceof ErlangGlobalFunctionCallExpression; if (!isQualifiedFunCall && !ErlangPsiImplUtil.inLeftPartOfAssignment(element, false)) { expressions.add((ErlangExpression) element); } } element = element.getParent(); } if (expressions.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) { extractor.process(editor, expressions.get(0)); } else if (expressions.size() > 1) { IntroduceTargetChooser.showChooser(editor, expressions, new Pass<ErlangExpression>() { @Override public void pass(@NotNull ErlangExpression expression) { extractor.process(editor, expression); } }, PsiElement::getText ); } } public interface Extractor { boolean checkContext(@NotNull PsiFile file, @NotNull Editor editor, @Nullable PsiElement element); void process(@NotNull Editor editor, @NotNull ErlangExpression expression); } }