/*
 *
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package org.apache.royale.compiler.internal.scopes;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.royale.compiler.common.ASImportTarget;
import org.apache.royale.compiler.common.DependencyType;
import org.apache.royale.compiler.common.IImportTarget;
import org.apache.royale.compiler.common.NodeReference;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.definitions.IClassDefinition;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.INamespaceDefinition;
import org.apache.royale.compiler.definitions.IQualifiers;
import org.apache.royale.compiler.definitions.IScopedDefinition;
import org.apache.royale.compiler.definitions.references.INamespaceReference;
import org.apache.royale.compiler.internal.definitions.AmbiguousDefinition;
import org.apache.royale.compiler.internal.definitions.ClassDefinition;
import org.apache.royale.compiler.internal.definitions.ClassDefinitionBase;
import org.apache.royale.compiler.internal.definitions.FunctionDefinition;
import org.apache.royale.compiler.internal.definitions.InterfaceDefinition;
import org.apache.royale.compiler.internal.definitions.NamespaceDefinition;
import org.apache.royale.compiler.internal.definitions.ScopedDefinitionBase;
import org.apache.royale.compiler.internal.projects.CompilerProject;
import org.apache.royale.compiler.internal.tree.as.ScopedBlockNode;
import org.apache.royale.compiler.internal.workspaces.Workspace;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.scopes.IDefinitionSet;
import org.apache.royale.compiler.tree.as.IForLoopNode;
import org.apache.royale.compiler.tree.as.IScopedNode;
import org.apache.royale.compiler.units.ICompilationUnit;
import org.apache.royale.compiler.workspaces.IWorkspace;
import org.apache.royale.utils.CheapArray;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;

/**
 * IASScope implementation for class, interface, function, and 'with' scopes.
 */
public abstract class ASScope extends ASScopeBase
{
    private static String[] EMPTY_STRING_ARRAY = new String[0];

    protected static final NamespaceDefinition.IUseNamespaceDirective[] EMPTY_USE_ARRAY =
            new NamespaceDefinition.IUseNamespaceDirective[0];
    
    private static IForLoopNode[] EMPTY_LOOPCHECK_ARRAY = new IForLoopNode[0];

    /**
     * Constructor
     * 
     * @param block block node to which this scope belongs
     */
    public ASScope(ASScope containingScope, ScopedBlockNode block)
    {
        super();
        setContainingScope(containingScope);

        if (block != null)
        {
            block.setScope(this);
            // Node reference constructor only works
            // if the setContainingScope has already be called
            // above.
            scopedNodeRef = new NodeReference(block);
        }
    }

    public ASScope(ASScope containingScope)
    {
        this(containingScope, null);
    }

    private ASScope containingScope;

    /**
     * Weak ref back to the Block node to which this scope belongs TODO: Remove
     * once code model clients don't depend on this anymore
     */
    protected NodeReference scopedNodeRef = NodeReference.noReference;

    /**
     * List of all imports in scope
     */
    private Object importsInScope = null;

    /**
     * List of all aliases for imports in scope
     */
    private Map<String, String> aliasToImportQualifiedName = null;

    private Set<String> packageNames = null;

    private Object usedNamespaces = null;

    private NamespaceDefinition.INamespaceDirective firstNamespaceDirective;

    private NamespaceDefinition.INamespaceDirective lastNamespaceDirective;

    private boolean inWith = false;
    
    private Object loopChecks = null;
    public boolean getHasLoopCheck(){
        return loopChecks != null;
    }
    public void addLoopCheck(IForLoopNode value){
        if (loopChecks == null) loopChecks = CheapArray.create(1);
        else {
            int len = CheapArray.size(loopChecks);
            boolean exitEarly = false;
            //sometimes the same for loop exists as more than one instance for the same source locations.
            //this seems to happen somtimes in mxml code blocks.
            //The following makes sure that only one instance representing the same source code location is tracked
            //for ArrayLike inspection
            for (int i=0; i<len; i++) {
                IForLoopNode existing = (IForLoopNode) CheapArray.get(i, loopChecks);
                if (existing.getAbsoluteStart() == value.getAbsoluteStart()
                    && existing.getAbsoluteEnd() == value.getAbsoluteEnd()
                    && existing.getSourcePath().equals(value.getSourcePath())) {
                    CheapArray.replace(i, value, loopChecks);
                    exitEarly = true;
                    break;
                }
            }
            if (exitEarly) {
               return;
            }
        }
        CheapArray.add(value, loopChecks);
    }
    public IForLoopNode[] getLoopChecks(boolean remove){
        IForLoopNode[] returnLoopChecks = (IForLoopNode[]) CheapArray.toArray(loopChecks, EMPTY_LOOPCHECK_ARRAY);
        if (remove) loopChecks = null;
        return returnLoopChecks;
    }
    /**
     * Sets the scope which lexically contains this scope.
     * 
     * @param containingScope The containing scope.
     */
    public void setContainingScope(ASScope containingScope)
    {
        this.containingScope = containingScope;

        // calc this once, as it shouldn't change
        this.inWith = getContainingWithScope() != null;
    }

    /**
     * Compact the ArrayLists in this scope (so that they don't take up as much
     * space)
     */
    @Override
    public void compact()
    {
        super.compact();

        if (importsInScope != null)
            CheapArray.optimize(importsInScope, EMPTY_STRING_ARRAY);
        
        if (usedNamespaces != null)
            CheapArray.optimize(usedNamespaces, EMPTY_USE_ARRAY);

        if (loopChecks != null)
            CheapArray.optimize(loopChecks, EMPTY_LOOPCHECK_ARRAY);
    }

    public void addNamespaceDirective(NamespaceDefinition.INamespaceDirective directive)
    {
        if (lastNamespaceDirective != null)
        {
            lastNamespaceDirective.setNext(directive);
            lastNamespaceDirective = directive;
        }
        else
        {
            assert firstNamespaceDirective == null;
            firstNamespaceDirective = directive;
            lastNamespaceDirective = directive;
        }
    }

    public void addUseDirective(NamespaceDefinition.IUseNamespaceDirective useDirective)
    {
        addNamespaceDirective(useDirective);
        if (usedNamespaces == null)
            usedNamespaces = CheapArray.create(1);
        CheapArray.add(useDirective, usedNamespaces);
    }

    public boolean hasImportAlias(String alias)
    {
        return aliasToImportQualifiedName != null
                && aliasToImportQualifiedName.containsKey(alias);
    }

    public void addImport(String target, String alias)
    {
        if (aliasToImportQualifiedName == null)
        {
            aliasToImportQualifiedName = new HashMap<String, String>();
        }
        assert !hasImportAlias(alias) : "addImport() should not be called with an existing alias";
        addImport(target);
        aliasToImportQualifiedName.put(alias, target);
    }

    public void addImport(String target)
    {
        if (importsInScope == null)
        {
            importsInScope = CheapArray.create(20);
            packageNames = new HashSet<String>();
        }

        CheapArray.add(target, importsInScope);

        int idx = target.lastIndexOf('.');

        if (idx != -1)
        {
            String packName = target.substring(0, idx);
            if (!target.endsWith(".*"))
            {
                // If this is not a wildcard import, then add the imported name
                // to the importedNames table so we can construct the right namespace
                // set for that name when we see a reference to it.
                String defName = target.substring(idx + 1, target.length());

                if (importedNames == null)
                    importedNames = new HashMap<String, Set<String>>();

                Set<String> s = importedNames.get(defName);
                if (s == null)
                {
                    s = new LinkedHashSet<String>();
                    importedNames.put(defName, s);
                }
                s.add(packName);
            }
            // Whether the import was a wildcard or not, the packageName contributes to the
            // set of known package names.
            packageNames.add(packName);
        }
    }

    @Override
    public ASScope getContainingScope()
    {
        return containingScope;
    }

    /**
     * Re-connects this scope to the syntax tree node that corresponds to this
     * scope.
     * 
     * @param node {@link IScopedNode} that corresponds to this scope.
     */
    public void reconnectScopeNode(IScopedNode node)
    {
        scopedNodeRef.reconnectNode(node);
    }

    @Override
    public IScopedNode getScopeNode()
    {
        IWorkspace w = getWorkspace();
        return (IScopedNode)scopedNodeRef.getNode(w, this);
    }

