package org.jetbrains.plugins.ruby.motion.symbols; import com.intellij.openapi.module.Module; import com.intellij.psi.PsiElement; import com.jetbrains.cidr.CocoaDocumentationManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.ruby.motion.RubyMotionUtil; import org.jetbrains.plugins.ruby.motion.bridgesupport.Class; import org.jetbrains.plugins.ruby.motion.bridgesupport.Function; import org.jetbrains.plugins.ruby.motion.bridgesupport.InheritanceInfoHolder; import org.jetbrains.plugins.ruby.ruby.codeInsight.symbols.Type; import org.jetbrains.plugins.ruby.ruby.codeInsight.symbols.structure.*; import org.jetbrains.plugins.ruby.ruby.codeInsight.symbols.v2.SymbolPsiProcessor; import java.util.Collections; import java.util.List; /** * @author Dennis.Ushakov */ public class MotionClassSymbol extends SymbolImpl implements MotionSymbol { @NotNull private final Module myModule; @NotNull private final List<Class> myClasses; public MotionClassSymbol(@NotNull Module module, @NotNull List<Class> classes) { super(module.getProject(), classes.get(0).getName(), Type.CLASS, null); myModule = module; myClasses = classes; } @NotNull @Override public Children getChildren() { return new ChildrenImpl() { @Override public boolean processChildren(SymbolPsiProcessor processor, final PsiElement invocationPoint) { final MotionClassSymbol parent = MotionClassSymbol.this; for (Class clazz : myClasses) { for (Function function : clazz.getFunctions()) { for (RTypedSyntheticSymbol functionSymbol : MotionSymbolUtil.createSelectorSymbols(myModule, parent, function)) { if (!processor.process(functionSymbol)) { return false; } } } for (Class subClass : clazz.getSubClasses()) { final MotionClassSymbol symbol = new MotionClassSymbol(myModule, Collections.singletonList(subClass)); if (!processor.process(symbol)) { return false; } } } final Symbol superClass = getSuperClassSymbol(invocationPoint); if (superClass != null) { final Children children = superClass.getChildren(); if (!children.processChildren(processor, invocationPoint)) { return false; } } return true; } }; } @Nullable public Symbol getSuperClassSymbol(@Nullable PsiElement invocationPoint) { String sdkVersion = RubyMotionUtil.getInstance().getSdkVersion(myModule); String ancestor = InheritanceInfoHolder.getInstance().getInheritance(myName, sdkVersion); if (ancestor == null) { if (RubyMotionUtil.getInstance().isOSX(myModule)) { ancestor = InheritanceInfoHolder.getInstance().getInheritance(myName, "10.10"); } else if (!RubyMotionUtil.getInstance().isAndroid(myModule)) { ancestor = InheritanceInfoHolder.getInstance().getInheritance(myName, "9.3"); } } return ancestor != null ? SymbolUtil.findSymbol(getProject(), Type.CLASS, ancestor, invocationPoint) : null; } @Override public CocoaDocumentationManager.DocTokenType getInfoType() { return CocoaDocumentationManager.DocTokenType.CLASS; } @Override public String getInfoName() { final String name = getName(); assert name != null; return name; } @NotNull @Override public Module getModule() { return myModule; } }