blob: efb4fe4d2c43710e986fce9e790f7cfa77bc4567 [file] [log] [blame]
/*
* Copyright 2000-2009 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.template.macro;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.template.*;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.search.PsiElementProcessorAdapter;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class DescendantClassesEnumMacro extends Macro {
@Override
public String getName() {
return "descendantClassesEnum";
}
@Override
public String getPresentableName() {
return CodeInsightBundle.message("macro.descendant.classes.enum");
}
@Override
public Result calculateResult(@NotNull Expression[] params, ExpressionContext context) {
final List<PsiClass> classes = findDescendants(context, params);
if (classes == null || classes.size() == 0) return null;
Result[] results = calculateResults(classes);
return results[0];
}
private static Result[] calculateResults(final List<PsiClass> classes) {
Result[] results = new Result[classes.size()];
int i = 0;
for (final PsiClass aClass : classes) {
results[i++] = new JavaPsiElementResult(aClass);
}
return results;
}
@Nullable
private static List<PsiClass> findDescendants(ExpressionContext context, Expression[] params) {
if (params == null || params.length == 0) return null;
PsiManager instance = PsiManager.getInstance(context.getProject());
Result result = params[0].calculateResult(context);
if (result == null) return null;
final String paramResult = result.toString();
if (paramResult == null) return null;
final boolean isAllowAbstract = isAllowAbstract(context, params);
final PsiClass myBaseClass =
JavaPsiFacade.getInstance(instance.getProject()).findClass(paramResult, GlobalSearchScope.allScope(context.getProject()));
if (myBaseClass != null) {
final List<PsiClass> classes = new ArrayList<PsiClass>();
ClassInheritorsSearch.search(myBaseClass, true).forEach(new PsiElementProcessorAdapter<PsiClass>(new PsiElementProcessor<PsiClass>() {
@Override
public boolean execute(@NotNull PsiClass element) {
if (isAllowAbstract || !isAbstractOrInterface(element)) {
classes.add(element);
}
return true;
}
}));
return classes;
}
return null;
}
@Override
public Result calculateQuickResult(@NotNull Expression[] params, ExpressionContext context) {
final List<PsiClass> classes = findDescendants(context, params);
if (classes == null || classes.size() == 0) return null;
Result[] results = calculateResults(classes);
return results[0];
}
@Override
public LookupElement[] calculateLookupItems(@NotNull Expression[] params, ExpressionContext context) {
final List<PsiClass> classes = findDescendants(context, params);
if (classes == null || classes.size() == 0) return null;
Set<LookupElement> set = new LinkedHashSet<LookupElement>();
boolean isShortName = params.length > 1 && !Boolean.valueOf(params[1].calculateResult(context).toString());
for (PsiClass object : classes) {
final String name = isShortName ? object.getName() : object.getQualifiedName();
if (name != null && name.length() > 0) {
set.add(LookupElementBuilder.create(name));
}
}
return set.toArray(new LookupElement[set.size()]);
}
private static boolean isAbstractOrInterface(final PsiClass psiClass) {
final PsiModifierList modifierList = psiClass.getModifierList();
return psiClass.isInterface() || (modifierList != null && modifierList.hasModifierProperty(PsiModifier.ABSTRACT));
}
private static boolean isAllowAbstract(final ExpressionContext context, final Expression[] params) {
return params.length > 2 ? Boolean.valueOf(params[2].calculateResult(context).toString()) : true;
}
@Override
public boolean isAcceptableInContext(TemplateContextType context) {
return context instanceof JavaCodeContextType;
}
}