    public String[] getImports()
    {
        return (String[])CheapArray.toArray(importsInScope, EMPTY_STRING_ARRAY);
    }

    private ScopedDefinitionBase containingDefinition;

    @Override
    public ScopedDefinitionBase getDefinition()
    {
        return containingDefinition;
    }

    public void setContainingDefinition(ScopedDefinitionBase value)
    {
        containingDefinition = value;
    }

    /**
     * For debugging only.
     */
    @Override
    protected String toStringHeader()
    {
        StringBuilder sb = new StringBuilder();

        sb.append(super.toStringHeader());

        IDefinition definition = getDefinition();
        if (definition != null)
        {
            sb.append(" for ");
            sb.append(definition.toString());
        }

        return sb.toString();
    }

    /**
     * Determine whether the string passed in is a known package name The scope
     * will check if the package was introduced by any of it's imports, and if
     * not will delegate to its containing scope.
     * 
     * @param p the string to test
     * @return true is p is a package name
     */
    public boolean isPackageName(String p)
    {
        if (packageNames != null)
        {
            if (packageNames.contains(p))
            {
                return true;
            }
        }

        if (containingScope != null)
            return containingScope.isPackageName(p);

        return false;
    }

    /**
     * Return the additional namespaces for a reference, if the name has been
     * explicitly imported. If 'a.b.Foo' has been imported, and we see reference
     * to Foo, this will return the INamespaceDefinition for 'a.b'. If the name
     * has not been explicitly imported then this method will return the empty
     * set.
     * 
     * @param project CompilerProject to use to resolve the package INamespaces
     * @param name The name of the reference
     * @return A Set<INamespaceDefinition> representing the packages from the
     * imports if the name was explicitly imported. Returns the empty set if the
     * name was not explicitly imported.
     */
    public Set<INamespaceDefinition> getExplicitImportQualifiers(CompilerProject project, String name)
    {
        Set<INamespaceDefinition> nsSet = new LinkedHashSet<INamespaceDefinition>();

        Workspace workspace = project.getWorkspace();

        getContainingScopeExplicitImports(project, name, nsSet);

        if (importedNames != null)
        {
            // Was it an import in this scope
            Set<String> packages = importedNames.get(name);
            if (packages != null)
            {
                for (String s : packages)
                {
                    nsSet.add(workspace.getPackageNamespaceDefinitionCache().get(s, false));
                }
            }
        }
        return nsSet.size() > 0 ? nsSet : Collections.<INamespaceDefinition> emptySet();
    }

    /**
     * Get the additional namespaces for a reference, if the name has been explicitly imported in
     * a containing scope
     * @param project   the active project
     * @param name      the name of the reference
     * @param nsSet     the namespace set to add the namespaces to
     */
    protected void getContainingScopeExplicitImports (CompilerProject project, String name, Set<INamespaceDefinition> nsSet)
    {
        if (getContainingScope() != null)
        {
            // check any containing scopes
            nsSet.addAll(getContainingScope().getExplicitImportQualifiers(project, name));
        }
    }

    /**
     * Maps names to the package name used to look them up - this is used to
     * store explicit imports of definitions (import a.b.Foo)
     */
    private Map<String, Set<String>> importedNames;

    protected INamespaceReference[] getUsedNamespaces()
    {
        return (INamespaceReference[])CheapArray.toArray(usedNamespaces, EMPTY_USE_ARRAY);
    }

    /**
     * Gets the first namespace definition or use namespace directive in the
     * scope.
     * 
     * @return The first namespace definition or use namespace directive in the
     * scope.
     */
    public NamespaceDefinition.INamespaceDirective getFirstNamespaceDirective()
    {
        return firstNamespaceDirective;
    }

    /**
     * Adds {@link INamespaceDefinition}'s for each import in this scope to the
     * specified namespace set.
     * 
     * @param workspace {@link IWorkspace} used to construct
     * {@link INamespaceDefinition}'s for imported packages.
     * @param namespaceSet Namespace set to add namespaces to.
     */
    public void addLocalImportsToNamespaceSet(IWorkspace workspace, Set<INamespaceDefinition> namespaceSet)
    {
        String[] imports = getImports();
        if (imports != null)
        {
            for (String importStr : imports)
            {
                IImportTarget importTarget = ASImportTarget.get(workspace, importStr);
                // Only wildcard imports contribute to the namespace set
                // e.g. a.b.*, but not a.b.Foo
                if (importTarget.isWildcard())
                    namespaceSet.add(importTarget.getNamespace());
            }
        }
    }

    /**
     * Calculate the namespace set to use to resolve name. If name is an
     * explicitly imported definition, then the namespace set will consist of
     * the package name from the import(s) plus the open namespace set. If name
     * was not explitly imported then the open namespace set will be calculated
     * and returned
     * 
     * @param project The compiler project
     * @param name A name.
     * @return the namespace set to use to lookup name. This set should not be
     * modified
     */
    public Set<INamespaceDefinition> getNamespaceSetForName(ICompilerProject project, String name)
    {
        // if the name is an alias, we want the original name -JT
        name = resolveBaseNameFromAlias(name);
        if (namespaceSetSameAsContainingScopeNamespaceSet() && getContainingScope() != null)
        {
            // If this scope doesn't contribute anything to the namespace set, then just ask our containing
            // scope for the namespace set.  Doing this before we hit the cache has the benefit that the 
            // namespace set will only get cached in the containing scopes cache, instead of getting cached
            // in each individual scope cache (e.g. it will be cached in the class scope, instead of in each function
            // scope in the class).  This saves a lot of memory, as many functions will not affect the list 
            // of open namespaces.
            return getContainingScope().getNamespaceSetForName(project, name);
        }
        CompilerProject compilerProject = (CompilerProject)project;
        ASScopeCache scopeCache = compilerProject.getCacheForScope(this);
        return scopeCache.getNamespaceSetForName(name);
    }

    protected boolean namespaceSetSameAsContainingScopeNamespaceSet()
    {
        if ((getImports() != null) || (getUsedNamespaces() != null))
            return false;

        // function with no namespace set modifications, so reuse
        if (containingDefinition instanceof FunctionDefinition)
            return true;

        // TODO: can with scopes also be optimized here?

        return false;
    }

    /**
     * Implementation of getNamespaceSetForName method, above. The scope cache
     * will call this method when it does not already have the results cached
     * 
     * @param project
     * @param name
     * @return the namespace set to use to lookup name. This set should not be
     * modified
     */
    Set<INamespaceDefinition> getNamespaceSetForNameImpl(ICompilerProject project, String name)
    {
        if (namespaceSetSameAsContainingScopeNamespaceSet())
        {
            ASScope containingScope = getContainingScope();
            if (containingScope != null)
            {
                return containingScope.getNamespaceSetForName(project, name);
            }
        }

        Set<INamespaceDefinition> openNamespaces = getNamespaceSet(project);
        // If the reference has been explicitly imported, then we are a qualified name lookup
        // e.g. 'import a.b.Foo' means that any reference to Foo must have the package namespace of 'a.b' added
        // to its set of namespaces
        Set<INamespaceDefinition> additionalNamespaces = getExplicitImportQualifiers((CompilerProject)project, name);
        if (additionalNamespaces != null)
        {
            Set<INamespaceDefinition> newSet = new LinkedHashSet<INamespaceDefinition>();
            newSet.addAll(openNamespaces);
            newSet.addAll(additionalNamespaces);
            return newSet;
        }
        else
        {
            return openNamespaces;
        }
    }

    /**
     * Computes and returns the namespace set for this scope.
     * <p>
     * The returned set should not be modified.
     * 
     * @param project The compiler project.
     * @return The namespace set for this scope. The returned set should not be
     * modified
     */
    public Set<INamespaceDefinition> getNamespaceSet(ICompilerProject project)
    {
        CompilerProject compilerProject = (CompilerProject)project;
        ASScopeCache scopeCache = compilerProject.getCacheForScope(this);
        return scopeCache.getNamespaceSet();
    }

