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

import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;

import antlr.Token;

import org.apache.royale.compiler.common.ASModifier;
import org.apache.royale.compiler.common.ISourceLocation;
import org.apache.royale.compiler.common.SourceLocation;
import org.apache.royale.compiler.config.CompilerDiagnosticsConstants;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.filespecs.IFileSpecification;
import org.apache.royale.compiler.internal.common.Counter;
import org.apache.royale.compiler.internal.definitions.DefinitionBase;
import org.apache.royale.compiler.internal.parsing.as.OffsetLookup;
import org.apache.royale.compiler.internal.scopes.ASFileScope;
import org.apache.royale.compiler.internal.scopes.ASScope;
import org.apache.royale.compiler.internal.scopes.TypeScope;
import org.apache.royale.compiler.internal.semantics.PostProcessStep;
import org.apache.royale.compiler.problems.ICompilerProblem;
import org.apache.royale.compiler.scopes.IASScope;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IFileNode;
import org.apache.royale.compiler.tree.as.IImportNode;
import org.apache.royale.compiler.tree.as.IPackageNode;
import org.apache.royale.compiler.tree.as.IScopedNode;
import org.apache.royale.compiler.tree.mxml.IMXMLClassDefinitionNode;
import org.apache.royale.compiler.workspaces.IWorkspace;

/**
 * Base class for ActionScript parse tree nodes
 */
public abstract class NodeBase extends SourceLocation implements IASNode
{
    /**
     * Used in calls to CheapArray functions. It represents the type of objects
     * that appear in fSymbols.
     */
    protected static final IASNode[] emptyNodeArray = new IASNode[0];
    

    /**
     * Combine the attributes from the base class with the attributes specific
     * to this class
     * 
     * @param superAttributes The attributes of the base class.
     * @param myAttributes The attributes of this class.
     * @return attribute value
     */
    public static String[] combineAttributes(String[] superAttributes, String[] myAttributes)
    {
        String[] combinedAttributes = new String[superAttributes.length + myAttributes.length];
        for (int i = 0; i < superAttributes.length; i++)
        {
            combinedAttributes[i] = superAttributes[i];
        }
        for (int i = 0; i < myAttributes.length; i++)
        {
            combinedAttributes[superAttributes.length + i] = myAttributes[i];
        }
        return combinedAttributes;
    }

    /**
     * Constructor.
     */
    public NodeBase()
    {
        super();
        parent = null;
        
        if (Counter.COUNT_NODES)
            countNodes();
    }

    /**
     * Parent node.
     * <p>
     * Methods (even in NodeBase itself) should use getParent() instead of
     * accessing this member directly. getParent() is overridden in FileNode to
     * do something special when the FileNode represents a shared file.
     */
    protected IASNode parent;

    @Override
    public IASNode getParent()
    {
        return parent;
    }

    @Override
    public int getChildCount()
    {
        return 0;
    }

    @Override
    public IASNode getChild(int i)
    {
        return null;
    }

