package org.angularjs.codeInsight;
import com.intellij.codeInsight.completion.CompletionContributor;
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.lang.Language;
import com.intellij.lang.javascript.completion.JSLookupPriority;
import com.intellij.lang.javascript.completion.JSLookupUtilImpl;
import com.intellij.lang.javascript.psi.impl.JSReferenceExpressionImpl;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ReadAction;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiUtilCore;
import org.angularjs.index.AngularControllerIndex;
import org.angularjs.index.AngularFilterIndex;
import org.angularjs.index.AngularIndexUtil;
import org.angularjs.lang.AngularJSLanguage;
import org.angularjs.lang.psi.AngularJSAsExpression;
import org.angularjs.lang.psi.AngularJSFilterExpression;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
/**
* @author Dennis.Ushakov
*/
public class AngularJSCompletionContributor extends CompletionContributor {
private static final JSLookupPriority NG_VARIABLE_PRIORITY = JSLookupPriority.LOCAL_SCOPE_MAX_PRIORITY;
@Override
public void fillCompletionVariants(@NotNull final CompletionParameters parameters, @NotNull final CompletionResultSet result) {
if (!getElementLanguage(parameters).is(AngularJSLanguage.INSTANCE)) return;
if (AngularMessageFormatCompletion.messageFormatCompletion(parameters, result)) return;
PsiReference ref = parameters.getPosition().getContainingFile().findReferenceAt(parameters.getOffset());
if (ref instanceof JSReferenceExpressionImpl && ((JSReferenceExpressionImpl)ref).getQualifier() == null) {
final PsiElement parent = ((JSReferenceExpressionImpl)ref).getParent();
if (addFilterVariants(result, parameters, ref, parent)) return;
if (addControllerVariants(result, parameters, ref, parent)) return;
AngularJSProcessor.process(parameters.getPosition(), element -> {
final String name = element.getName();
if (name != null) {
result.consume(JSLookupUtilImpl.createPrioritizedLookupItem(element, name, NG_VARIABLE_PRIORITY, false, false));
}
});
}
}
private static boolean addControllerVariants(CompletionResultSet result, CompletionParameters parameters, PsiReference ref, PsiElement parent) {
if (AngularJSAsExpression.isAsControllerRef(ref, parent)) {
addResults(result, parameters, AngularIndexUtil.getAllKeys(AngularControllerIndex.KEY, parent.getProject()));
return true;
}
return false;
}
private static boolean addFilterVariants(final CompletionResultSet result, CompletionParameters parameters, PsiReference ref, PsiElement parent) {
if (AngularJSFilterExpression.isFilterNameRef(ref, parent)) {
addResults(result, parameters, AngularIndexUtil.getAllKeys(AngularFilterIndex.KEY, parent.getProject()));
return true;
}
return false;
}
static void addResults(final CompletionResultSet result, CompletionParameters parameters, final Collection<String> keys) {
for (String controller : keys) {
result.consume(JSLookupUtilImpl.createPrioritizedLookupItem(null, controller, NG_VARIABLE_PRIORITY, false, false));
}
result.runRemainingContributors(parameters, result1 -> {
final String string = result1.getLookupElement().getLookupString();
if (!keys.contains(string)) {
result.passResult(result1);
}
});
}
static Language getElementLanguage(final CompletionParameters parameters) {
final AccessToken l = ReadAction.start();
try {
return PsiUtilCore.getLanguageAtOffset(parameters.getPosition().getContainingFile(), parameters.getOffset());
} finally {
l.finish();
}
}
}