    /**
     * Computes and returns the namespace set for this scope. This is the
     * implementation of getNamespaceSet above. The scope cache will call this
     * method when it does not have a cached result for the namespace set.
     * <p>
     * The returned set should not be modified.
     * 
     * @param project
     * @return The namespace set for this scope. The returned set should not be
     * modified
     */
    Set<INamespaceDefinition> getNamespaceSetImpl(ICompilerProject project)
    {
        if (namespaceSetSameAsContainingScopeNamespaceSet())
        {
            ASScope containingScope = getContainingScope();
            if (containingScope != null)
            {
                return containingScope.getNamespaceSetImpl(project);
            }
        }

        CompilerProject compilerProject = (CompilerProject)project;
        IWorkspace workspace = compilerProject.getWorkspace();

        Set<INamespaceDefinition> result = new LinkedHashSet<INamespaceDefinition>();

        // First add the imports, use namespaces, etc from this scope
        this.addLocalImportsToNamespaceSet(workspace, result);
        INamespaceReference[] usedNamespaces = this.getUsedNamespaces();
        if (usedNamespaces != null)
        {
            for (INamespaceReference usedNamespaceReference : usedNamespaces)
            {
                INamespaceDefinition usedNamespace = usedNamespaceReference.resolveNamespaceReference(compilerProject);
                if (usedNamespace != null)
                    result.add(usedNamespace);
            }
        }

        this.addImplicitOpenNamespaces(compilerProject, result);

        // Next add the open namespaces from the containing scope
        addNamespacesFromContainingScope(compilerProject, result);

        Set<INamespaceDefinition> emptyNamespaceSet = Collections.emptySet();
        result = result.size() == 0 ? emptyNamespaceSet : result;
        return result;
    }

    /**
     * Add the open namespaces from the containing scope to the namespace set passed in
     * @param compilerProject   the active project
     * @param result            the Namespace Set to add namespaces to
     */
    protected void addNamespacesFromContainingScope (CompilerProject compilerProject, Set<INamespaceDefinition> result)
    {
        ASScope containingScope = this.getContainingScope();
        if (containingScope != null)
        {
            result.addAll(containingScope.getNamespaceSet(compilerProject));
        }
    }

    public void addImplicitOpenNamespaces(CompilerProject compilerProject, Set<INamespaceDefinition> result)
    {
        // By default there is nothing to do here. 
        // overrides in ASFileScope, PackageScope, and TypeScope.
    }

    /**
     * Adds all definitions ( including definitions from base types ) in the
     * current scope to the specified collections of definitions that have a
     * namespace qualifier in the specified definition set, when looking for
     * definitions in the scope chain.
     * 
     * @param project {@link CompilerProject} used to resolve reference to
     * definitions outside of the {@link ICompilationUnit} that contains this
     * scope.
     * @param defs Collection that found {@link IDefinition}'s are added to.
     * @param namespaceSet Namespace set in which the qualifier of any matching
     * definition must exist to be considered a match.
     */
    public void getAllPropertiesForScopeChain(CompilerProject project, Collection<IDefinition> defs, Set<INamespaceDefinition> namespaceSet)
    {
        getAllLocalProperties(project, defs, namespaceSet, null);
    }

    /**
     * Adds all definitions ( including definitions from base types ) in the
     * current scope to the specified collections of definitions that have a
     * namespace qualifier in the specified definition set, when looking for
     * definitions through a member access.
     * 
     * @param project {@link CompilerProject} used to resolve reference to
     * definitions outside of the {@link ICompilationUnit} that contains this
     * scope.
     * @param defs Collection that found {@link IDefinition}'s are added to.
     * @param namespaceSet Namespace set in which the qualifier of any matching
     * definition must exist to be considered a match.
     */
    public void getAllPropertiesForMemberAccess(CompilerProject project, Collection<IDefinition> defs, Set<INamespaceDefinition> namespaceSet)
    {
        getAllLocalProperties(project, defs, namespaceSet, null);
    }

    /**
     * Gets all definitions (including definitions from base types) that have
     * the specified name to the specified collections of definitions that have
     * a namespace qualifier in the specified definition set, when looking for
     * definitions through a member access.
     * 
     * @param project {@link CompilerProject} used to resolve reference to
     * definitions outside of the {@link ICompilationUnit} that contains this
     * scope.
     * @param memberName the name of the desired definition(s).
     * @param namespaceSet Namespace set in which the qualifier of any matching
     * definition must exist to be considered a match.
     * @return the collection of matching definitions.
     */
    public List<IDefinition> getPropertiesByNameForMemberAccess(CompilerProject project, String memberName, Set<INamespaceDefinition> namespaceSet)
    {
        //  Get the collection of all properties.
        List<IDefinition> result = new ArrayList<IDefinition>();

        getPropertyForMemberAccess(project, result, memberName, namespaceSet, true);

        return result;
    }

    /**
     * Gets the definition (including definitions from base types) that has
     * the specified name and that has a namespace qualifier in the specified
     * namespace set, when looking for definitions through a member access.
     *
     * @param project {@link CompilerProject} used to resolve reference to
     * definitions outside of the {@link ICompilationUnit} that contains this
     * scope.
     * @param memberName the name of the desired definition(s).
     * @param namespaceSet Namespace set in which the qualifier of any matching
     * definition must exist to be considered a match.
     * @return The first definition that matches the name and namespaceSet.  May return the AmbiguousDefinition
     *         if more than one definition in a scope matches.
     */
    public IDefinition getPropertyByNameForMemberAccess(CompilerProject project, String memberName, Set<INamespaceDefinition> namespaceSet)
    {
        List<IDefinition> defs = new ArrayList<IDefinition>();
        getPropertyForMemberAccess(project, defs, memberName, namespaceSet, false);
        return getSingleResult(project, defs);
    }

    /**
     * Finds all the definitions in this scope that match the specified
     * namespace set and base name. This method is intended to implement the
     * getproperty operation defined by AS3 and the VM.
     * <p>
     * If this scope is not for a class or interface definition then only
     * definitions in this scope are considered.
     * <p>
     * If this scope is for a class or interface definition then definitions in
     * this scope and the scope for any implemented or extended interfaces and
     * classes are also considered. Unless findAll is true, then this function
     * returns as soon as one or more definitions has been found that match the
     * namespace set and base name.
     * <p>
     * 
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param defs Collection of {@link IDefinition}'s to add found definitions
     * to.
     * @param baseName The name of the definition(s) to find.
     * @param namespaceSet The namespace set in which a found definition's
     * qualifier must be in.
     * @param findAll If true find all match definitions that match the baseName
     * and namespace set not just those in the first scope that had one or more
     * matches.
     */
    public void getPropertyForMemberAccess(CompilerProject project, Collection<IDefinition> defs, String baseName, Set<INamespaceDefinition> namespaceSet, boolean findAll)
    {
        NamespaceSetPredicate nsPred = new NamespaceSetPredicate(project, namespaceSet);
        Collection<IDefinition> filteredDefs = new FilteredCollection<IDefinition>(nsPred, defs);
        getPropertyForMemberAccess(project, filteredDefs, baseName, nsPred, findAll);
    }


    /**
     * Finds all the definitions in this scope that match the specified
     * namespace set and base name. This method is intended to implement the
     * getproperty operation defined by AS3 and the VM.
     * <p>
     * This version of the method expects that the Collection passed in will implement
     * whatever filtering is necessary, other than filtering based on the base name.
     * For most cases, this means the Collection will be an {@link ASScopeBase.FilteredCollection}
     * with a {@link NamespaceSetPredicate}.
     * The {@link NamespaceSetPredicate} must also be passed down as some name resolution
     * may need it to apply extra namespaces (i.e. deal with protected namespaces)
     *
     * <p>
     * If this scope is not for a class or interface definition then only
     * definitions in this scope are considered.
     * <p>
     * If this scope is for a class or interface definition then definitions in
     * this scope and the scope for any implemented or extended interfaces and
     * classes are also considered. Unless findAll is true, then this function
     * returns as soon as one or more definitions has been found that match the
     * namespace set and base name.
     * <p>
     *
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param defs Collection of {@link IDefinition}'s to add found definitions
     * to.  This collection must perform any necessary filtering of results, other than filtering
     * based on the baseName.
     * @param baseName The name of the definition(s) to find.
     * @param namespaceSet The {@link NamespaceSetPredicate} which the name resolution code
     *                     can use to modify the namespace set as necessary.
     * @param findAll If true find all match definitions that match the baseName
     * and namespace set not just those in the first scope that had one or more
     * matches.
     */
    protected void getPropertyForMemberAccess(CompilerProject project, Collection<IDefinition> defs, String baseName, NamespaceSetPredicate namespaceSet, boolean findAll)
    {
        getLocalProperty(project, defs, baseName, true);
    }