    @Override
    public IFileSpecification getFileSpecification()
    {
        // TODO Make sure this works with include processing!!!
        ASFileScope fileScope = getFileScope();
        IWorkspace w = fileScope.getWorkspace();
    	if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.WORKSPACE) == CompilerDiagnosticsConstants.WORKSPACE)
    		System.out.println("NodeBase waiting for lock in getFileSpecification");
        IFileSpecification fs = w.getFileSpecification(fileScope.getContainingPath());
    	if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.WORKSPACE) == CompilerDiagnosticsConstants.WORKSPACE)
    		System.out.println("NodeBase done with lock in getFileSpecification");
        return fs;
    }

    @Override
    public int getSpanningStart()
    {
        return getStart();
    }

    /**
     * Get the node type as a string. For example, this will return
     * "IdentifierNode" for an IdentifierNode.
     * 
     * @return the node type
     */
    public String getNodeKind()
    {
        return getClass().getSimpleName();
    }

    @Override
    public boolean contains(int offset)
    {
        return getAbsoluteStart() < offset && getAbsoluteEnd() >= offset;
    }

    /**
     * Determine whether the offset "loosely" fits within this node. With normal
     * nodes, this will return true if the offset matches fLocation.fStart or
     * fLocation.fEnd or anything in between. With bogus nodes (which have
     * fStart == fEnd), this will return true if the offset comes after fStart
     * and before any other nodes in the parse tree
     * 
     * @param offset the offset to test
     * @return true if the offset is "loosely" contained within this node
     */
    public boolean looselyContains(int offset)
    {
        if (getAbsoluteStart() == getAbsoluteEnd())
        {
            // This is a bogus placeholder node (generally an identifier that's been inserted to complete an expression).
            // We'll pretend that it extends all the way to the start offset of the next node.  Now to find that next node...
            if (getAbsoluteStart() <= offset)
            {
                NodeBase containingNode = (NodeBase)getParent();
                // Step 1: Find a node that extends beyond the target offset
                while (containingNode != null && containingNode.getAbsoluteEnd() <= getAbsoluteEnd())
                    containingNode = (NodeBase)containingNode.getParent();
                // If no such node exists, we know that there aren't any tokens in the parse
                // tree that end after this bogus token.  So we can go ahead and pretend this node
                // extends all the way out.
                if (containingNode == null)
                    return true;
                // Step 2: Find a node that starts after the target offset
                IASNode succeedingNode = containingNode.getSucceedingNode(getAbsoluteEnd());
                // If no such node exists, we know that there aren't any tokens in the parse
                // tree that start after this bogus token.  So we can go ahead and pretend this
                // node extends all the way out.
                if (succeedingNode == null)
                    return true;
                // Otherwise, pretend this node extends all the way to the next token.
                if (succeedingNode.getAbsoluteStart() >= offset)
                    return true;
            }
        }
        else
        {
            // This is a real token.  See if the test offset fits within (including the boundaries, since we're looking
            // at "loose" containment.
            return getAbsoluteStart() <= offset && getAbsoluteEnd() >= offset;
        }
        return false;
    }

    @Override
    public IASNode getSucceedingNode(int offset)
    {
        // This node ends before the offset is even reached.  This is hopeless.
        if (getAbsoluteEnd() <= offset)
            return null;

        // See if one of our children starts after the offset
        for (int i = 0; i < getChildCount(); i++)
        {
            IASNode child = getChild(i);
            
            if (child.getAbsoluteStart() > offset)
                return child;
            else if (child.getAbsoluteEnd() > offset)
                return child.getSucceedingNode(offset);
        }
        
        return null;
    }

    /**
     * Determine whether this node is transparent. If a node is transparent, it
     * can never be returned from getContainingNode... the offset will be
     * considered part of the parent node instead.
     * 
     * @return true if the node is transparent
     */
    public boolean isTransparent()
    {
        return false;
    }

    @Override
    public IASNode getContainingNode(int offset)
    {
        // This node doesn't even contain the offset.  This is hopeless.
        if (!contains(offset))
        {
            return null;
        }
        IASNode containingNode = this;
        int childCount = getChildCount();
        // See if the offset is contained within one of our children.
        for (int i = 0; i < childCount; i++)
        {
            IASNode child = getChild(i);
            if (child.getAbsoluteStart() <= offset)
            {
                if (child.contains(offset))
                {
                    containingNode = child.getContainingNode(offset);
                    if (child instanceof NodeBase && ((NodeBase)child).canContinueContainmentSearch(containingNode, this, i, true))
                        continue;
                    break;
                }
            }
            else
            {
                if (child instanceof NodeBase && ((NodeBase)child).canContinueContainmentSearch(containingNode, this, i, false))
                    continue;
                // We've passed this offset without finding a child that contains it.  This is
                // the nearest enclosing node.
                break;
            }
        }
        // Make sure we don't return a transparent node
        while (containingNode != null && containingNode instanceof NodeBase && ((NodeBase)containingNode).isTransparent())
        {
            containingNode = containingNode.getParent();
        }
        return containingNode;
    }

    @Override
    public boolean isTerminal()
    {
        return false;
    }

    @Override
    public IScopedNode getContainingScope()
    {
        return (IScopedNode)getAncestorOfType(IScopedNode.class);
    }

    // TODO Can probably eliminate this.
    protected boolean canContinueContainmentSearch(IASNode containingNode, IASNode currentNode, int childOffset, boolean offsetsStillValid)
    {
        return false;
    }

    @Override
    public IASNode getAncestorOfType(Class<? extends IASNode> nodeType)
    {
        IASNode current = getParent();
        while (current != null && !(nodeType.isInstance(current)))
            current = current.getParent();
        if (current != null)
            return current;
        return null;
    }

    @Override
    public String getPackageName()
    {
        // Starting with this node's parent, walk up the parent chain
        // looking for a package node or an MXML class definition node.
        // These two types of nodes understand what their package is.
        IASNode current = getParent();
        while (current != null &&
               !(current instanceof IPackageNode ||
                 current instanceof IMXMLClassDefinitionNode))
        {
            current = current.getParent();
        }

        if (current instanceof IPackageNode)
            return ((IPackageNode)current).getPackageName();
        else if (current instanceof IMXMLClassDefinitionNode)
            return ((IMXMLClassDefinitionNode)current).getPackageName();

        return null;
    }

    /**
     * Set the start offset of the node to fall just after the token. Used
     * during parsing.
     * 
     * @param token start this node after this token
     */
    public void startAfter(Token token)
    {
        if (token instanceof ISourceLocation)
        {
            startAfter((ISourceLocation) token);
        }
    }
    
    /**
     * Set the start offset of the node to fall just after the token. Used
     * during parsing.
     * 
     * @param location start this node after this token
     */
    public final void startAfter(ISourceLocation location)
    {
        final int end = location.getEnd();
        if (end != UNKNOWN)
        {
            setSourcePath(location.getSourcePath());
            setStart(end);
            setLine(location.getEndLine());
            setColumn(location.getEndColumn());
        }
    }

    /**
     * Set the start offset of the node to fall just before the token. Used
     * during parsing.
     * 
     * @param token start this node before this token
     */
    public final void startBefore(Token token)
    {
        if (token instanceof ISourceLocation)
            startBefore((ISourceLocation)token);
    }

    /**
     * Set the start offset of the node to fall just before the token. Used
     * during parsing.
     * 
     * @param location start this node before this token
     */
    public final void startBefore(ISourceLocation location)
    {
        final int start = location.getStart();
        if (start != UNKNOWN)
        {
            setSourcePath(location.getSourcePath());
            setStart(start);
            setLine(location.getLine());
            setColumn(location.getColumn());
        }
    }

    /**
     * Set the end offset of the node to fall just after the token. Used during
     * parsing.
     * 
     * @param token end this node after this token
     */
    public final void endAfter(Token token)
    {
        if (token instanceof ISourceLocation)
            endAfter((ISourceLocation)token);
    }

    /**
     * Set the end offset of the node to fall just after the token. Used during
     * parsing.
     * 
     * @param location end this node after this token
     */
    public final void endAfter(ISourceLocation location)
    {
        final int end = location.getEnd();
        if (end != UNKNOWN)
        {
            setEnd(end);
            setEndLine(location.getEndLine());
            setEndColumn(location.getEndColumn());
        }
    }

    /**
     * Set the end offset of the node to fall just before the token. Used during
     * parsing.
     * 
     * @param token start this node before this token
     */
    public final void endBefore(Token token)
    {
        if (token instanceof ISourceLocation)
            endBefore((ISourceLocation)token);
    }

    /**
     * Set the end offset of the node to fall just before the token. Used during
     * parsing.
     * 
     * @param location start this node before this token
     */
    public final void endBefore(ISourceLocation location)
    {
        final int start = location.getStart();
        if (start != UNKNOWN)
        {
            setEnd(start);
            setEndLine(location.getLine());
            setEndColumn(location.getColumn());
        }
    }

    /**
     * Set the start and end offsets of the node to coincide with the token's
     * offsets. Used during parsing.
     * 
     * @param token the token to take the offsets from
     */
    public final void span(Token token)
    {
        if (token instanceof ISourceLocation)
            span((ISourceLocation)token);
    }

    /**
     * Set the start and end offsets of the node to coincide with the tokens'
     * offsets. Used during parsing.
     * 
     * @param firstToken the token to take the start offset and line number from
     * @param lastToken the token to take the end offset from
     */
    public final void span(Token firstToken, Token lastToken)
    {
        if (firstToken instanceof ISourceLocation && lastToken instanceof ISourceLocation)
            span((ISourceLocation)firstToken, (ISourceLocation)lastToken);
    }

    /**
     * Set the start and end offsets of the node. Used during parsing.
     * 
     * @param start start offset for the node
     * @param end end offset for the node
     * @param line line number for the node
     */
    public final void span(int start, int end, int line, int column)
    {
        setStart(start);
        setEnd(end);
        setLine(line);
        setColumn(column);
    }

    public Collection<ICompilerProblem> runPostProcess(EnumSet<PostProcessStep> set, ASScope containingScope)
    {
        ArrayList<ICompilerProblem> problems = new ArrayList<ICompilerProblem>(10);
        normalize(set.contains(PostProcessStep.CALCULATE_OFFSETS));
        if (set.contains(PostProcessStep.POPULATE_SCOPE) || set.contains(PostProcessStep.RECONNECT_DEFINITIONS))
            analyze(set, containingScope, problems);
        return problems;
    }

    protected void analyze(EnumSet<PostProcessStep> set, ASScope scope, Collection<ICompilerProblem> problems)
    {
        int childrenSize = getChildCount();
        // Populate this scope with definitions found among the children
        for (int i = 0; i < childrenSize; i++)
        {
            IASNode child = getChild(i);
            if (child instanceof NodeBase)
            {
                if (child.getParent() == null)
                    ((NodeBase)child).setParent(this);
                ((NodeBase)child).analyze(set, scope, problems);
            }
        }
    }

    /**
     * Changes the position of two children in our tree. Neither child can be
     * null and both must have the same parent
     * 
     * @param child the child to replace target
     * @param target the child to replace child
     */
    protected void swapChildren(NodeBase child, NodeBase target)
    {
        //no op in this impl
    }

    /**
     * Replaces the child with the given target. The child will be removed from
     * the tree, and its parentage will be updated
     * 
     * @param child the {@link NodeBase} to replace
     * @param target the {@link NodeBase} to replace the replaced
     */
    protected void replaceChild(NodeBase child, NodeBase target)
    {
        //no op
    }

    /**
     * Normalize the tree. Move custom children into the real child list and
     * fill in missing offsets so that offset lookup will work. Used during
     * parsing.
     */
    public void normalize(boolean fillInOffsets)
    {
        // The list of children doesn't change, so the child count should be constant throughout the loop
        int childrenSize = getChildCount();
        // Normalize the regular children
        for (int i = 0; i < childrenSize; i++)
        {
            IASNode child = getChild(i);
            if (child instanceof NodeBase)
            {
                ((NodeBase)child).setParent(this);
                ((NodeBase)child).normalize(fillInOffsets);
            }
        }
        // Add the special children (which get normalized as they're added)
        if (childrenSize == 0)
            setChildren(fillInOffsets);
        // Fill in offsets based on the child nodes
        if (fillInOffsets)
            fillInOffsets();
        // fill in any dangling ends
        //fillEndOffsets();
        // get rid of unused child space
    }

    /**
     * Allow various subclasses to do special kludgy things like identify
     * mx.core.Application.application
     */
    protected void connectedToProjectScope()
    {
        // The list of children doesn't change, so the child count should be constant throughout the loop
        int childrenSize = getChildCount();
        for (int i = 0; i < childrenSize; i++)
        {
            IASNode child = getChild(i);
            if (child instanceof NodeBase)
                ((NodeBase)child).connectedToProjectScope();
        }
    }

    /**
     * If this node has custom children (names, arguments, etc), shove them into
     * the list of children. Used during parsing.
     */
    protected void setChildren(boolean fillInOffsets)
    {
        //nothing in this class
    }

    /**
     * If the start and end offsets haven't been set explicitly, fill them in
     * based on the offsets of the children. Used during parsing. If the end
     * offset is less than any of the kids' offsets, change fLocation.fEnd to
     * encompass kids.
     */
    protected void fillInOffsets()
    {
        int numChildren = getChildCount();
        if (numChildren > 0)
        {
            int start = getAbsoluteStart();
            int end = getAbsoluteEnd();
            if (start == -1)
            {
                for (int i = 0; i < numChildren; i++)
                {
                    IASNode child = getChild(i);
                    int childStart = child.getAbsoluteStart();
                    if (childStart != -1)
                    {
                        if (getSourcePath() == null)
                            setSourcePath(child.getSourcePath());
                        setStart(childStart);
                        setLine(child.getLine());
                        setColumn(child.getColumn());
                        break;
                    }
                }
            }
            for (int i = numChildren - 1; i >= 0; i--)
            {
                IASNode child = getChild(i);
                int childEnd = child.getAbsoluteEnd();
                if (childEnd != -1)
                {
                    if (end < childEnd)
                    {
                        setEnd(childEnd);
                        setEndLine(child.getEndLine());
                        setEndColumn(child.getEndColumn());
                    }
                    break;
                }
            }
        }
    }

    /**
     * Set the parent node. Used during parsing.
     * 
     * @param parent parent node
     */
    public void setParent(NodeBase parent)
    {
        this.parent = parent;
    }

    /**
     * Get the nearest containing scope for this node. Used during type
     * decoration.
     * 
     * @return nearest containing scope for this node
     */
    // TODO Make this more efficient using overrides on BlockNode and FileNode.
    public IScopedNode getScopeNode()
    {
        if (this instanceof IScopedNode && ((IScopedNode)this).getScope() != null)
            return (IScopedNode)this;
        IASNode parent = getParent();
        if (parent != null && parent instanceof NodeBase)
            return ((NodeBase)parent).getScopeNode();
        return null;
    }

    /**
     * Get the path of the file in which this parse tree node resides.
     * <p>
     * The tree builder can set a node's origin source file using
     * {@link #setSourcePath(String)}. If the source path was set, return the
     * source path; Otherwise, use root {@link FileNode}'s path.
     * 
     * @return file path that contains this node
     */
    public String getContainingFilePath()
    {
        String path = getSourcePath();
        if (path != null)
            return path;

        final FileNode fileNode = (FileNode)getAncestorOfType(FileNode.class);
        if (fileNode != null)
            return fileNode.getSourcePath();
        return null;
    }

    /**
     * For debugging only. Displays this node and its children in a form like
     * this:
     * 
     * <pre>
     * FileNode "D:\tests\UIComponent.as" 0:0 0-467464  D:\tests\UIComponent.as
     *   PackageNode "mx.core" 12:1 436-465667 D:\tests\UIComponent.as
     *     FullNameNode "mx.core" 0:0 444-451 null
     *       IdentifierNode "mx" 12:9 444-446 D:\tests\UIComponent.as
     *       IdentifierNode "core" 12:12 447-451 D:\tests\UIComponent.as
     *     ScopedBlockNode 13:1 454-465667 D:\tests\UIComponent.as
     *       ImportNode "flash.accessibility.Accessibility" 14:1 457-497 D:\tests\UIComponent.as
     *       FullNameNode "flash.accessibility.Accessibility" 0:0 464-497 null
     *         FullNameNode "flash.accessibility" 0:0 464-483 null
     *           IdentifierNode "flash" 14:8 464-469 D:\tests\UIComponent.as
     *           IdentifierNode "accessibility" 14:14 470-483 D:\tests\UIComponent.as
     *         IdentifierNode "Accessibility" 14:28 484-497 D:\tests\UIComponent.as
     *       ...
     * </pre>
     * <p>
     * Subclasses may not override this, because we want to maintain regularity
     * for how all nodes display.
     */
    @Override
    public final String toString()
    {
        StringBuilder sb = new StringBuilder();
        buildStringRecursive(sb, 0, false);
        return sb.toString();
    }

    /**
     * For debugging only. Called by {@code toString()}, and recursively by
     * itself, to display this node on one line and each descendant node on
     * subsequent indented lines.
     * 
     * * */
    public void buildStringRecursive(StringBuilder sb, int level, boolean skipSrcPath)
    {
        // Indent two spaces for each nesting level.
        for (int i = 0; i < level; i++)
        {
            sb.append("  ");
        }

        // Build the string that represents this node.
        buildOuterString(sb, skipSrcPath);
      
        sb.append('\n');
        
        //To test scopes in ParserSuite
        if(skipSrcPath && (this instanceof IScopedNode)) {
            for (int i = 0; i < level+1; i++)
                sb.append("  ");
            sb.append("[Scope]");
            sb.append("\n");
            IScopedNode scopedNode = (IScopedNode)this;
            IASScope scope = scopedNode.getScope();
            Collection<IDefinition> definitions = scope.getAllLocalDefinitions();
            for(IDefinition def : definitions) {
                for (int i = 0; i < level+2; i++)
                    sb.append("  ");
                ((DefinitionBase)def).buildString(sb, false);
                sb.append('\n');
            }
        }

        // Recurse over the child nodes.
        int n = getChildCount();
        for (int i = 0; i < n; i++)
        {
            NodeBase child = (NodeBase)getChild(i);
            // The child can be null if we're toString()'ing
            // in the debugger during tree building.
            if (child != null)
                child.buildStringRecursive(sb, level + 1, skipSrcPath);
        }
    }

    /**
     * For debugging only. Called by {@code buildStringRecursive()} to display
     * information for this node only.
     * <p>
     * An example is
     * 
     * <pre>
     * PackageNode "mx.core" 12:1 436-465667 D:\tests\UIComponent.as
     * </pre>.
     * <p>
     * The type of node (PackageNode) is displayed first, followed by
     * node-specific information ("mx.core") followed by location information in
     * the form
     * 
     * <pre>
     * line:column start-end sourcepath
     * </pre>
     * 
     */
    private void buildOuterString(StringBuilder sb, boolean skipSrcPath)
    {
        // First display the type of node, as represented by 
        // the short name of the node class.
        sb.append(getNodeKind());

        sb.append("(").append(getNodeID().name()).append(")");
        
        sb.append(' ');

        // Display optional node-specific information in the middle.
        if (buildInnerString(sb))
            sb.append(' ');

        // The SourceLocation superclass handles producing a string such as
        // "17:5 160-188" C:/test.as".
        if(skipSrcPath) 
            sb.append(getOffsetsString());
        else
            sb.append(super.toString());
    }

    /**
     * For debugging only. This method is called by {@code buildOuterString()}.
     * It is overridden by subclasses to display optional node-specific
     * information in the middle of the string, between the node type and the
     * location information.
     */
    protected boolean buildInnerString(StringBuilder sb)
    {
        return false;
    }
    
    /**
     * For debugging only.
     */
    public String getInnerString()
    {
        StringBuilder sb = new StringBuilder();
        buildInnerString(sb);
        return sb.toString();
    }

    public ASFileScope getFileScope()
    {
        ASScope scope = getASScope();
        assert scope != null;
        while (!(scope instanceof ASFileScope))
        {
            scope = scope.getContainingScope();
            assert scope != null;
        }
        return (ASFileScope)scope;
    }

    /**
     * @return {@link OffsetLookup} object for the current tree or null.
     */
    protected final OffsetLookup tryGetOffsetLookup()
    {
        // Try FileNode.getOffsetLookup()
        final IASNode fileNode = getAncestorOfType(IFileNode.class);
        if (fileNode != null)
            return ((IFileNode)fileNode).getOffsetLookup();
        else
            return null;
    }

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

    /**
     * Get the scope this Node uses for name resolution as an ASScope.
     * 
     * @return the ASScope for this node, or null if there isn't one.
     */
    public ASScope getASScope()
    {
        IScopedNode scopeNode = getContainingScope();
        IASScope scope = scopeNode != null ? scopeNode.getScope() : null;

        // If the ScopedNode had a null scope, keep looking up the tree until we
        // find one with a non-null scope.
        // TODO: Is it a bug that an IScopedNode returns null for it's scope?
        // TODO: this seems like a leftover from block scoping - for example, a
        // TODO: ForLoopNode is an IScopedNode, but it doesn't really have a scope
        while (scope == null && scopeNode != null)
        {
            scopeNode = scopeNode.getContainingScope();
            scope = scopeNode != null ? scopeNode.getScope() : null;
        }

        if (scope instanceof TypeScope)
        {
            TypeScope typeScope = (TypeScope)scope;
            if (this instanceof BaseDefinitionNode)
            {
                if (((BaseDefinitionNode)this).hasModifier(ASModifier.STATIC))
                    scope = typeScope.getStaticScope();
                else
                    scope = typeScope.getInstanceScope();
            }
            else
            {
                // Do we need the class or instance scope?
                BaseDefinitionNode bdn = (BaseDefinitionNode)this.getAncestorOfType(BaseDefinitionNode.class);
                if (bdn instanceof ClassNode)
                {
                    // We must be loose code in a class
                    scope = typeScope.getStaticScope();
                }
                else
                {
                    if (bdn != null && bdn.hasModifier(ASModifier.STATIC)
                            // Namespaces are always static
                            || bdn instanceof NamespaceNode)
                        scope = typeScope.getStaticScope();
                    else
                        scope = typeScope.getInstanceScope();
                }
            }
        }
        ASScope asScope = scope instanceof ASScope ? (ASScope)scope : null;
        return asScope;
    }

    /**
     * Get the node's local start offset.
     */
    @Override
    public int getStart()
    {
        final OffsetLookup offsetLookup = tryGetOffsetLookup();
        if (offsetLookup != null)
        {
            // to handle start offset in an included file
            int absoluteOffset = getAbsoluteStart();
            final String pathBeforeCaret = offsetLookup.getFilename(absoluteOffset - 1);
            // if the offset is the first offset in the included file return without adjustment
            if (pathBeforeCaret != null && pathBeforeCaret.equals(getSourcePath()))
                return offsetLookup.getLocalOffset(absoluteOffset-1)+1;
            
            return offsetLookup.getLocalOffset(absoluteOffset);
        }
        
        return super.getStart();
    }

    /**
     * Get the node's local end offset.
     */
    @Override
    public int getEnd()
    {
        final OffsetLookup offsetLookup = tryGetOffsetLookup();
        return offsetLookup != null ?
                // to handle end offset in an included file
                offsetLookup.getLocalOffset(super.getEnd() - 1) + 1 :
                super.getEnd();
    }

    /**
     * @return The node's absolute start offset.
     */
    @Override
    public int getAbsoluteStart()
    {
        return super.getStart();
    }

    /**
     * @return The node's absolute end offset.
     */
    @Override
    public int getAbsoluteEnd()
    {
        return super.getEnd();
    }
    
    /**
     * Collects the import nodes that are descendants of this node
     * but which are not contained within a scoped node.
     * <p>
     * This is a helper method for {@link IScopedNode#getAllImportNodes}().
     * Since that method walks up the chain of scoped nodes, we don't want
     * to look inside scoped nodes that were already processed.
     * 
     * @param importNodes The collection of import nodes being built.
     */
    public void collectImportNodes(Collection<IImportNode> importNodes)
    {
        int childCount = getChildCount();
        for (int i = 0; i < childCount; ++i)
        {
            IASNode child = getChild(i);
            
            if (child instanceof IImportNode)
                importNodes.add((IImportNode)child);

            else if (!(child instanceof IScopedNode))
                ((NodeBase)child).collectImportNodes(importNodes);
        }
    }

    /**
     * Used only in asserts.
     */
    public boolean verify()
    {
        // Verify the id.
        ASTNodeID id = getNodeID();
        assert id != null &&
               id != ASTNodeID.InvalidNodeID &&
               id != ASTNodeID.UnknownID : "Definition has bad id";

        // TODO: Verify the source location eventually.
        //      assert getSourcePath() != null : "Node has null source path:\n" + toString();
        //      assert getStart() != UNKNOWN : "Node has unknown start:\n" + toString();
        //      assert getEnd() != UNKNOWN : "Node has unknown end:\n" + toString();
        //      assert getLine() != UNKNOWN : "Node has unknown line:\n" + toString();
        //      assert getColumn() != UNKNOWN : "Node has unknown column:\n" + toString();

        // Verify the children.
        int n = getChildCount();
        for (int i = 0; i < n; i++)
        {
            // Any null children?
            NodeBase child = (NodeBase)getChild(i);
            assert child != null : "Node has null child";

            // Does each child have this node as its parent?
            // (Note: Two node classes override getParent() to not return the parent,
            // so exclude these for now.)
            if (!(child instanceof NamespaceIdentifierNode || child instanceof QualifiedNamespaceExpressionNode))
            {
                assert child.getParent() == this : "Child node has bad parent";
            }

            // Recurse on each child.
            child.verify();
        }

        return true;
    }
    
    /**
     * Counts various types of nodes that are created,
     * as well as the total number of nodes.
     */
    private void countNodes()
    {
    	if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.COUNTER) == CompilerDiagnosticsConstants.COUNTER)
    		System.out.println("ASScopeBase incrementing counter for " + getClass().getSimpleName());
        Counter counter = Counter.getInstance();
        counter.incrementCount(getClass().getSimpleName());
        counter.incrementCount("nodes");
    	if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.COUNTER) == CompilerDiagnosticsConstants.COUNTER)
    		System.out.println("ASScopeBase done incrementing counter for " + getClass().getSimpleName());
    }
}
