package org.angularjs.codeInsight;
import com.intellij.lang.javascript.psi.JSCallExpression;
import com.intellij.lang.javascript.psi.JSImplicitElementProvider;
import com.intellij.lang.javascript.psi.JSLiteralExpression;
import com.intellij.lang.javascript.psi.ecma6.ES6Decorator;
import com.intellij.lang.javascript.psi.stubs.JSImplicitElement;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.stubs.StubIndexKey;
import com.intellij.util.Processor;
import org.angularjs.index.AngularDirectivesDocIndex;
import org.angularjs.index.AngularDirectivesIndex;
import org.angularjs.index.AngularIndexUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import static com.intellij.openapi.util.text.StringUtil.trimEnd;
import static com.intellij.openapi.util.text.StringUtil.trimStart;
/**
* @author Dennis.Ushakov
*/
public class DirectiveUtil {
public static String getAttributeName(final String text) {
final String[] split = StringUtil.unquoteString(text).split("(?=[A-Z])");
for (int i = 0; i < split.length; i++) {
split[i] = StringUtil.decapitalize(split[i]);
}
return StringUtil.join(split, "-");
}
public static String normalizeAttributeName(String name) {
if (name == null) return null;
if (name.startsWith("data-")) {
name = name.substring(5);
}
else name = trimStart(name, "x-");
name = name.replace(':', '-');
name = name.replace('_', '-');
if (name.endsWith("-start")) {
name = name.substring(0, name.length() - 6);
}
else name = trimEnd(name, "-end");
return name;
}
public static boolean isAngular2Directive(final PsiElement directive) {
return directive instanceof JSImplicitElement && (directive.getParent() instanceof JSCallExpression ||
directive.getParent() instanceof ES6Decorator);
}
public static String attributeToDirective(final PsiElement directive, final String name) {
if (isAngular2Directive(directive)) {
return name;
}
final String[] words = name.split("-");
for (int i = 1; i < words.length; i++) {
words[i] = StringUtil.capitalize(words[i]);
}
return StringUtil.join(words);
}
public static boolean processTagDirectives(final Project project,
Processor<JSImplicitElement> processor) {
final Collection<String> docDirectives = AngularIndexUtil.getAllKeys(AngularDirectivesDocIndex.KEY, project);
for (String directiveName : docDirectives) {
final JSImplicitElement directive = getTagDirective(project, directiveName, AngularDirectivesDocIndex.KEY);
if (directive != null) {
if (!processor.process(directive)) {
return false;
}
}
}
final Collection<String> directives = AngularIndexUtil.getAllKeys(AngularDirectivesIndex.KEY, project);
for (String directiveName : directives) {
if (!docDirectives.contains(directiveName)) {
final JSImplicitElement directive = getTagDirective(project, directiveName, AngularDirectivesIndex.KEY);
if (directive != null) {
if (!processor.process(directive)) {
return false;
}
}
}
}
return true;
}
public static JSImplicitElement getTagDirective(String directiveName, Project project) {
final JSImplicitElement directive = getTagDirective(project, directiveName, AngularDirectivesDocIndex.KEY);
return directive == null ? getTagDirective(project, directiveName, AngularDirectivesIndex.KEY) : directive;
}
private static JSImplicitElement getTagDirective(Project project, String directiveName, final StubIndexKey<String, JSImplicitElementProvider> index) {
final JSImplicitElement directive = AngularIndexUtil.resolve(project, index, directiveName);
final String restrictions = directive != null ? directive.getTypeString() : null;
if (restrictions != null) {
final String[] split = restrictions.split(";", -1);
final String restrict = AngularIndexUtil.convertRestrictions(project, split[0]);
if (!StringUtil.isEmpty(restrict) && StringUtil.containsIgnoreCase(restrict, "E")) {
return directive;
}
}
return null;
}
@Nullable
public static JSImplicitElement getDirective(@Nullable PsiElement element) {
if (element instanceof JSImplicitElement) {
return isAngular2Directive(element) ? (JSImplicitElement)element : getDirective(element, ((JSImplicitElement)element).getName());
}
if (element instanceof JSLiteralExpression && ((JSLiteralExpression)element).isQuotedLiteral()) {
return getDirective(element, StringUtil.unquoteString(element.getText()));
}
return null;
}
@Nullable
private static JSImplicitElement getDirective(@NotNull PsiElement element, final String name) {
final String directiveName = getAttributeName(name);
final JSImplicitElement directive = AngularIndexUtil.resolve(element.getProject(), AngularDirectivesIndex.KEY, directiveName);
if (directive != null && directive.isEquivalentTo(element)) {
return directive;
}
return null;
}
}