    /**
     * Helper method to get a namespace set for a member access
     */
    private Set<INamespaceDefinition> getNamespaceSetForMemberAccess(ICompilerProject project, IDefinition def, boolean isSuperRef)
    {
        Set<INamespaceDefinition> namespaceSet;
        if (def instanceof InterfaceDefinition)
            // If we are getting a property from an interface, use the special interface namespace set
            namespaceSet = ((InterfaceDefinition)def).getInterfaceNamespaceSet(project);
        else if (isSuperRef)
            namespaceSet = getNamespaceSetForSuper(project, def);
        else
        {
            namespaceSet = getNamespaceSet(project);

            // If the expression a.b occurs inside the class definition for a's type A,
            // then add A's protected namespace so that we can see a protected b.
            if (def == getContainingClass())
                namespaceSet.add(((IClassDefinition)def).getProtectedNamespaceReference());
        }
        return namespaceSet;
    }

    /**
     * Find a property in an IDefinition, using the open namespaces & packages
     * of this scope.
     *
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param def The definition to resolve the property in
     * @param name The name of the definition to find
     * @param isSuperRef whether this lookup is through a 'super' reference - if
     * it is then the namespace set will be adjusted to use the base classes
     * protected namespace instead of the containing classes protected namespace
     * @return The IDefinition for the property, or null if one is not found
     */
    public IDefinition getPropertyFromDef(ICompilerProject project, IDefinition def, String name, boolean isSuperRef)
    {
        CompilerProject compilerProject = (CompilerProject)project;
        Set<INamespaceDefinition> namespaceSet = getNamespaceSetForMemberAccess(project, def, isSuperRef);

        return getPropertyFromDef(compilerProject, def, name, namespaceSet, false);
    }

    /**
     * Find a property in an IDefinition, using the open namespaces & packages
     * of this scope, and any additional constraints that are passed in as a {@link Predicate}.
     *
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param def The definition to resolve the property in
     * @param name The name of the definition to find
     * @param additional A {@link Predicate} that will perform additional filtering of the results.
     *                   This {@link Predicate} will run before any namespace set checking.
     * @param isSuperRef whether this lookup is through a 'super' reference - if
     * it is then the namespace set will be adjusted to use the base classes
     * protected namespace instead of the containing classes protected namespace
     * @return The IDefinition for the property, or null if one is not found
     */
    public IDefinition getPropertyFromDef(ICompilerProject project,
                                          IDefinition def,
                                          String name,
                                          Predicate<IDefinition> additional,
                                          boolean isSuperRef)
    {
        NamespaceSetPredicate nsPred = new NamespaceSetPredicate(project, getNamespaceSetForMemberAccess(project, def, isSuperRef));
        Predicate<IDefinition> combinedPred = Predicates.and(additional, nsPred);
        return getPropertyFromDef((CompilerProject)project, def, name, combinedPred, nsPred, isSuperRef);
    }
    /**
     * Find a property in an IDefinition, using the namespace passed in as the
     * qualifier.
     *
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve references.
     * @param def The definition to resolve the property in
     * @param name The name of the definition to find
     * @param qualifier The namespace to us to look up name
     * @param isSuperRef whether this lookup is through a 'super' reference - if
     * it is then the namespace set will be adjusted to use the base classes
     * protected namespace instead of the containing classes protected namespace
     * @return The IDefinition for the property, or null if one is not found
     */
    public IDefinition getQualifiedPropertyFromDef(ICompilerProject project, IDefinition def, String name,
                                                   INamespaceDefinition qualifier, boolean isSuperRef)
    {
        Set<INamespaceDefinition> namespaceSet = ImmutableSet.of(qualifier);
        if (isSuperRef)
            namespaceSet = adjustNamespaceSetForSuper(def, namespaceSet);

        return getPropertyFromDef((CompilerProject)project, def, name, namespaceSet, false);
    }

    /**
     * Find a property in an IDefinition, using the qualifiers passed in to provide the namespace set.
     *
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve references.
     * @param def The definition to resolve the property in
     * @param name The name of the definition to find
     * @param qualifiers The namespace(s) to us to look up name
     * @param isSuperRef whether this lookup is through a 'super' reference - if
     * it is then the namespace set will be adjusted to use the base classes
     * protected namespace instead of the containing classes protected namespace
     * @return The IDefinition for the property, or null if one is not found
     */
    public IDefinition getQualifiedPropertyFromDef(ICompilerProject project, IDefinition def, String name,
                                                   IQualifiers qualifiers, boolean isSuperRef)
    {
        Set<INamespaceDefinition> namespaceSet = qualifiers.getNamespaceSet();
        if (isSuperRef)
            namespaceSet = adjustNamespaceSetForSuper(def, namespaceSet);

        return getPropertyFromDef((CompilerProject)project, def, name, namespaceSet, false);
    }

    /**
     * Implementation for getPropertyFromDef + getQualifiedPropertyFromDef
     */
    private IDefinition getPropertyFromDef(CompilerProject project, IDefinition def, String name, Set<INamespaceDefinition> namespaceSet, boolean lookForStatics)
    {
        NamespaceSetPredicate nsPred = new NamespaceSetPredicate(project, namespaceSet);
        return getPropertyFromDef(project, def, name, nsPred, nsPred, lookForStatics);
    }

    /**
     * Implementation of getPropertyFromDef + getQualifiedPropertyFromDef
     *
     * @param project           project to resolve references in
     * @param def               The {@link IDefinition} to get the property from
     * @param name              The name to look for
     * @param pred              The {@link Predicate} to use to perform the lookup
     * @param nsPred            The {@link NamespaceSetPredicate} to use if the namespace set needs to be modified
     *                          during lookup
     * @param lookForStatics    whether to find statics or not
     */
    private IDefinition getPropertyFromDef(CompilerProject project,
                                           IDefinition def,
                                           String name,
                                           Predicate<IDefinition> pred,
                                           NamespaceSetPredicate nsPred,
                                           boolean lookForStatics)
    {
        ASScope defScope = (ASScope)(def instanceof IScopedDefinition ? ((IScopedDefinition)def).getContainedScope() : null);

        // TODO: eliminate lookForStatics flag from getPropertyFromDef methods
        if (defScope instanceof TypeScope)
        {
            // Adjust scope if we are looking in a TypeScope
            TypeScope ts = (TypeScope)defScope;
            if (lookForStatics)
                defScope = ts.getStaticScope();
            else
                defScope = ts.getInstanceScope();
        }

        if (defScope != null)
        {
            ArrayList<IDefinition> defs = new ArrayList<IDefinition>(1);

            defScope.getPropertyForMemberAccess(project, new FilteredCollection<IDefinition>(pred, defs), name, nsPred, false);

            return getSingleResult(project, defs);
        }
        return null;
    }

    /**
     * Implementation of getPropertyForScopeChain.
     *
     * This method will filter results based on baseName only - any additional filtering
     * should be done by the {@link Collection} passed in.
     *
     * @param project       {@link CompilerProject} to resolve things in
     * @param defs          The {@link Collection} to add the results to
     * @param baseName      The name of the definition to find
     * @param namespaceSet  the {@link NamespaceSetPredicate} to use if the namespace set needs to be adjusted
     *                      during lookup
     */
    protected void getPropertyForScopeChain(CompilerProject project, Collection<IDefinition> defs, String baseName, NamespaceSetPredicate namespaceSet, boolean findAll)
    {
        getLocalProperty(project, defs, baseName, true);
    }

