package com.jetbrains.lang.dart.psi.impl;
import com.intellij.icons.AllIcons;
import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.RowIcon;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PlatformIcons;
import com.jetbrains.lang.dart.DartComponentType;
import com.jetbrains.lang.dart.DartTokenTypes;
import com.jetbrains.lang.dart.psi.*;
import com.jetbrains.lang.dart.util.DartPresentableUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
abstract public class AbstractDartComponentImpl extends DartPsiCompositeElementImpl implements DartComponent {
public AbstractDartComponentImpl(@NotNull ASTNode node) {
super(node);
}
@Override
public String getName() {
final DartComponentName name = getComponentName();
if (name != null) {
return name.getText();
}
return super.getName();
}
@Override
public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
final DartComponentName componentName = getComponentName();
if (componentName != null) {
componentName.setName(name);
}
return this;
}
@Nullable
@Override
public PsiElement getNameIdentifier() {
return getComponentName();
}
@Override
public Icon getIcon(int flags) {
final DartComponentType type = DartComponentType.typeOf(this);
Icon icon = type == null ? super.getIcon(flags) : type.getIcon(this);
icon = doOverlays(icon);
RowIcon baseIcon = new RowIcon(2);
baseIcon.setIcon(icon, 0);
Icon visibility = isPublic() ? PlatformIcons.PUBLIC_ICON : PlatformIcons.PRIVATE_ICON;
baseIcon.setIcon(visibility, 1);
return baseIcon;
}
private Icon doOverlays(Icon icon) {
if (isStatic() && !isGetter() && !isSetter()) {
icon = overlayIcons(icon, AllIcons.Nodes.StaticMark);
}
if (isFinal()) {
icon = overlayIcons(icon, AllIcons.Nodes.FinalMark);
}
if (isConst()) {
//TODO: find a distinct const icon
icon = overlayIcons(icon, AllIcons.Nodes.FinalMark);
}
return icon;
}
public boolean isConst() {
return findChildByType(DartTokenTypes.CONST) != null;
}
public boolean isFinal() {
return findChildByType(DartTokenTypes.FINAL) != null;
}
public boolean isOperator() {
return findChildByType(DartTokenTypes.OPERATOR) != null;
}
@Override
public boolean isStatic() {
if (this instanceof DartVarDeclarationListPart) {
return ((DartVarDeclarationList)getParent()).getVarAccessDeclaration().isStatic();
}
return findChildByType(DartTokenTypes.STATIC) != null;
}
@Override
public boolean isPublic() {
final String name = getName();
return name != null && !name.startsWith("_");
}
public boolean isConstructor() {
return DartComponentType.typeOf(this) == DartComponentType.CONSTRUCTOR;
}
@Override
public boolean isSetter() {
return findChildByType(DartTokenTypes.SET) != null;
}
@Override
public boolean isGetter() {
return findChildByType(DartTokenTypes.GET) != null;
}
@Override
public boolean isAbstract() {
final DartComponentType componentType = DartComponentType.typeOf(this);
return componentType == DartComponentType.CLASS &&
findChildByType(DartTokenTypes.ABSTRACT) != null
||
componentType == DartComponentType.METHOD &&
findChildByType(DartTokenTypes.EXTERNAL) == null &&
findChildByType(DartTokenTypes.FUNCTION_BODY) == null;
}
@Override
public boolean isUnitMember() {
return PsiTreeUtil.getParentOfType(this, DartComponent.class) == null;
}
@Override
@Nullable
public DartMetadata getMetadataByName(@NotNull final String name) {
for (DartMetadata metadata : PsiTreeUtil.getChildrenOfTypeAsList(this, DartMetadata.class)) {
if (name.equals(metadata.getReferenceExpression().getText())) {
return metadata;
}
}
return null;
}
@Override
public ItemPresentation getPresentation() {
return new ItemPresentation() {
@Override
public String getPresentableText() {
final StringBuilder result = new StringBuilder();
result.append(getComponentName());
final DartComponentType type = DartComponentType.typeOf(AbstractDartComponentImpl.this);
if ((type == DartComponentType.METHOD ||
type == DartComponentType.FUNCTION ||
type == DartComponentType.CONSTRUCTOR ||
type == DartComponentType.OPERATOR) && !(isGetter() || isSetter())) {
final String parameterList = DartPresentableUtil.getPresentableParameterList(AbstractDartComponentImpl.this);
result.append("(").append(parameterList).append(")");
}
if (type == DartComponentType.METHOD ||
type == DartComponentType.FIELD ||
type == DartComponentType.FUNCTION ||
type == DartComponentType.OPERATOR) {
final DartReturnType returnType = PsiTreeUtil.getChildOfType(AbstractDartComponentImpl.this, DartReturnType.class);
final DartType dartType = PsiTreeUtil.getChildOfType(AbstractDartComponentImpl.this, DartType.class);
if (returnType != null) {
result.append(" ").append(DartPresentableUtil.RIGHT_ARROW).append(" ");
result.append(DartPresentableUtil.buildTypeText(AbstractDartComponentImpl.this, returnType, null));
}
else if (dartType != null) {
result.append(" ").append(DartPresentableUtil.RIGHT_ARROW).append(" ");
result.append(DartPresentableUtil.buildTypeText(AbstractDartComponentImpl.this, dartType, null));
}
}
return result.toString();
}
@Nullable
private String getComponentName() {
String name = getName();
if (DartComponentType.typeOf(AbstractDartComponentImpl.this) == DartComponentType.CONSTRUCTOR) {
DartClass dartClass = PsiTreeUtil.getParentOfType(AbstractDartComponentImpl.this, DartClass.class);
if (dartClass == null) {
return name;
}
return StringUtil.isEmpty(name) ? dartClass.getName() : dartClass.getName() + "." + name;
}
return name;
}
@Override
public String getLocationString() {
if (!isValid()) {
return "";
}
if (!(AbstractDartComponentImpl.this instanceof DartClass)) {
final DartClass dartClass = PsiTreeUtil.getParentOfType(AbstractDartComponentImpl.this, DartClass.class);
if (dartClass != null) {
return dartClass.getName();
}
}
DartExecutionScope root = PsiTreeUtil.getTopmostParentOfType(AbstractDartComponentImpl.this, DartExecutionScope.class);
DartPartOfStatement partOfStatement = PsiTreeUtil.getChildOfType(root, DartPartOfStatement.class);
return partOfStatement == null ? null : partOfStatement.getLibraryName();
}
@Override
public Icon getIcon(boolean open) {
return AbstractDartComponentImpl.this.getIcon(0);
}
};
}
@Override
public int getTextOffset() {
final DartComponentName name = getComponentName();
return name != null ? name.getTextOffset() : super.getTextOffset();
}
}