// Path: src/org/emberjs/lang/psi/EmberJSAsExpression.java
// public class EmberJSAsExpression extends JSBinaryExpressionImpl {
//     public EmberJSAsExpression(ASTNode node) {
//         super(node);
//     }
// 
//     @Nullable
//     public JSDefinitionExpression getDefinition() {
//         return PsiTreeUtil.getChildOfType(this, JSDefinitionExpression.class);
//     }
// 
//     @Override
//     public void accept(@NotNull PsiElementVisitor visitor) {
//         if (visitor instanceof EmberJSElementVisitor) {
//             ((EmberJSElementVisitor)visitor).visitEmberJSAsExpression(this);
//         } else {
//             super.accept(visitor);
//         }
//     }
// 
//     public static boolean isAsControllerRef(PsiReference ref, PsiElement parent) {
//         if (parent instanceof EmberJSAsExpression && ref == parent.getFirstChild()) {
//             return true;
//         }
//         final InjectedLanguageManager injector = InjectedLanguageManager.getInstance(parent.getProject());
//         final PsiLanguageInjectionHost host = injector.getInjectionHost(parent);
//         final PsiElement hostParent = host instanceof XmlAttributeValueImpl ? host.getParent() : null;
//         final String normalized = hostParent instanceof XmlAttribute ?
//                 ComponentUtil.getAttributeName(((XmlAttribute) hostParent).getName()) : null;
// 
//         // TODO: Do some kind of test
//         return true;
//         // return "ng-controller".equals(normalized);
//     }
// }
// 
// Path: src/org/emberjs/lang/psi/EmberJSRecursiveVisitor.java
// public class EmberJSRecursiveVisitor extends EmberJSElementVisitor {
//     @Override
//     public void visitElement(PsiElement element) {
//         element.acceptChildren(this);
//     }
// }
// 
// Path: src/org/emberjs/lang/psi/EmberJSRepeatExpression.java
// public class EmberJSRepeatExpression extends JSExpressionImpl {
//     public EmberJSRepeatExpression(ASTNode node) {
//         super(node);
//     }
// 
//     public Collection<JSDefinitionExpression> getDefinitions() {
//         final PsiElement firstChild = getFirstChild();
//         if (firstChild instanceof JSDefinitionExpression) {
//             return Collections.singletonList((JSDefinitionExpression)firstChild);
//         } else if (firstChild instanceof JSParenthesizedExpression) {
//             final PsiElement commaExpression = PsiTreeUtil.findChildOfType(firstChild, JSCommaExpression.class);
//             if (commaExpression != null) {
//                 return PsiTreeUtil.findChildrenOfType(commaExpression, JSDefinitionExpression.class);
//             }
//         }
//         return Collections.emptyList();
//     }
// 
//     public JSExpression getCollection() {
//         final ASTNode myNode = getNode();
//         final ASTNode secondExpression = myNode.findChildByType(
//                 JSElementTypes.EXPRESSIONS, myNode.findChildByType(JSTokenTypes.IN_KEYWORD)
//         );
//         return secondExpression != null ? (JSExpression)secondExpression.getPsi() : null;
//     }
// 
//     @Override
//     public void accept(@NotNull PsiElementVisitor visitor) {
//         if (visitor instanceof EmberJSElementVisitor) {
//             ((EmberJSElementVisitor)visitor).visitEmberJSRepeatExpression(this);
//         } else {
//             super.accept(visitor);
//         }
//     }
// }


import com.intellij.codeInsight.completion.CompletionUtil;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.lang.javascript.flex.XmlBackedJSClassImpl;
import com.intellij.lang.javascript.psi.JSDefinitionExpression;
import com.intellij.lang.javascript.psi.JSFile;
import com.intellij.lang.javascript.psi.JSNamedElement;
import com.intellij.lang.javascript.psi.resolve.ImplicitJSVariableImpl;
import com.intellij.lang.javascript.psi.resolve.JSResolveUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.psi.impl.source.html.HtmlEmbeddedContentImpl;
import com.intellij.psi.impl.source.resolve.FileContextUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.*;
import com.intellij.util.Consumer;
import org.emberjs.lang.psi.EmberJSAsExpression;
import org.emberjs.lang.psi.EmberJSRecursiveVisitor;
import org.emberjs.lang.psi.EmberJSRepeatExpression;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
package org.emberjs.codeInsight;



/**
 * @author Dennis.Ushakov
 */
public class EmberJSProcessor {
    private static final Map<String, String> NG_REPEAT_IMPLICITS = new HashMap<String, String>();
    static {
        NG_REPEAT_IMPLICITS.put("$alias", "String");
        NG_REPEAT_IMPLICITS.put("$model", "String");
    }