    protected String resolveBaseNameFromAlias(String possibleAlias)
    {
        if (aliasToImportQualifiedName != null
                && aliasToImportQualifiedName.containsKey(possibleAlias))
        {
            String qualifiedName = aliasToImportQualifiedName.get(possibleAlias);
            int index = qualifiedName.lastIndexOf(".");
            if (index != -1)
            {
                return qualifiedName.substring(index + 1);
            }
            return qualifiedName;
        }
        ASScope containingScope = getContainingScope();
        if (containingScope != null)
        {
            return containingScope.resolveBaseNameFromAlias(possibleAlias);
        }
        return possibleAlias;
    }

    protected String resolveAliasFromQualifiedImport(String qualifiedName)
    {
        if (aliasToImportQualifiedName != null
                && aliasToImportQualifiedName.containsValue(qualifiedName))
        {
            for (String key : aliasToImportQualifiedName.keySet())
            {
                if (aliasToImportQualifiedName.get(key).equals(qualifiedName))
                {
                    return key;
                }
            }
        }
        ASScope containingScope = getContainingScope();
        if (containingScope != null)
        {
            return containingScope.resolveAliasFromQualifiedImport(qualifiedName);
        }
        return null;
    }

    protected String resolveQualifiedNameFromAlias(String possibleAlias)
    {
        if (aliasToImportQualifiedName != null
                && aliasToImportQualifiedName.containsKey(possibleAlias))
        {
            return aliasToImportQualifiedName.get(possibleAlias);
        }
        ASScope containingScope = getContainingScope();
        if (containingScope != null)
        {
            return containingScope.resolveQualifiedNameFromAlias(possibleAlias);
        }
        return possibleAlias;
    }

    /**
     * This is called by {@link ASScopeCache} when there was a cache miss.
     * 
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param baseName base name of the property we are looking for.
     * @param namespaceSet Namespace set in which the qualifier of any found
     * definition must found.
     * @param dt The type of dependency that should be added to the dependency
     * graph when resolving this reference across a compilation unit boundary.
     * @return One or more {@link IDefinition}'s matched by the namespace set
     * and base name.
     */
    public List<IDefinition> findProperty(CompilerProject project, String baseName, Set<INamespaceDefinition> namespaceSet, DependencyType dt)
    {
        return findProperty(project, baseName, namespaceSet, dt, false);
    }

    /**
     * Version of findProperty that determine the results based on the namespace set passed in,
     * along with any additional constraints passed in via the {@link Predicate}.
     *
     *
     * @param project       The {@link CompilerProject} to resolve things in
     * @param baseName      The name to find
     * @param additional    Any additional constraints on the lookup.  This predicate will
     *                      run before any namespace checking occurs.
     * @param namespaceSet  The Namespace set to use for the lookup
     * @param dt            The dependency type to introduce if this resolves to something from
     *                      another compilation unit
     * @return              a List of IDefinition that matched the name, namespace set, and any
     *                      additional constraints specified by the predicate.
     */
    public List<IDefinition> findProperty(CompilerProject project,
                                          String baseName,
                                          Predicate<IDefinition> additional,
                                          Set<INamespaceDefinition> namespaceSet,
                                          DependencyType dt)
    {
        return findProperty(project, baseName, additional, namespaceSet, dt, false);
    }

    /**
     * This is the core <code>findproperty()</code> method. It implements the
     * equivalent of the <code>findprop</code> AVM instruction in Royale.
     * <p>
     * The algorithm searches up the scope chain, starting with this scope, for
     * definitions with the specified base name and namespace set.
     * <p>
     * After the file scope, the project scope is searched if necessary. If
     * definitions are found in the project scope, a dependency is created on
     * the compilation unit that produced them.
     * <p>
     * If the <code>findAll</code> parameter is <code>false</code>, the search
     * stops with the first scope that has one or more matching definition; if
     * it is <code>true</code>, the search continues to find all matching
     * definitions in the entire chain, including the project scope.
     * 
     * @param accumulator Collection to which definitions that match the
     * namespace set and base name are added.
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param baseName base name of the property we are looking for.
     * @param namespaceSet Namespace set in which the qualifier of any found
     * definition must found.
     * @param dt The type of dependency that should be added to the dependency
     * graph when resolving this reference across a compilation unit boundary.
     * @param findAll If true, then find all definitions that match the
     * namespace set and base name, not just those from the first scope with a
     * single match.
     */
    public void findProperty(Collection<IDefinition> accumulator, CompilerProject project,
                              String baseName, Set<INamespaceDefinition> namespaceSet,
                              DependencyType dt, boolean findAll)
    {
        NamespaceSetPredicate nsPred = new NamespaceSetPredicate(project, namespaceSet);
        FilteredCollection<IDefinition> filteredCollection = new FilteredCollection<IDefinition>(nsPred, accumulator);
        findProperty(filteredCollection, project, baseName, nsPred, dt, findAll);
    }

    /**
     * This is the implementation of the various <code>findproperty()</code> methods. It implements the
     * equivalent of the <code>findprop</code> AVM instruction in Royale.
     * <p>
     * The algorithm searches up the scope chain, starting with this scope, for
     * definitions with the specified base name.
     * <p>
     * If any additional constraints are required (e.g. filtering based on the namespace set), then
     * callers should pass in an {@link ASScopeBase.FilteredCollection} as the accumulator that will implement those
     * constraints.  For the common case, the accumulator will be an {@link ASScopeBase.FilteredCollection}
     * with a {@link NamespaceSetPredicate}.
     * <p>
     * After the file scope, the project scope is searched if necessary. If
     * definitions are found in the project scope, a dependency is created on
     * the compilation unit that produced them.
     * <p>
     * If the <code>findAll</code> parameter is <code>false</code>, the search
     * stops with the first scope that has one or more matching definition; if
     * it is <code>true</code>, the search continues to find all matching
     * definitions in the entire chain, including the project scope.
     *
     * @param accumulator Collection to which definitions that match the
     * base name are added.
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param baseName base name of the property we are looking for.
     * @param nsPred The {@link NamespaceSetPredicate}, if one is being used, that the lookup
     *               can modify as it walks up the scope chain (necessary to handle protected correctly).
     * @param dt The type of dependency that should be added to the dependency
     * graph when resolving this reference across a compilation unit boundary.
     * @param findAll If true, then find all definitions that match the
     * namespace set and base name, not just those from the first scope with a
     * single match.
     */
    protected void findProperty(Collection<IDefinition> accumulator, CompilerProject project,
                             String baseName, NamespaceSetPredicate nsPred,
                             DependencyType dt, boolean findAll)
    {

        assert accumulator.isEmpty() : "findProperty() should not be called with a non-empty collection";
        assert baseName.indexOf('.') == -1 : "baseName must not be any sort of qname " + baseName;

        // Walk the scope chain starting with this scope.
        // This loop may go as far as the file scope, whose containing scope is null. 
        // But it may break out early; lastSearchScope will keep track of how far it went. 
        ASScope lastSearchedScope = null;
        String baseNameForAlias = this.resolveBaseNameFromAlias(baseName);
        for (ASScope currentScope = this; currentScope != null; currentScope = currentScope.getContainingScope())
        {
            // If we're not looking for all matching definitions, 
            // and we've already got some, stop walking. 
            if (!findAll && accumulator.size() != 0)
                break;

            // Search one scope for any definitions matching baseName and naamespaceSet. 
            currentScope.getPropertyForScopeChain(project, accumulator, baseNameForAlias, nsPred, findAll);

            // Keep track of the last scope that was searched. 
            lastSearchedScope = currentScope;
        }

        assert lastSearchedScope != null || accumulator.size() == 0 : "If accumulator is not empty, which searched scope added to it?";

        // Determine whether we need to search the project scope. 
        boolean searchProjectScope = false;

        // If we haven't found any matching definitions yet, 
        // we need to search the project scope. 
        if (accumulator.size() == 0)
            searchProjectScope = true;

        // If we're looking for all matching definitions, 
        // we need to search the project scope. 
        else if (findAll)
            searchProjectScope = true;

        // If the last scope we searched was a package scope or a file scope, 
        // we need to search the project scope because the project scope 
        // might have other definitions with the same name which should 
        // cause an ambiguity. 
        else if (lastSearchedScope instanceof PackageScope ||
                 lastSearchedScope instanceof ASFileScope)
        {
            searchProjectScope = true;
        }

        // Search the project scope if necessary. 
        if (searchProjectScope)
        {
            ASProjectScope projectScope = project.getScope();
            projectScope.getPropertyForScopeChain(this, accumulator, baseNameForAlias, nsPred.getNamespaceSet(), dt);
        }
        if(!baseName.equals(baseNameForAlias)) // has alias
        {
            // remove anything with the same base name that doesn't have an
            // alias, unless its base name is equal to the alias. that is the
            // only time where there will be ambiguity. -JT
            String alias = baseName; //for clarity
            ArrayList<IDefinition> toRemove = new ArrayList<IDefinition>();
            String qualifiedNameForAlias = resolveQualifiedNameFromAlias(alias);
            for(IDefinition definition : accumulator)
            {
                if(!definition.getBaseName().equals(alias)
                        && !definition.getQualifiedName().equals(qualifiedNameForAlias))
                {
                    toRemove.add(definition);
                }
            }
            // some collections can't remove while iterating, so do it after
            // collecting all of the definitions to remove -JT
            accumulator.removeAll(toRemove);
        }
        else // no alias
        {
            // remove anything that has an alias, unless its alias is equal to
            // the original base name.
            ArrayList<IDefinition> toRemove = new ArrayList<IDefinition>();
            for (IDefinition definition : accumulator)
            {
                String otherAlias = resolveAliasFromQualifiedImport(definition.getQualifiedName());
                if (otherAlias != null && !otherAlias.equals(baseName))
                {
                    toRemove.add(definition);
                }
            }
            accumulator.removeAll(toRemove);
        }
    }

