/*
 *
 *  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.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];

    /**
     * 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;

    /**
     * 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);
    }

    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";

        // 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";
        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";

        // 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);
        }
    }
}
