/*
* Copyright 2011 Jon S Akhtar (Sylvanaar)
*
* 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.sylvanaar.idea.Lua.refactoring;
import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.lexer.Lexer;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.util.ReflectionCache;
import com.sylvanaar.idea.Lua.lang.lexer.LuaLexer;
import com.sylvanaar.idea.Lua.lang.lexer.LuaTokenTypes;
import com.sylvanaar.idea.Lua.lang.psi.LuaPsiFileBase;
import com.sylvanaar.idea.Lua.lang.psi.statements.LuaBlock;
import com.sylvanaar.idea.Lua.lang.psi.symbols.LuaParameter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
/**
* Created by IntelliJ IDEA.
* User: Jon S Akhtar
* Date: 7/9/11
* Time: 6:56 AM
*/
public class LuaRefactoringUtil {
@Nullable
public static PsiElement getEnclosingContainer(PsiElement place) {
PsiElement parent = place.getParent();
while (true) {
if (parent == null) {
return null;
}
if (parent instanceof LuaBlock) {
return parent;
}
parent = parent.getParent();
}
}
public static void sortOccurrences(PsiElement[] occurences) {
Arrays.sort(occurences, new Comparator<PsiElement>() {
public int compare(PsiElement elem1, PsiElement elem2) {
final int offset1 = elem1.getTextRange().getStartOffset();
final int offset2 = elem2.getTextRange().getStartOffset();
return offset1 - offset2;
}
});
}
@Nullable
public static <T extends PsiElement> T findElementInRange(final LuaPsiFileBase file,
int startOffset,
int endOffset,
final Class<T> klass) {
PsiElement element1 = file.getViewProvider().findElementAt(startOffset, file.getLanguage());
PsiElement element2 = file.getViewProvider().findElementAt(endOffset - 1, file.getLanguage());
if (LuaTokenTypes.WHITE_SPACES_SET.contains(element1.getNode().getElementType())) {
startOffset = element1.getTextRange().getEndOffset();
element1 = file.getViewProvider().findElementAt(startOffset, file.getLanguage());
}
if (LuaTokenTypes.WHITE_SPACES_SET.contains(element2.getNode().getElementType())) {
endOffset = element2.getTextRange().getStartOffset();
element2 = file.getViewProvider().findElementAt(endOffset - 1, file.getLanguage());
}
if (element2 == null || element1 == null) return null;
final PsiElement commonParent = PsiTreeUtil.findCommonParent(element1, element2);
assert commonParent != null;
final T element = ReflectionCache.isAssignable(klass, commonParent.getClass())
? (T) commonParent : PsiTreeUtil.getParentOfType(commonParent, klass);
if (element == null || element.getTextRange().getStartOffset() != startOffset) {
return null;
}
return element;
}
public static PsiElement[] getExpressionOccurrences(@NotNull PsiElement expr, @NotNull PsiElement scope) {
ArrayList<PsiElement> occurrences = new ArrayList<PsiElement>();
Comparator<PsiElement> comparator = new Comparator<PsiElement>() {
public int compare(PsiElement element1, PsiElement element2) {
if (element1.equals(element2)) return 0;
if (element1 instanceof LuaParameter &&
element2 instanceof LuaParameter) {
final String name1 = ((LuaParameter) element1).getName();
final String name2 = ((LuaParameter) element2).getName();
if (name1 != null && name2 != null) {
return name1.compareTo(name2);
}
}
return 1;
}
};
// if (scope instanceof LuaConditionalLoop) {
// PsiElement son = expr;
// while (son.getParent() != null && !(son.getParent() instanceof GrLoopStatement)) {
// son = son.getParent();
// }
// assert scope.equals(son.getParent());
// collectOccurrences(expr, son, occurrences, comparator, false);
// } else {
collectOccurrences(expr, scope, occurrences, comparator, scope instanceof LuaPsiFileBase);
// }
return PsiUtilBase.toPsiElementArray(occurrences);
}
private static void collectOccurrences(@NotNull PsiElement expr, @NotNull PsiElement scope, @NotNull ArrayList<PsiElement> acc, Comparator<PsiElement> comparator, boolean goIntoInner) {
if (scope.equals(expr)) {
acc.add(expr);
return;
}
for (PsiElement child : scope.getChildren()) {
// if (goIntoInner || !(scope instanceof LuaPsiFileBase)) {
if (PsiEquivalenceUtil.areElementsEquivalent(child, expr, comparator, false)) {
acc.add(child);
} else {
collectOccurrences(expr, child, acc, comparator, goIntoInner);
}
}
// }
}
public static boolean isAppropriateContainerForIntroduceVariable(PsiElement realContainer) {
return realContainer instanceof LuaBlock;
}
public static boolean isIdentifier(String text) {
if (text == null) return false;
Lexer lexer = new LuaLexer();
lexer.start(text);
if (lexer.getTokenType() != LuaTokenTypes.NAME) return false;
lexer.advance();
return lexer.getTokenType() == null;
}
}