    /**
     * For each {@link IProtectedNamespaceDefinition} in the given
     * {@code namespaceSet}, if it does not have a corresponding
     * {@link IStaticProtectedNamespaceDefinition}, create one and add it to the
     * {@code namespaceSet}.
     * 
     * @param namespaceSet Namespace definitions. New items might be added.
     * @return Updated namespace definitions.
     */
    @SuppressWarnings("unused")
    private static Set<INamespaceDefinition> addStaticProtectedNS(Set<INamespaceDefinition> namespaceSet)
    {
        if (namespaceSet == null)
            return null;

        // The keys are URI strings. The values are "protected" namespace definitions.
        final Map<String, INamespaceDefinition.IStaticProtectedNamespaceDefinition> staticProtectedNamespaces =
                new HashMap<String, INamespaceDefinition.IStaticProtectedNamespaceDefinition>();
        final Set<INamespaceDefinition.IProtectedNamespaceDefinition> protectedNamespaces =
                new HashSet<NamespaceDefinition.IProtectedNamespaceDefinition>();
        for (final INamespaceDefinition namespace : namespaceSet)
        {
            if (namespace instanceof INamespaceDefinition.IStaticProtectedNamespaceDefinition)
            {
                final INamespaceDefinition.IStaticProtectedNamespaceDefinition staticProtectedNamespace =
                        (INamespaceDefinition.IStaticProtectedNamespaceDefinition)namespace;
                staticProtectedNamespaces.put(
                        staticProtectedNamespace.getURI(),
                        staticProtectedNamespace);
            }
            else if (namespace instanceof INamespaceDefinition.IProtectedNamespaceDefinition)
            {
                protectedNamespaces.add((INamespaceDefinition.IProtectedNamespaceDefinition)namespace);
            }
        }

        // Find all "protected" namespace definitions that don't have their 
        // corresponding "static protected" namespace definitions.
        final Set<INamespaceDefinition.IStaticProtectedNamespaceDefinition> addedStaticProtectedNamespaces =
                new HashSet<NamespaceDefinition.IStaticProtectedNamespaceDefinition>();
        for (final INamespaceDefinition.IProtectedNamespaceDefinition protectedNamespace : protectedNamespaces)
        {
            if (!staticProtectedNamespaces.containsKey(protectedNamespace.getURI()))
            {
                addedStaticProtectedNamespaces.add(
                        NamespaceDefinition.createStaticProtectedNamespaceDefinition(
                                protectedNamespace.getURI()));
            }
        }

        final Set<INamespaceDefinition> result;
        if (addedStaticProtectedNamespaces.isEmpty())
        {
            result = namespaceSet;
        }
        else
        {
            result = new HashSet<INamespaceDefinition>();
            result.addAll(addedStaticProtectedNamespaces);
            result.addAll(namespaceSet);
        }
        return result;
    }

    /**
     * This is the core findproperty method. This method implements the
     * equivalent of the findprop AVM instruction in Royale.
     * 
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param baseName base name of the property we are looking for.
     * @param namespaceSet Namespace set in which the qualifier of any found
     * definition must found.
     * @param dt The type of dependency that should be added to the dependency
     * graph when resolving this reference across a compilation unit boundary.
     * @param findAll If true, then find all definitons that match the namespace
     * set and base name, not just those from the first scope with a single
     * match.
     * @return One or more {@link IDefinition}'s matched by the namespace set
     * and base name.
     */
    private List<IDefinition> findProperty(CompilerProject project, String baseName, Set<INamespaceDefinition> namespaceSet, DependencyType dt, boolean findAll)
    {
        ArrayList<IDefinition> defs = new ArrayList<IDefinition>(1);
        findProperty(defs, project, baseName, namespaceSet, dt, findAll);
        return defs;
    }

    /**
     * Version of findProperty that determine the results based on the namespace set passed in,
     * along with any additional constraints passed in via the {@link Predicate}.
     *
     *
     * @param project       The {@link CompilerProject} to resolve things in
     * @param baseName      The name to find
     * @param additional    Any additional constraints on the lookup.  This predicate will
     *                      run before any namespace checking occurs.
     * @param namespaceSet  The Namespace set to use for the lookup
     * @param dt            The dependency type to introduce if this resolves to something from
     *                      another compilation unit
     * @return              a List of IDefinition that matched the name, namespace set, and any
     *                      additional constraints specified by the predicate.
     */
    private List<IDefinition> findProperty(CompilerProject project,
                                           String baseName,
                                           Predicate<IDefinition> additional,
                                           Set<INamespaceDefinition> namespaceSet,
                                           DependencyType dt,
                                           boolean findAll)
    {
        ArrayList<IDefinition> defs = new ArrayList<IDefinition>(1);
        NamespaceSetPredicate nsPred = new NamespaceSetPredicate(project, namespaceSet);
        Predicate<IDefinition> pred = Predicates.and(additional, nsPred);
        FilteredCollection<IDefinition> filteredCollection = new FilteredCollection<IDefinition>(pred, defs);
        findProperty(filteredCollection, project, baseName, nsPred, dt, findAll);
        return defs;
    }

    /**
     * Is this scope inside a with scope.
     * 
     * @return true if this scope is nested in a with scope, or this scope is a
     * with scope
     */
    public boolean isInWith()
    {
        return inWith;
    }

    /**
     * Get any containing with scope
     * 
     * @return the ASScope that is the containing with scope, or null if there
     * is no containing with scope
     */
    ASScope getContainingWithScope()
    {
        ASScope scope = this;
        while (scope != null)
        {
            if (scope instanceof WithScope)
                return scope;
            scope = scope.getContainingScope();
        }
        return scope;
    }

    /**
     * IFilter the result of a findDefinition based on any containing with scopes
     * and if the lookup is allowed to escape a with scope This method is used
     * by findProperty, and findPropertyQualified to filter the results. By
     * default, the lookup will look past the with scopes (this is what code
     * model expects), so we will filter the results here, but only if we are in
     * a with scope. With scopes are rare enough that the performance hit
     * shouldn't be too bad, since we only do the filtering when we know we are
     * in a with scope. If we are not in a with scope, or the lookup is allowed
     * to escape the with block, then we immediately return the passed in
     * definition.
     * 
     * @param d the definition the lookup resolved to
     * @param canEscapeWith true if the lookup can esape a with, false if it
     * can't
     * @return the definition to use as the result of the lookup
     */
    IDefinition filterWith(IDefinition d, boolean canEscapeWith)
    {
        if (!inWith || canEscapeWith || d == null)
            return d;

        ASScope withScope = getContainingWithScope();
        if (withScope != null)
        {
            ASScope scope = this;
            while (scope != null)
            {
                // Didn't find the defns containing scope before we hit
                // the with, so act as if we couldn't resolve it.
                if (scope == withScope)
                    return null;
                // We found the declaring scope, and we haven't seen a with
                // scope yet, so we can return the definition
                if (scope == d.getContainingScope())
                    return d;

                scope = scope.getContainingScope();
            }
            return null;
        }
        return d;
    }