    public static void process(final PsiElement element, final Consumer<JSNamedElement> consumer) {
        final PsiElement original = CompletionUtil.getOriginalOrSelf(element);
        final PsiFile hostFile = FileContextUtil.getContextFile(original != element ? original : element.getContainingFile().getOriginalFile());
        if (hostFile == null) return;

        final XmlFile file = (XmlFile)hostFile;
        final JSResolveUtil.JSInjectedFilesVisitor visitor = new JSResolveUtil.JSInjectedFilesVisitor() {
            @Override
            protected void process(JSFile file) {
                file.accept(new EmberJSRecursiveVisitor() {
                    @Override
                    public void visitJSDefinitionExpression(JSDefinitionExpression node) {
                        if (scopeMatches(original, node)) {
                            consumer.consume(node);
                        }
                        super.visitJSDefinitionExpression(node);

                    }

                    // handlebars {{#each alias as
                    @Override
// Path: src/org/emberjs/lang/psi/EmberJSAsExpression.java
// public class EmberJSAsExpression extends JSBinaryExpressionImpl {
//     public EmberJSAsExpression(ASTNode node) {
//         super(node);
//     }
// 
//     @Nullable
//     public JSDefinitionExpression getDefinition() {
//         return PsiTreeUtil.getChildOfType(this, JSDefinitionExpression.class);
//     }
// 
//     @Override
//     public void accept(@NotNull PsiElementVisitor visitor) {
//         if (visitor instanceof EmberJSElementVisitor) {
//             ((EmberJSElementVisitor)visitor).visitEmberJSAsExpression(this);
//         } else {
//             super.accept(visitor);
//         }
//     }
// 
//     public static boolean isAsControllerRef(PsiReference ref, PsiElement parent) {
//         if (parent instanceof EmberJSAsExpression && ref == parent.getFirstChild()) {
//             return true;
//         }
//         final InjectedLanguageManager injector = InjectedLanguageManager.getInstance(parent.getProject());
//         final PsiLanguageInjectionHost host = injector.getInjectionHost(parent);
//         final PsiElement hostParent = host instanceof XmlAttributeValueImpl ? host.getParent() : null;
//         final String normalized = hostParent instanceof XmlAttribute ?
//                 ComponentUtil.getAttributeName(((XmlAttribute) hostParent).getName()) : null;
// 
//         // TODO: Do some kind of test
//         return true;
//         // return "ng-controller".equals(normalized);
//     }
// }
// 
// Path: src/org/emberjs/lang/psi/EmberJSRecursiveVisitor.java
// public class EmberJSRecursiveVisitor extends EmberJSElementVisitor {
//     @Override
//     public void visitElement(PsiElement element) {
//         element.acceptChildren(this);
//     }
// }
// 
// Path: src/org/emberjs/lang/psi/EmberJSRepeatExpression.java
// public class EmberJSRepeatExpression extends JSExpressionImpl {
//     public EmberJSRepeatExpression(ASTNode node) {
//         super(node);
//     }
// 
//     public Collection<JSDefinitionExpression> getDefinitions() {
//         final PsiElement firstChild = getFirstChild();
//         if (firstChild instanceof JSDefinitionExpression) {
//             return Collections.singletonList((JSDefinitionExpression)firstChild);
//         } else if (firstChild instanceof JSParenthesizedExpression) {
//             final PsiElement commaExpression = PsiTreeUtil.findChildOfType(firstChild, JSCommaExpression.class);
//             if (commaExpression != null) {
//                 return PsiTreeUtil.findChildrenOfType(commaExpression, JSDefinitionExpression.class);
//             }
//         }
//         return Collections.emptyList();
//     }
// 
//     public JSExpression getCollection() {
//         final ASTNode myNode = getNode();
//         final ASTNode secondExpression = myNode.findChildByType(
//                 JSElementTypes.EXPRESSIONS, myNode.findChildByType(JSTokenTypes.IN_KEYWORD)
//         );
//         return secondExpression != null ? (JSExpression)secondExpression.getPsi() : null;
//     }
// 
//     @Override
//     public void accept(@NotNull PsiElementVisitor visitor) {
//         if (visitor instanceof EmberJSElementVisitor) {
//             ((EmberJSElementVisitor)visitor).visitEmberJSRepeatExpression(this);
//         } else {
//             super.accept(visitor);
//         }
//     }
// }


// Path: src/org/emberjs/codeInsight/EmberJSProcessor.java
import com.intellij.codeInsight.completion.CompletionUtil;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.lang.javascript.flex.XmlBackedJSClassImpl;
import com.intellij.lang.javascript.psi.JSDefinitionExpression;
import com.intellij.lang.javascript.psi.JSFile;
import com.intellij.lang.javascript.psi.JSNamedElement;
import com.intellij.lang.javascript.psi.resolve.ImplicitJSVariableImpl;
import com.intellij.lang.javascript.psi.resolve.JSResolveUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.psi.impl.source.html.HtmlEmbeddedContentImpl;
import com.intellij.psi.impl.source.resolve.FileContextUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.*;
import com.intellij.util.Consumer;
import org.emberjs.lang.psi.EmberJSAsExpression;
import org.emberjs.lang.psi.EmberJSRecursiveVisitor;
import org.emberjs.lang.psi.EmberJSRepeatExpression;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;

package org.emberjs.codeInsight;



/**
 * @author Dennis.Ushakov
 */
public class EmberJSProcessor {
    private static final Map<String, String> NG_REPEAT_IMPLICITS = new HashMap<String, String>();
    static {
        NG_REPEAT_IMPLICITS.put("$alias", "String");
        NG_REPEAT_IMPLICITS.put("$model", "String");
    }


    public static void process(final PsiElement element, final Consumer<JSNamedElement> consumer) {
        final PsiElement original = CompletionUtil.getOriginalOrSelf(element);
        final PsiFile hostFile = FileContextUtil.getContextFile(original != element ? original : element.getContainingFile().getOriginalFile());
        if (hostFile == null) return;

        final XmlFile file = (XmlFile)hostFile;
        final JSResolveUtil.JSInjectedFilesVisitor visitor = new JSResolveUtil.JSInjectedFilesVisitor() {
            @Override
            protected void process(JSFile file) {
                file.accept(new EmberJSRecursiveVisitor() {
                    @Override
                    public void visitJSDefinitionExpression(JSDefinitionExpression node) {
                        if (scopeMatches(original, node)) {
                            consumer.consume(node);
                        }
                        super.visitJSDefinitionExpression(node);

                    }

                    // handlebars {{#each alias as
                    @Override
                    public void visitEmberJSAsExpression(EmberJSAsExpression asExpression) {