package jetbrains.mps.idea.scopes;/*
* Copyright 2000-2012 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.
*/
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.patterns.ElementPattern;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightMethod;
import com.intellij.psi.scope.BaseScopeProcessor;
import com.intellij.util.Consumer;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class IdeaScopesUtils {
private static CompletionParameters createCompletionParameter(@NotNull final PsiElement position,
@NotNull final PsiFile originalFile,
final CompletionType completionType,
int offset,
final int invocationCount,
Lookup lookup) {
Constructor c = CompletionParameters.class.getDeclaredConstructors()[0];
c.setAccessible(true);
try {
if (c.getParameterTypes().length == 6) {
return (CompletionParameters)c.newInstance(position, originalFile, completionType, offset, invocationCount, lookup);
}
else {
return (CompletionParameters)c.newInstance(position, originalFile, completionType, offset, invocationCount, lookup, false);
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
public static List<String> getMembersFromClass_New(PsiClass clazz) {
String methodText = "public static void scopes_test_239(" + clazz.getName() + " test) { test.? }";
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(clazz.getProject()).getElementFactory();
PsiMethod psiMethod =
elementFactory.createMethodFromText(methodText.replace("?", CompletionInitializationContext.DUMMY_IDENTIFIER), clazz);
psiMethod = new LightMethod(clazz.getManager(), psiMethod, clazz);
PsiReferenceExpression thisRef = (PsiReferenceExpression)psiMethod.getBody().getStatements()[0].getFirstChild();
PsiElement element = thisRef.getChildren()[3];
CompletionParameters _parameters =
createCompletionParameter(element, element.getContainingFile(), CompletionType.BASIC, element.getTextRange().getStartOffset(), 1,
null);
JavaCompletionContributor contributor = new JavaCompletionContributor();
MyResultSet resultSet = new MyResultSet(contributor);
contributor.fillCompletionVariants(_parameters, resultSet);
return resultSet.result;
}
public static List<String> getMembersFromClass_Old(PsiClass clazz) {
String methodText = "public static void scopes_test_239() { " + clazz.getName() + ".? }";
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(clazz.getProject()).getElementFactory();
PsiMethod psiMethod =
elementFactory.createMethodFromText(methodText.replace("?", CompletionInitializationContext.DUMMY_IDENTIFIER), clazz);
psiMethod = new LightMethod(clazz.getManager(), psiMethod, clazz);
PsiReferenceExpression thisRef = (PsiReferenceExpression)psiMethod.getBody().getStatements()[0].getFirstChild();
return getMembersFromReference(thisRef);
}
private static List<String> getMembersFromReference(PsiJavaReference reference) {
MyProcessor processor = new MyProcessor();
reference.processVariants(processor);
return processor.myResults;
}
private static String getMethodParametersPresentation(PsiMethod method) {
return String.format("<%d>(%d)", method.getTypeParameters().length, method.getParameterList().getParametersCount());
}
private static String getSignature(PsiElement element) {
if (!(element instanceof PsiMember)) {
return "Not psi member: " + element.toString();
}
PsiMember member = (PsiMember)element;
PsiClass memberClazz = member.getContainingClass();
boolean isStatic = member.getModifierList().hasModifierProperty(PsiModifier.STATIC);
return (isStatic ? "static " : "") + memberClazz.getQualifiedName() + ":" + member.getName() +
(member instanceof PsiMethod ? getMethodParametersPresentation((PsiMethod)member) : "");
}
private static class MyProcessor extends BaseScopeProcessor {
public final Set<Object> myResultNames = new THashSet<Object>();
public final List<String> myResults = new ArrayList<String>();
private static Object getUniqueId(Object element, PsiSubstitutor substitutor) {
if (element instanceof PsiClass) {
return ((PsiClass)element).getQualifiedName();
}
if (element instanceof PsiPackage) {
return ((PsiPackage)element).getQualifiedName();
}
if (element instanceof PsiMethod) {
return ((PsiMethod)element).getSignature(substitutor);
}
if (element instanceof PsiVariable) {
return "#" + ((PsiVariable)element).getName();
}
return null;
}
@Override
public boolean execute(@NotNull PsiElement element, ResolveState state) {
if (myResultNames.add(getUniqueId((PsiNamedElement)element, state.get(PsiSubstitutor.KEY)))) {
myResults.add(getSignature(element));
}
return true;
}
}
private static class MyResultSet extends CompletionResultSet {
public final List<String> result = new ArrayList<String>();
MyResultSet(CompletionContributor contributor) {
super(new PlainPrefixMatcher(""), Consumer.EMPTY_CONSUMER, contributor);
}
@Override
public void addElement(@NotNull LookupElement element) {
// TODO: comment it when scopes supports inner classes
if (element.getObject() instanceof PsiClass) {
return;
}
if (element.getObject() instanceof PsiElement) {
result.add(getSignature((PsiElement)element.getObject()));
}
}
@NotNull
@Override
public CompletionResultSet withPrefixMatcher(@NotNull PrefixMatcher matcher) {
return this;
}
@NotNull
@Override
public CompletionResultSet withPrefixMatcher(@NotNull String prefix) {
return this;
}
@NotNull
@Override
public CompletionResultSet withRelevanceSorter(@NotNull CompletionSorter sorter) {
return this;
}
@Override
public void addLookupAdvertisement(@NotNull String s) {
}
@NotNull
@Override
public CompletionResultSet caseInsensitive() {
return this;
}
@Override
public void restartCompletionOnPrefixChange(ElementPattern<String> prefixCondition) {
}
@Override
public void restartCompletionWhenNothingMatches() {
}
}
}