    /**
     * The main public entry point for the findprop operation in the compiler.
     * This method uses the {@link ASScopeCache} to improve performance.
     * 
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param baseName base name of the property we are looking for.
     * @param dt The type of dependency that should be added to the dependency
     * graph when resolving this reference across a compilation unit boundary.
     * @return A single {@link IDefinition} to which the specified base name
     * resolves to in this scope, or null. Null is returned when no definition
     * is found <b>and</b> when more than one definition is found.
     */
    public IDefinition findProperty(ICompilerProject project, String baseName, DependencyType dt)
    {
        return findProperty(project, baseName, dt, false);
    }

    /**
     * The main public entry point for the findprop operation in the compiler.
     * This method uses the {@link ASScopeCache} to improve performance.
     * 
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param baseName base name of the property we are looking for.
     * @param dt The type of dependency that should be added to the dependency
     * graph when resolving this reference across a compilation unit boundary.
     * @param canEscapeWith should this lookup find definitions that occur
     * outside of a containing with scope
     * @return A single {@link IDefinition} to which the specified base name
     * resolves to in this scope, or null. Null is returned when no definition
     * is found <b>and</b> when more than one definition is found.
     */
    public IDefinition findProperty(ICompilerProject project, String baseName, DependencyType dt, boolean canEscapeWith)
    {
        if (canDelegateLookupToContainingScope(baseName))
        {
            // If we know that we can't possibly find the property in this scope, just ask the containing scope
            // which may have already computed and cached the result.
            return getContainingScope().findProperty(project, baseName, dt, canEscapeWith);
        }
        assert baseName.indexOf('.') == -1 : "baseName must not be any sort of qname " + baseName;
        CompilerProject compilerProject = (CompilerProject)project;
        ASScopeCache scopeCache = compilerProject.getCacheForScope(this);
        return filterWith(scopeCache.findProperty(baseName, dt, canEscapeWith), canEscapeWith);
    }

    /**
     * An alternate entry point for findprop operations.
     *
     * This method takes an addition Predicate that allows custom filtering of the results, instead
     * of just using the namespace set.  This method will still use the namespace set, but the predicate passed
     * in will be called first to filter the results.
     *
     * @param project       the active project
     * @param baseName      base name of the property we're looking for
     * @param additional    A Predicate that performs custom filtering on the results
     * @param dt            The dependency type that should be added to the dependency graph
     *                      when resolving this reference across a compilation boundary
     * @param canEscapeWith should this lookup find definitions that occur outside of a containing with scope
     * @return              A single {@link IDefinition} to which the specified base name resolves to in this
     *                      scope, given the additional constraints supplied by the additional Predicate.
     */
    public IDefinition findProperty(ICompilerProject project, String baseName, Predicate<IDefinition> additional, DependencyType dt, boolean canEscapeWith)
    {
        Set<INamespaceDefinition> nsSet = getNamespaceSetForName(project, baseName);
        return findProperty(project, baseName, additional, nsSet, dt, canEscapeWith);
    }

    public IDefinition findProperty (ICompilerProject project, String baseName, Predicate<IDefinition> additional, Set<INamespaceDefinition> nsSet, DependencyType dt, boolean canEscapeWith)
    {
        NamespaceSetPredicate nsPred = new NamespaceSetPredicate(project, nsSet);

        List<IDefinition> storage = new ArrayList<IDefinition>();
        Predicate<IDefinition> pred = Predicates.and(additional, nsPred);
        FilteredCollection<IDefinition> defs = new FilteredCollection<IDefinition>(pred, storage);
        findProperty(defs, (CompilerProject)project, baseName, nsPred, dt, false);
        IDefinition def = null;
        def = getSingleResult(project, storage);
        return filterWith(def, canEscapeWith);
    }

    /**
     *  Helper method to narrow a List of results down to one result for the methods
     *  that return only 1 result.
     *  @return null if there are no results,
     *          the first definition if there is 1 result
     *          one of the definitions if there are multiple results, and the ambiguities can be resolved
     *          an {@link AmbiguousDefinition} if there are multiple results and the ambiguities could
     *          not be resolved
     */
    static IDefinition getSingleResult (ICompilerProject project, List<IDefinition> defs)
    {
        IDefinition def;
        switch (defs.size())
        {
            case 0:
                // No definition found!
                def = null;
                break;
            case 1:
                // found single definition!
                def = defs.get(0);
                assert def.isInProject(project);
                break;
            default:
                IDefinition d = AmbiguousDefinition.resolveAmbiguities(project, defs, false);
                if (d != null)
                    def = d;
                else
                    def = AmbiguousDefinition.get();
        }
        return def;
    }

    /**
     * Is it ok to skip this scope, and just ask the containing scope to perform
     * the lookup. This is possible if this scope does not contribute to the set
     * of open namespaces, and if we have no definitions with the simple name we
     * are looking for.
     *
     * @return true if we can just ask the containing scope to perform the
     * lookup
     */
    protected boolean canDelegateLookupToContainingScope(String name)
    {
        return namespaceSetSameAsContainingScopeNamespaceSet()
                && getContainingScope() != null
                && getLocalDefinitionSetByName(name) == null;
    }

    /**
     * The main public entry point for the findprop operation in the compiler
     * with an explicit qualifier namespace. This method uses the
     * {@link ASScopeCache} to improve performance.
     * 
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param qual {@link INamespaceDefinition} which must match the qualifier
     * namespace of the found {@link IDefinition}.
     * @param baseName base name of the property we are looking for.
     * @param dt The type of dependency that should be added to the dependency
     * graph when resolving this reference across a compilation unit boundary.
     * @return A single {@link IDefinition} to which the specified qualifier and
     * base name resolves to in this scope, or null. Null is returned when no
     * definition is found <b>and</b> when more than one definition is found.
     */
    public IDefinition findPropertyQualified(ICompilerProject project, INamespaceDefinition qual, String baseName, DependencyType dt)
    {
        return findPropertyQualified(project, qual, baseName, dt, false);
    }

    /**
     * The main public entry point for the findprop operation in the compiler
     * with an explicit qualifier namespace. This method uses the
     * {@link ASScopeCache} to improve performance.
     *
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param qual {@link INamespaceDefinition} which must match the qualifier
     * namespace of the found {@link IDefinition}.
     * @param baseName base name of the property we are looking for.
     * @param dt The type of dependency that should be added to the dependency
     * graph when resolving this reference across a compilation unit boundary.
     * @return A single {@link IDefinition} to which the specified qualifier and
     * base name resolves to in this scope, or null. Null is returned when no
     * definition is found <b>and</b> when more than one definition is found.
     */
    public IDefinition findPropertyQualified(ICompilerProject project, Predicate<IDefinition> additional,
                                             INamespaceDefinition qual, String baseName, DependencyType dt)
    {
        if( qual == null )
            return null;

        NamespaceSetPredicate nsPred = new NamespaceSetPredicate(project, ImmutableSet.of(qual));
        Predicate<IDefinition> pred = Predicates.and(additional, nsPred);
        List<IDefinition> defs = new ArrayList<IDefinition>();
        FilteredCollection<IDefinition> filteredCollection = new FilteredCollection<IDefinition>(pred, defs);
        findProperty(filteredCollection, (CompilerProject)project, baseName, nsPred, dt, false);
        return getSingleResult(project, defs);
    }

    /**
     * The main public entry point for the findprop operation in the compiler
     * with an explicit qualifier namespace. This method uses the
     * {@link ASScopeCache} to improve performance.
     * 
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param qual The qualifier(s) to use to lookup the property.
     * @param baseName base name of the property we are looking for.
     * @param canEscapeWith should this lookup find definitions that occur
     * outside of a containing with scope
     * @param dt The type of dependency that should be added to the dependency
     * graph when resolving this reference across a compilation unit boundary.
     * @return A single {@link IDefinition} to which the specified qualifier and
     * base name resolves to in this scope, or null. Null is returned when no
     * definition is found <b>and</b> when more than one definition is found.
     */
    public IDefinition findPropertyQualified(ICompilerProject project, INamespaceDefinition qual, String baseName, DependencyType dt, boolean canEscapeWith)
    {
        assert baseName.indexOf('.') == -1 : "baseName must not be any sort of qname " + baseName;

        // Can't find a property if we don't know what its qualifier is
        if( qual == null )
            return null;

        CompilerProject compilerProject = (CompilerProject)project;
        ASScopeCache scopeCache = compilerProject.getCacheForScope(this);

        IDefinition definition = scopeCache.findPropertyQualified(qual, baseName, dt);
        return filterWith(definition, canEscapeWith);
    }

    /**
     * The main public entry point for the findprop operation in the compiler
     * with an explicit set of qualifier namespaces. This method uses the
     * {@link ASScopeCache} to improve performance.
     *
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve namespace references in the "use namespace" set this scope.
     * @param baseName base name of the property we are looking for.
     * @param qual The qualifier(s) to use to lookup the property.
     * @param canEscapeWith should this lookup find definitions that occur
     * outside of a containing with scope
     * @param dt The type of dependency that should be added to the dependency
     * graph when resolving this reference across a compilation unit boundary.
     * @return A single {@link IDefinition} to which the specified qualifier and
     * base name resolves to in this scope, or null. Null is returned when no
     * definition is found <b>and</b> when more than one definition is found.
     */
    public IDefinition findPropertyQualified(ICompilerProject project, IQualifiers qual, String baseName, DependencyType dt, boolean canEscapeWith)
    {
        if( qual == null || qual.getNamespaceCount() == 0 )
            return null ;

        if( qual.getNamespaceCount() == 1 )
        {
            return findPropertyQualified(project, qual.getFirst(), baseName, dt, canEscapeWith);
        }
        else
        {
            List<IDefinition> defs = findProperty((CompilerProject)project, baseName, qual.getNamespaceSet(), dt);
            return filterWith(getSingleResult(project, defs), canEscapeWith);
        }
    }

    /**
     * Helper method to get the namespace set to use for a super reference. This
     * will replace the protected namespace for this class with the protected
     * namespace for the super class in the returned namespace set.
     * 
     * @param project project used to resolve namespaces
     * @param superDef the IDefinition representing the base class
     * @return The correct namespace set to use for a super reference
     */
    public Set<INamespaceDefinition> getNamespaceSetForSuper(ICompilerProject project, IDefinition superDef)
    {
        Set<INamespaceDefinition> nsSet = getNamespaceSet(project);
        return adjustNamespaceSetForSuper(superDef, nsSet);
    }

    /**
     * Adjust the namespace set passed in so it's the right set for a super
     * access. This will replace the protected namespace for this class with the
     * protected namespace for the super class in the returned namespace set.
     * 
     * @param superDef the IDefinition representing the base class
     * @param nsSet the namespace set to adjust
     * @return The correct namespace set to use for a super reference
     */
    public Set<INamespaceDefinition> adjustNamespaceSetForSuper(IDefinition superDef, Set<INamespaceDefinition> nsSet)
    {
        ClassDefinitionBase containingClass = getContainingClass();

        if (superDef instanceof ClassDefinition &&
                nsSet.contains(containingClass.getProtectedNamespaceReference()))
        {
            Set<INamespaceDefinition> adjustedSet = new LinkedHashSet<INamespaceDefinition>();
            adjustedSet.addAll(nsSet);
            adjustedSet.remove(containingClass.getProtectedNamespaceReference());
            adjustedSet.add(((ClassDefinition)superDef).getProtectedNamespaceReference());
            return adjustedSet;
        }
        return nsSet;
    }

    /**
     * Helper method to return the ClassDefinition this scope is inside of, if
     * there is one.
     * 
     * @return the ClassDefinition that contains this scope, or null if this
     * scope is not in a ClassDefinition
     */
    public ClassDefinitionBase getContainingClass()
    {
        ASScope scope = this;
        ScopedDefinitionBase sdb = null;

        while (scope != null && sdb == null)
        {
            // Walk up the scope chain until we find the first scope with a definition.
            // stuff like catch, or with scopes will have no definition associated with them
            sdb = scope.getDefinition();
            scope = scope.getContainingScope();
        }

        if (sdb instanceof ClassDefinitionBase)
            return (ClassDefinitionBase)sdb;
        else if (sdb != null)
            return (ClassDefinitionBase)sdb.getAncestorOfType(ClassDefinitionBase.class);

        return null;

    }

    public ASFileScope getFileScope()
    {
        ASScope scope = this;
        while (!(scope instanceof ASFileScope))
        {
            scope = scope.getContainingScope();
            // instantiated Vectors may not have containing scopes
            if (scope == null)
                break;
        }
        return (ASFileScope)scope;
    }

    /**
     * Get's the {@link IWorkspace} in which this {@link ASScope} lives.
     * 
     * @return The {@link IWorkspace} in which this {@link ASScope} lives.
     */
    public IWorkspace getWorkspace()
    {
        return getFileScope().getWorkspace();
    }

    public String getContainingSourcePath(String qName, ICompilerProject project)
    {
        ASScope containingScope = getContainingScope();
        if (containingScope != null)
            return containingScope.getContainingSourcePath(qName, project);
        return null;
    }

    /**
     * Determine if any of the definitions in this scope are Bindable
     * 
     * @return true, if any non-static definitions in this scope are explicitly marked
     * bindable, false if there are none.
     */
    public boolean hasAnyBindableDefinitions()
    {
        for (IDefinitionSet set : getAllLocalDefinitionSets())
        {
            int n = set.getSize();
            for (int i = 0; i < n; i++)
            {
                IDefinition d = set.getDefinition(i);
                if (d.isBindable() && !d.isStatic())
                    return true;
            }
        }
        return false;
    }

    /**
     * Get's the {@link ScopedDefinitionBase} that contains this scope. This
     * method differs from {@link #getDefinition()} in that this method will
     * walk up the scope chain.
     * 
     * @return The {@link ScopedDefinitionBase} that contains this scope
     */
    public IScopedDefinition getContainingDefinition()
    {
        // sub-classes override this method.
        // This class just returns the definition attached this scope.
        return containingDefinition;
    }

    /**
     * Makes this scope be the containing scope of the specified anonymous
     * function. Anonymous functions do not get added to scopes, but they do
     * need to know which scope they are inside of.
     */
    public void setAsContainingScopeOfAnonymousFunction(FunctionDefinition anonymousFunction)
    {
        anonymousFunction.setContainingScope(this);
    }

    /**
     * Add a dependency to the given builtintype, from the compilation unit which contains this scope
     * @param project           the active project
     * @param builtinType       the builtin type to depend on
     * @param dependencyType    the type of dependency to add
     */
    public void addDependencyOnBuiltinType(ICompilerProject project, IASLanguageConstants.BuiltinType builtinType,
                                            DependencyType dependencyType)
    {
        // Just proxy up to the file scope, since dependencies are from CompilationUnit to CompilationUnit
        if( containingScope != null )
            containingScope.addDependencyOnBuiltinType(project, builtinType, dependencyType);
    }

    /**
     * Implementation of addDependencyOnBuiltinType that will actually add the dependency.
     * This will only be called if there is a cache miss.
     * @param project           the active project
     * @param builtinType       the builtin type to depend on
     * @param dependencyType    type of dependency to add
     */
    void addDependencyOnBuiltinTypeImpl(CompilerProject project, IASLanguageConstants.BuiltinType builtinType,
                                           DependencyType dependencyType)
    {
        IDefinition definition = project.getBuiltinType(builtinType);

        if( definition != null && 
                builtinType != IASLanguageConstants.BuiltinType.ANY_TYPE &&
                builtinType != IASLanguageConstants.BuiltinType.VOID)
        {
            ASProjectScope projectScope = project.getScope();

            ICompilationUnit from = projectScope.getCompilationUnitForScope(this);
            ICompilationUnit to = projectScope.getCompilationUnitForDefinition(definition);

            String qname = definition.getQualifiedName();
            project.addDependency(from, to, dependencyType, qname);
        }
    }
}
