You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by go...@apache.org on 2013/04/16 05:05:33 UTC

[1/4] Moved MXMLData-related classes into internal package

Updated Branches:
  refs/heads/develop 1c7ddc285 -> bec3ba002


http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLTagData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLTagData.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLTagData.java
deleted file mode 100644
index 72d77c3..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLTagData.java
+++ /dev/null
@@ -1,1130 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.ListIterator;
-import java.util.Map;
-
-import org.apache.flex.compiler.common.ISourceLocation;
-import org.apache.flex.compiler.common.MutablePrefixMap;
-import org.apache.flex.compiler.common.PrefixMap;
-import org.apache.flex.compiler.common.PrefixedXMLName;
-import org.apache.flex.compiler.common.SourceLocation;
-import org.apache.flex.compiler.common.XMLName;
-import org.apache.flex.compiler.filespecs.IFileSpecification;
-import org.apache.flex.compiler.internal.mxml.MXMLDialect;
-import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
-import org.apache.flex.compiler.mxml.IMXMLTextData.TextType;
-import org.apache.flex.compiler.parsing.IMXMLToken;
-import org.apache.flex.compiler.parsing.MXMLTokenTypes;
-import org.apache.flex.compiler.problems.ICompilerProblem;
-import org.apache.flex.compiler.problems.MXMLDuplicateAttributeProblem;
-import org.apache.flex.compiler.problems.SyntaxProblem;
-import org.apache.flex.utils.FastStack;
-
-/**
- * Encapsulation of an open tag, a close tag, or an empty tag in MXML.
- */
-public class MXMLTagData extends MXMLUnitData implements IMXMLTagData
-{
-    private static final IMXMLTagAttributeData[] NO_ATTRIBUTES = new IMXMLTagAttributeData[0];
-
-    /**
-     * Constructor.
-     */
-    public MXMLTagData()
-    {
-        // Although we don't normally rely on the default ctor to make a completely valid object,
-        // in some cases we don't end up calling init, and we end up with a partially construced object.
-        // So let's init enough stuff so that the object is well behaved.
-        this.attributeMap = Collections.emptyMap();
-        this.attributes = NO_ATTRIBUTES;
-    }
-
-    /**
-     * Copy constructor.
-     */
-    protected MXMLTagData(MXMLTagData other)
-    {
-        super(other);
-        this.nameStart = other.nameStart;
-        this.contentEnd = other.contentEnd;
-        this.tagName = other.tagName;
-        this.nameType = other.nameType;
-        this.commentToken = other.commentToken;
-        this.stateStart = other.stateStart;
-        this.stateName = other.stateName;
-        this.attributesStart = other.attributesStart;
-        this.emptyTag = other.emptyTag;
-        this.explicitCloseToken = other.explicitCloseToken;
-        this.attributeMap = other.attributeMap;
-        this.attributes = other.attributes;
-        this.uri = other.uri;
-
-        this.setOffsets(other.getStart(), other.getEnd());
-        this.setLine(other.getLine());
-        this.setColumn(other.getColumn());
-    }
-
-    protected String tagName;
-
-    /**
-     * The URI specified by this tag's prefix.
-     */
-    protected String uri;
-
-    protected String stateName;
-
-    /**
-     * In-order list of MXML attributes
-     */
-    protected IMXMLTagAttributeData[] attributes;
-
-    /**
-     * Map of attribute name to MXML attribute
-     */
-    protected Map<String, IMXMLTagAttributeData> attributeMap;
-
-    /*
-     * offset where the tag name starts Note that we also use the for
-     * offsetContains(), as it is the first "real" character in the tag
-     */
-    protected int nameStart;
-
-    /*
-     * this is the offset of the end of the "stuff inside the punctuation
-     */
-    protected int contentEnd;
-
-    protected int nameType;
-
-    /**
-     * MXML Comment
-     */
-    protected IMXMLToken commentToken;
-
-    protected int stateStart;
-
-    /**
-     * Start of the attribute list (after the tag name + whitespace)
-     */
-    protected int attributesStart;
-
-    /**
-     * Is this an empty tag (ending with "/>")?
-     */
-    protected boolean emptyTag;
-
-    /**
-     * Indicates if we have an explicit close tag
-     */
-    protected boolean explicitCloseToken;
-
-    /*
-     * unlike most MXML units, our "content" bounds are not the same as the
-     * {@link SourceLocation#getStart()} For tags, we don't count the outer
-     * punctuation as "content", although we do count spaces. Example:
-     * 0123456789 <foo /> start ==0 contentStart==1 contentEnd== 6 end == 8
-     */
-    @Override
-    public int getContentStart()
-    {
-        return nameStart;
-    }
-
-    @Override
-    public int getContentEnd()
-    {
-        return contentEnd;
-    }
-
-    @SuppressWarnings("fallthrough")
-    MutablePrefixMap init(IMXMLData mxmlData, MXMLToken nameToken, ListIterator<MXMLToken> tokenIterator, MXMLDialect dialect, IFileSpecification spec, Collection<ICompilerProblem> problems)
-    {
-        setSourcePath(mxmlData.getPath());
-        MutablePrefixMap map = null;
-        emptyTag = false;
-        explicitCloseToken = false;
-
-        // the start offset will by where '<' is. We strip that text off, but need to remember correct offset first
-        int startOffset = nameToken.getStart();
-        if (nameToken.getType() == MXMLTokenTypes.TOKEN_OPEN_TAG_START)
-            nameToken.truncate(1, 0);
-        else if (nameToken.getType() == MXMLTokenTypes.TOKEN_CLOSE_TAG_START)
-            nameToken.truncate(2, 0);
-        else
-        {
-            problems.add(new SyntaxProblem(nameToken));
-            return map;
-        }
-
-        // Deal with name if it is of the form name.state
-        int nameStart = nameToken.getStart();
-        MXMLStateSplitter splitState = new MXMLStateSplitter(nameToken, dialect, problems, spec);
-        tagName = splitState.baseName;
-        if (splitState.stateName != null)
-        {
-            stateName = splitState.stateName;
-            stateStart = nameToken.getStart() + splitState.stateNameOffset;
-        }
-
-        nameType = nameToken.getType();
-
-        int nameEnd = nameStart + tagName.length();
-        int contentEnd = nameEnd;
-        setTagOffsets(startOffset, nameEnd, nameStart, contentEnd);
-        setColumn(nameToken.getColumn());
-        setLine(nameToken.getLine());
-        attributesStart = getNameEnd();
-        ArrayList<IMXMLTagAttributeData> attrs = new ArrayList<IMXMLTagAttributeData>();
-        attributeMap = new LinkedHashMap<String, IMXMLTagAttributeData>(); //preserve order of attrs
-        boolean foundTagEnd = false;
-        boolean putTokenBack = false; // This is a pre-falcon algorithm that helped recover from tag nesting errors
-                                      // I am bringing it back to life
-        while (tokenIterator.hasNext() && !foundTagEnd)
-        {
-            MXMLToken token = tokenIterator.next();
-            MXMLTagAttributeData attribute = null;
-            switch (token.getType())
-            {
-                case MXMLTokenTypes.TOKEN_NAME:
-                    if (nameType == MXMLTokenTypes.TOKEN_CLOSE_TAG_START)
-                    {
-                        problems.add(new SyntaxProblem(token));
-                        //burn forward until the end tag
-                        //TODO do we want to mark each token as an error, or just the first?
-                        while (tokenIterator.hasNext() && !foundTagEnd)
-                        {
-                            token = tokenIterator.next();
-                            switch (token.getType())
-                            {
-                                case MXMLTokenTypes.TOKEN_TAG_END:
-                                case MXMLTokenTypes.TOKEN_EMPTY_TAG_END:
-                                    foundTagEnd = true;
-                                    break;
-                            }
-                        }
-                        break;
-                    }
-                    if (token.getText().startsWith("xmlns"))
-                    {
-                        attribute = new MXMLNamespaceAttributeData(token, tokenIterator, dialect, spec, problems);
-                        if (map == null)
-                            map = new MutablePrefixMap();
-                        map.add(((IMXMLNamespaceAttributeData)attribute).getNamespacePrefix(), ((IMXMLNamespaceAttributeData)attribute).getNamespace());
-                    }
-                    else
-                    {
-                        attribute = new MXMLTagAttributeData(token, tokenIterator, dialect, spec, problems);
-                    }
-                    attribute.setParent(this);
-                    // add the attribute to the attributes list even if it is duplicate
-                    // otherwise code-hinting will not work properly
-                    if (attributeMap.containsKey(token.getText()))
-                    {
-                        MXMLDuplicateAttributeProblem problem = new MXMLDuplicateAttributeProblem(attribute);
-                        problems.add(problem);
-                    }
-                    attrs.add(attribute);
-                    attributeMap.put(token.getText(), attribute);
-
-                    // Now advance the offsets to include the newly parsed attributes
-                    contentEnd = attribute.getAbsoluteEnd();
-                    setTagOffsets(startOffset, contentEnd, nameStart, contentEnd);
-                    break;
-                case MXMLTokenTypes.TOKEN_TAG_END:
-                    foundTagEnd = true;
-                    explicitCloseToken = !token.isImplicit();
-                    break;
-                case MXMLTokenTypes.TOKEN_EMPTY_TAG_END:
-                    emptyTag = true;
-                    explicitCloseToken = !token.isImplicit();
-                    foundTagEnd = true;
-                    break;
-                case MXMLTokenTypes.TOKEN_OPEN_TAG_START:
-                case MXMLTokenTypes.TOKEN_CLOSE_TAG_START:
-                    problems.add(new SyntaxProblem(token));
-                    foundTagEnd = true; // Don't keep going - bail from malformed tag
-                    putTokenBack = true;
-
-                    // if we added 	this.fEmptyTag = true; then we could repair the damage here, 
-                    // but it's better to let the balancer repair it (in case there is a matching close lurking somewhere)
-                    break;
-                default:
-                    problems.add(new SyntaxProblem(token));
-                    break;
-            }
-            if (foundTagEnd)
-            {
-                if (token.isImplicit() && token.getStart() == -1)
-                {
-                    explicitCloseToken = false;
-                    //let's try to end at the start of the next token if one exists
-                    if (tokenIterator.hasNext())
-                    {
-                        MXMLToken next = tokenIterator.next();
-                        if (next != null)
-                        {
-                            // extend the end, but not the content end
-                            setTagOffsets(getAbsoluteStart() == -1 ? next.getStart() : getAbsoluteStart(), getAbsoluteEnd() == -1 ? next.getStart() : getAbsoluteEnd(), nameStart == -1 ? next.getStart() : nameStart, contentEnd == -1 ? next.getStart() : contentEnd);
-                            tokenIterator.previous();
-                        }
-                    }
-                    else
-                    {
-                        // TODO: if we hit this case do we need to call setTagOffset.
-                        // and is getNameEnd() correct in any case?
-                        setOffsets(startOffset, getNameEnd());
-                    }
-                }
-                else
-                {
-                    // A Tag's content extends all the way to the end token,
-                    // so use the token to set content end
-                    contentEnd = token.getStart();
-                    if (!putTokenBack)
-                    {
-                        // if we are terminating on a "real" close tag, then the "end"
-                        // of our tag will be the end of the TOKEN_TAG_END
-                        setTagOffsets(startOffset, token.getEnd(), nameStart, contentEnd);
-                    }
-                    else
-                    {
-                        // ... conversely, if we are terminating on some other kind of token
-                        // and are going to push the token back, we definietly don't
-                        // want to adjust our bounds based on the end of THAT token.
-                        //
-                        // So.. use the token start to set the conent end (above) and the end
-                        setTagOffsets(startOffset, contentEnd, nameStart, contentEnd);
-                        tokenIterator.previous();
-                    }
-                }
-            }
-            else if (getAbsoluteEnd() < token.getEnd())
-            {
-                contentEnd = token.getEnd();
-                setTagOffsets(startOffset, contentEnd, nameStart, contentEnd);
-            }
-        }
-        attributes = attrs.toArray(new MXMLTagAttributeData[0]);
-        return map;
-    }
-
-    /**
-     * For tags, we "contain" an offset if our content contains the offset. This
-     * means that we return false for the outside "<", ">", "</", "/>"
-     */
-    @Override
-    public boolean containsOffset(int offset)
-    {
-        boolean ret = offset >= nameStart && offset <= contentEnd;
-        return ret;
-    }
-
-    private void setTagOffsets(int start, int end, int contentStart, int contentEnd)
-    {
-        assert (start <= contentStart) && ((contentStart <= contentEnd) || contentEnd == -1) && ((contentEnd <= end) || (end == -1));
-        setOffsets(start, end);
-        nameStart = contentStart;
-
-        if (contentEnd != -1)
-            this.contentEnd = contentEnd;
-    }
-
-    public void setCommentToken(IMXMLToken commentToken)
-    {
-        this.commentToken = commentToken;
-    }
-
-    public IMXMLToken getCommentToken()
-    {
-        return commentToken;
-    }
-
-    @Override
-    public void setParentUnitDataIndex(int parentIndex)
-    {
-        //when we fixup tokens, we don't have enough context to determine if we are a root tag.  When we're a root tag, we cannot be
-        //an emty 
-        if (emptyTag && !explicitCloseToken)
-        {
-            if (parentIndex == -1)
-            {
-                emptyTag = false;
-            }
-        }
-        super.setParentUnitDataIndex(parentIndex);
-    }
-
-    /**
-     * Adjust all associated offsets by the adjustment amount
-     * 
-     * @param offsetAdjustment amount to add to offsets
-     */
-    @Override
-    public void adjustOffsets(int offsetAdjustment)
-    {
-        super.adjustOffsets(offsetAdjustment);
-        nameStart += offsetAdjustment;
-        contentEnd += offsetAdjustment;
-        if (stateName != null)
-        {
-            stateStart += offsetAdjustment;
-        }
-        attributesStart += offsetAdjustment;
-        for (int i = 0; i < attributes.length; i++)
-        {
-            IMXMLTagAttributeData attribute = attributes[i];
-            ((MXMLTagAttributeData)attribute).adjustOffsets(offsetAdjustment);
-        }
-    }
-
-    @Override
-    public boolean isTag()
-    {
-        return true;
-    }
-
-    @Override
-    public boolean isEmptyTag()
-    {
-        return emptyTag;
-    }
-
-    /**
-     * accessor for repair. This lets the balancer mark a tag as empty.
-     */
-    public void setEmptyTag()
-    {
-        emptyTag = true;
-    }
-
-    /**
-     * True if this MXMLTagData object has an actual close token, and was not
-     * closed as a post-process step of MXML repair
-     * 
-     * @return if we have an explicit close tag
-     */
-    public boolean hasExplicitCloseTag()
-    {
-        return explicitCloseToken;
-    }
-
-    /**
-     * Returns true if this tag is the root tag of the containing MXML document
-     * 
-     * @return true if we are the root tag
-     */
-    public boolean isDocumentRoot()
-    {
-        if (isOpenTag())
-        {
-            if (getParentUnitDataIndex() == -1)
-            {
-                int index = getIndex();
-                if (index == 0)
-                    return true;
-                //if we are not zero, scan backwards to see if there is a tag before us
-                index--;
-                while (index >= 0)
-                {
-                    IMXMLUnitData unit = getParent().getUnit(index);
-                    if (unit == null || unit.isTag())
-                        return false;
-                    index--;
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Is this MXML unit an open tag? (i.e. &lt;foo&gt; OR &lt;foo/&gt;, note
-     * that the latter is also an empty tag)
-     * 
-     * @return true if the unit is an open tag
-     */
-    @Override
-    public boolean isOpenTag()
-    {
-        return nameType == MXMLTokenTypes.TOKEN_OPEN_TAG_START;
-    }
-
-    @Override
-    public boolean isOpenAndNotEmptyTag()
-    {
-        return (isOpenTag() && !isEmptyTag());
-    }
-
-    @Override
-    public boolean isCloseTag()
-    {
-        return nameType == MXMLTokenTypes.TOKEN_CLOSE_TAG_START;
-    }
-
-    @Override
-    public String getName()
-    {
-        return tagName;
-    }
-
-    /**
-     * Get the tag name as an {@link PrefixedXMLName}
-     * 
-     * @return the tag name as an {@link PrefixedXMLName}
-     */
-    public PrefixedXMLName getPrefixedXMLName()
-    {
-        return new PrefixedXMLName(getName(), getURI());
-    }
-
-    @Override
-    public XMLName getXMLName()
-    {
-        return new XMLName(getURI(), getShortName());
-    }
-
-    @Override
-    public PrefixMap getPrefixMap()
-    {
-        return getParent().getPrefixMapForData(this);
-    }
-
-    @Override
-    public PrefixMap getCompositePrefixMap()
-    {
-        MutablePrefixMap compMap = new MutablePrefixMap();
-        IMXMLTagData lookingAt = this;
-        while (lookingAt != null)
-        {
-            PrefixMap depth = getParent().getPrefixMapForData(lookingAt);
-            if (depth != null)
-            {
-                compMap.addAll(depth, true);
-            }
-            lookingAt = lookingAt.getParentTag();
-        }
-        return compMap;
-    }
-
-    @Override
-    public String getPrefix()
-    {
-        String name = getName();
-        int i = name.indexOf(':');
-        return i != -1 ? name.substring(0, i) : "";
-    }
-
-    @Override
-    public String getShortName()
-    {
-        String name = getName();
-        int i = name.indexOf(':');
-        return i != -1 ? name.substring(i + 1) : name;
-    }
-
-    @Override
-    public String getURI()
-    {
-        if (uri == null)
-        {
-            //walk up our chain to find the correct uri for our namespace.  first one wins
-            String prefix = getPrefix();
-            IMXMLTagData lookingAt = this;
-            while (lookingAt != null)
-            {
-                PrefixMap depth = getParent().getPrefixMapForData(lookingAt);
-                if (depth != null && depth.containsPrefix(prefix))
-                {
-                    uri = depth.getNamespaceForPrefix(prefix);
-                    break;
-                }
-                lookingAt = lookingAt.getParentTag();
-            }
-        }
-        return uri;
-    }
-
-    public void invalidateURI()
-    {
-        uri = null;
-        int length = attributes.length;
-        for (int i = 0; i < length; i++)
-        {
-            ((MXMLTagAttributeData)attributes[i]).invalidateURI();
-        }
-    }
-
-    @Override
-    public String getStateName()
-    {
-        return stateName != null ? stateName : "";
-    }
-
-    /**
-     * Find out if this tag contains the specified attribute.
-     * 
-     * @param attributeName name of the attribute
-     * @return true if the attribute is present
-     */
-    public boolean hasAttribute(String attributeName)
-    {
-        return attributeMap.containsKey(attributeName);
-    }
-
-    public boolean hasState()
-    {
-        return stateName != null;
-    }
-
-    public int getStateStart()
-    {
-        return stateStart;
-    }
-
-    public int getStateEnd()
-    {
-        return stateName != null ? stateName.length() + stateStart : 0;
-    }
-
-    @Override
-    public String getRawAttributeValue(String attributeName)
-    {
-        IMXMLTagAttributeData attributeData = attributeMap.get(attributeName);
-        if (attributeData != null)
-            return attributeData.getRawValue();
-        return null;
-    }
-
-    @Override
-    public IMXMLTagAttributeData getTagAttributeData(String attributeName)
-    {
-        return attributeMap.get(attributeName);
-    }
-
-    /**
-     * Get the start position of the tag name
-     * 
-     * @return the start position of the tag name
-     */
-    public int getNameStart()
-    {
-        return nameStart;
-    }
-
-    /**
-     * Get the end position of the tag name
-     * 
-     * @return the end position of the tag name
-     */
-    public int getNameEnd()
-    {
-        return nameStart + tagName.length();
-    }
-
-    /**
-     * Get the start position of the state name
-     * 
-     * @return the start position of the tag name
-     */
-    public int getStateNameStart()
-    {
-        return stateName != null ? stateStart : -1;
-    }
-
-    /**
-     * Get the end position of the state name
-     * 
-     * @return the end position of the tag name
-     */
-    public int getStateNameEnd()
-    {
-        return getStateEnd();
-    }
-
-    /**
-     * Get the start position of the attribute list (after the first whitespace
-     * after the tag name).
-     * 
-     * @return the start position of the attribute list
-     */
-    public int getAttributesStart()
-    {
-        return attributesStart;
-    }
-
-    /**
-     * Get the end position of the attribute list (before the ">" or "/>" or the
-     * start of the next tag).
-     * 
-     * @return the end position of the attribute list
-     */
-    public int getAttributesEnd()
-    {
-        return getAbsoluteEnd(); //attr end is just the end of this tag unit
-    }
-
-    @Override
-    public boolean isOffsetInAttributeList(int offset)
-    {
-        return MXMLData.contains(attributesStart, getAbsoluteEnd(), offset);
-    }
-
-    public boolean isInsideStateName(int offset)
-    {
-        if (stateName != null)
-            return MXMLData.contains(getStateStart(), getStateEnd(), offset);
-        return false;
-    }
-
-    /**
-     * Does the offset fall inside this tag's contents?
-     * 
-     * @param offset test offset
-     * @return true iff the offset falls inside this tag's contents
-     */
-    public boolean isOffsetInsideContents(int offset)
-    {
-        return MXMLData.contains(getContentStart(), getContentEnd(), // was getContentsEnd (plural)
-                offset);
-    }
-
-    /**
-     * Get all of the attribute names in this tag
-     * 
-     * @return all of the attribute names (as a String [])
-     */
-    public String[] getAttributeNames()
-    {
-        String[] attributeNames = new String[attributes.length];
-        for (int i = 0; i < attributeNames.length; i++)
-        {
-            attributeNames[i] = attributes[i].getName();
-        }
-        return attributeNames;
-    }
-
-    @Override
-    public IMXMLTagAttributeData[] getAttributeDatas()
-    {
-        return attributes;
-    }
-
-    /**
-     * Find the attribute that contains the offset
-     * 
-     * @param offset test offset
-     * @return the attribute (or null, if no attribute contains the offset)
-     */
-    public IMXMLTagAttributeData findAttributeContainingOffset(int offset)
-    {
-        // Find the last attribute that starts to the left of offset
-        IMXMLTagAttributeData lastAttribute = null;
-        IMXMLTagAttributeData attribute = null;
-        for (int i = 0; i < attributes.length; i++)
-        {
-            attribute = attributes[i];
-            if (attribute.getAbsoluteStart() < offset)
-                lastAttribute = attribute;
-            else
-                break;
-        }
-        // That last attribute is good if it's unfinished or if it contains the offset in question
-        if (lastAttribute != null && (lastAttribute.getAbsoluteEnd() == -1 || lastAttribute.getAbsoluteEnd() >= offset))
-            return lastAttribute;
-        return null;
-    }
-
-    /**
-     * Collect the text contents of this tag (like <mx:Script> or <mx:Style>)
-     * 
-     * @return the text contents of this tag
-     */
-    public int[] getTextContentOffsets()
-    {
-        int startOffset = -1;
-        int endOffset = -1;
-        if (!isEmptyTag() && isOpenTag())
-        {
-            IMXMLUnitData[] list = getParent().getUnits();
-            int index = getIndex() + 1;
-            for (int i = index; i < list.length; i++)
-            {
-                IMXMLUnitData next = list[i];
-                if (next instanceof IMXMLTextData && ((IMXMLTextData)next).getTextType() == TextType.WHITESPACE)
-                    continue;
-                if (next.isText())
-                {
-                    startOffset = startOffset == -1 ? next.getAbsoluteStart() : startOffset;
-                    endOffset = next.getAbsoluteEnd();
-                }
-                else
-                {
-                    if (startOffset == -1 && endOffset == -1)
-                    {
-                        startOffset = getAbsoluteEnd();
-                        endOffset = next.getAbsoluteStart();
-                    }
-                    break;
-                }
-            }
-        }
-        return new int[] {startOffset, endOffset};
-    }
-
-    @Override
-    public String getCompilableText()
-    {
-        StringBuilder sb = new StringBuilder();
-
-        for (IMXMLUnitData unit = getFirstChildUnit(); unit != null; unit = unit.getNextSiblingUnit())
-        {
-            if (unit.isText())
-                sb.append(((IMXMLTextData)unit).getCompilableText());
-        }
-
-        return sb.toString();
-    }
-
-    @Override
-    public IMXMLTagData findMatchingEndTag()
-    {
-        return findMatchingEndTag(false);
-    }
-
-    /**
-     * Finds the close tag that matches this tag.
-     * <p>
-     * Returns null if this tag is a close or empty tag.
-     * <p>
-     * Returns null if a surrounding tag is unbalanced ONLY if includeImplicit
-     * is false; this is determined by backing up to the innermost parent tag
-     * with a different tag.
-     * <p>
-     * {@code <a> <b> <b> <-- find matching for this one will return null
-     * </b> </a> * }
-     */
-    public IMXMLTagData findMatchingEndTag(boolean includeImplicit)
-    {
-        if (isCloseTag() || isEmptyTag())
-            return null;
-        // Back up to the first surrounding tag that has a different name, and ensure
-        // that *it* is balanced, saving our expected return value along the way.
-        IMXMLTagData startTag = this;
-        while (true)
-        {
-            IMXMLTagData parentTag = startTag.getContainingTag(startTag.getAbsoluteStart());
-            if (parentTag == null)
-                break;
-            startTag = parentTag;
-            if (!parentTag.getName().equals(this.getName()))
-            {
-                break;
-            }
-        }
-        // Now walk through the tags starting at startTag.  Once we pop ourselves
-        // off the tagStack, we've found our candidate result -- but keep going
-        // until the stack is null, to ensure that we're balanced out to the
-        // surrounding tag.
-        IMXMLUnitData[] list = getParent().getUnits();
-        FastStack<IMXMLTagData> tagStack = new FastStack<IMXMLTagData>();
-        IMXMLTagData result = null;
-        for (int i = startTag.getIndex(); i < list.length; i++)
-        {
-            IMXMLUnitData curUnit = list[i];
-            if (curUnit.isTag())
-            {
-                IMXMLTagData curTag = (IMXMLTagData)curUnit;
-                if (curTag.isEmptyTag())
-                {
-                    // do nothing for empty tags.
-                }
-                else if (curTag.isOpenTag())
-                {
-                    tagStack.push(curTag);
-                }
-                else if (curTag.isCloseTag())
-                {
-                    if (tagStack.isEmpty())
-                    {
-                        // document is unbalanced.
-                        return null;
-                    }
-                    IMXMLTagData pop = tagStack.pop();
-
-                    //check the short name in case the namespace is not spelled properly
-                    if (!pop.getName().equals(curTag.getName()) && !pop.getShortName().equals(curTag.getShortName()))
-                    {
-                        // document is unbalanced.
-                        return null;
-                    }
-                    if (pop == this)
-                    {
-                        // This is our result -- remember it.
-                        result = curTag;
-                    }
-                    if (tagStack.isEmpty())
-                    {
-                        if (result.isImplicit() && !includeImplicit)
-                            return null;
-                        return result;
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public boolean isImplicit()
-    {
-        return false;
-    }
-
-    /**
-     * determines if the current tag has an end tag. Will return true if this
-     * tag is a close tag or an end tag. If the document is not balanced, we
-     * will return false. If the end tag was implicit, we will return false
-     * 
-     * @return true if this tag has an end tag
-     */
-    public boolean hasEndTag()
-    {
-        if (isCloseTag() || isEmptyTag())
-            return explicitCloseToken;
-        IMXMLTagData tagData = findMatchingEndTag();
-        return tagData != null && !tagData.isImplicit();
-    }
-
-    @Override
-    public IMXMLUnitData getFirstChildUnit()
-    {
-        // If this tag is <foo/> then it has no child units.
-        if (!isOpenAndNotEmptyTag())
-            return null;
-
-        IMXMLUnitData next = getNext();
-
-        // If this tag is followed immediately by its end tag,
-        // as in <foo></foo>, then it has no child units.
-        if (next == findMatchingEndTag())
-            return null;
-
-        // Otherwise, the first child unit is the unit after the tag.
-        return next;
-    }
-
-    @Override
-    public IMXMLTagData getFirstChild(boolean includeEmptyTags)
-    {
-        IMXMLTagData nextTag = null;
-        if (isEmptyTag())
-            return null;
-        if (isOpenTag())
-        {
-            nextTag = getNextTag();
-        }
-        else
-        {
-            // This is a close tag.  Start at the corresponding open tag.
-            IMXMLTagData openTag = getContainingTag(getAbsoluteStart());
-            nextTag = openTag.getNextTag();
-        }
-        // Skip any text blocks to find the next actual tag.  If it's an open tag,
-        // that is our first child.  Otherwise it's a close tag, return null.
-        while (true)
-        {
-            if (nextTag == null || nextTag.isCloseTag())
-                return null;
-            if (nextTag.isOpenAndNotEmptyTag() || (nextTag.isEmptyTag() && includeEmptyTags))
-                return nextTag;
-            nextTag = nextTag.getNextTag();
-        }
-    }
-
-    @Override
-    public IMXMLTagData getNextSibling(boolean includeEmptyTags)
-    {
-        IMXMLTagData nextTag = null;
-        // Be sure we're starting at the close tag, then get the next tag.
-        if (isCloseTag() || isEmptyTag())
-        {
-            nextTag = getNextTag();
-        }
-        else
-        {
-            IMXMLTagData endTag = findMatchingEndTag();
-            if (endTag == null)
-                return null;
-            nextTag = endTag.getNextTag();
-        }
-        while (true)
-        {
-            if (nextTag == null || nextTag.isCloseTag())
-                return null;
-            if (nextTag.isOpenAndNotEmptyTag() || (nextTag.isEmptyTag() && includeEmptyTags))
-                return nextTag;
-            nextTag = nextTag.getNextTag();
-        }
-    }
-
-    /**
-     * Get the start tags for all children of this tag.
-     * 
-     * @param includeEmptyTags <code>true</code> if empty tags should be
-     * included.
-     * @return Array of children.
-     */
-    public IMXMLTagData[] getChildren(boolean includeEmptyTags)
-    {
-        ArrayList<IMXMLTagData> children = new ArrayList<IMXMLTagData>();
-        IMXMLTagData child = getFirstChild(includeEmptyTags);
-        while (child != null)
-        {
-            children.add(child);
-            child = child.getNextSibling(includeEmptyTags);
-        }
-        return children.toArray(new IMXMLTagData[0]);
-    }
-
-    /**
-     * Return the parent tag of this tag. If the document is not balanced before
-     * this tag, returns null.
-     */
-    public IMXMLTagData getParentTag()
-    {
-        IMXMLUnitData data = getParentUnitData();
-        if (data instanceof IMXMLTagData)
-            return (IMXMLTagData)data;
-        return null;
-    }
-
-    @Override
-    public ISourceLocation getLocationOfChildUnits()
-    {
-        String sourcePath = getSourcePath();
-        int start = getStart();
-        int end = getEnd();
-        int line = getLine();
-        int column = getColumn();
-
-        boolean foundFirstChild = false;
-
-        for (IMXMLUnitData unit = getFirstChildUnit(); unit != null; unit = unit.getNextSiblingUnit())
-        {
-            if (!foundFirstChild)
-            {
-                sourcePath = unit.getSourcePath();
-                start = unit.getStart();
-                line = unit.getLine();
-                column = unit.getColumn();
-
-                foundFirstChild = true;
-            }
-
-            end = unit.getEnd();
-        }
-
-        return new SourceLocation(sourcePath, start, end, line, column);
-    }
-
-    /**
-     * Verifies that this tag and its attributes have their source location
-     * information set.
-     * <p>
-     * This is used only in asserts.
-     */
-    @Override
-    public boolean verify()
-    {
-        // Verify the source location.
-        super.verify();
-
-        // Verify the attributes.
-        for (IMXMLTagAttributeData attribute : getAttributeDatas())
-        {
-            ((MXMLTagAttributeData)attribute).verify();
-        }
-
-        return true;
-    }
-
-    /**
-     * For debugging only. This format is nice in the Eclipse debugger.
-     */
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append('<');
-        if (isCloseTag())
-            sb.append('/');
-        sb.append(getName());
-        if (isEmptyTag())
-            sb.append('/');
-        sb.append('>');
-
-        sb.append(' ');
-
-        // Display line, column, start, end as "17:5 160-188"
-        sb.append(super.toString());
-
-        // add content range as "(161-187)"
-        sb.append(' ');
-        sb.append('(');
-        sb.append(nameStart);
-        sb.append('-');
-        sb.append(contentEnd);
-        sb.append(')');
-
-        return sb.toString();
-    }
-
-    /**
-     * For debugging only. This format is nice in a text file.
-     */
-    @Override
-    public String toDumpString()
-    {
-        return buildDumpString(false);
-    }
-
-    @Override
-    public String buildDumpString(boolean skipSrcPath)
-    {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append(super.buildDumpString(skipSrcPath));
-
-        sb.append('\t');
-
-        sb.append('|');
-        sb.append(getName());
-        sb.append('|');
-
-        return sb.toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLTextData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLTextData.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLTextData.java
deleted file mode 100644
index 0d15838..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLTextData.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import static org.apache.flex.compiler.constants.IMXMLCoreConstants.*;
-
-import java.util.Collection;
-
-import org.apache.flex.compiler.common.ISourceLocation;
-import org.apache.flex.compiler.internal.mxml.EntityProcessor;
-import org.apache.flex.compiler.internal.mxml.MXMLDialect;
-import org.apache.flex.compiler.internal.parsing.ISourceFragment;
-import org.apache.flex.compiler.internal.parsing.SourceFragment;
-import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
-import org.apache.flex.compiler.parsing.MXMLTokenTypes;
-import org.apache.flex.compiler.problems.ICompilerProblem;
-
-/**
- * Encapsulation of a block of text in MXML
- */
-public class MXMLTextData extends MXMLUnitData implements IMXMLTextData
-{
-    /**
-     * Constructor.
-     */
-    MXMLTextData(MXMLToken textToken)
-    {
-        text = textToken.getText();
-
-        setOffsets(textToken.getStart(), textToken.getEnd());
-        setLine(textToken.getLine());
-        setColumn(textToken.getColumn());
-
-        switch (textToken.getType())
-        {
-            case MXMLTokenTypes.TOKEN_TEXT:
-            {
-                type = TextType.TEXT;
-                break;
-            }
-            case MXMLTokenTypes.TOKEN_WHITESPACE:
-            {
-                type = TextType.WHITESPACE;
-                break;
-            }
-            case MXMLTokenTypes.TOKEN_CDATA:
-            {
-                type = TextType.CDATA;
-                break;
-            }
-            case MXMLTokenTypes.TOKEN_COMMENT:
-            {
-                type = TextType.COMMENT;
-                break;
-            }
-            case MXMLTokenTypes.TOKEN_ASDOC_COMMENT:
-            {
-                type = TextType.ASDOC;
-                break;
-            }
-            default:
-            {
-                type = TextType.OTHER;
-                break;
-            }
-        }
-    }
-
-    /**
-     * The represented text
-     */
-    private String text;
-
-    private TextType type;
-
-    //
-    // Object overrides
-    //
-
-    // For debugging only. This format is nice in the Eclipse debugger.
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder();
-
-        // Display TEXT, WHITESPACE, etc.
-        sb.append(getTextType());
-
-        sb.append(' ');
-
-        // Display the text characters.
-        sb.append('"');
-        sb.append(getEscapedContent());
-        sb.append('"');
-
-        sb.append(' ');
-
-        // Display line, column, start, and end as "17:5 160-188".
-        sb.append(super.toString());
-
-        return sb.toString();
-    }
-
-    //
-    // MXMLUnitData overrides
-    //
-
-    @Override
-    public boolean isText()
-    {
-        return true;
-    }
-
-    // For debugging only.
-    @Override
-    public String getTypeString()
-    {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append(super.getTypeString());
-        sb.append(":");
-        sb.append(getTextType());
-
-        return sb.toString();
-    }
-
-    // For debugging only. This format is nice in a text file.
-    @Override
-    public String toDumpString()
-    {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append(super.toDumpString());
-
-        sb.append('\t');
-
-        sb.append('|');
-        sb.append(getEscapedContent());
-        sb.append('|');
-
-        return sb.toString();
-    }
-
-    //
-    // IMXMLTextData implementations
-    //
-
-    @Override
-    public String getContent()
-    {
-        return text;
-    }
-
-    @Override
-    public TextType getTextType()
-    {
-        return type;
-    }
-
-    //
-    // Other methods
-    //
-
-    // For debugging only.
-    private String getEscapedContent()
-    {
-        String s = getContent();
-
-        s = s.replaceAll("\n", "\\\\n");
-        s = s.replaceAll("\r", "\\\\r");
-        s = s.replaceAll("\t", "\\\\t");
-
-        return s;
-    }
-
-    @Override
-    public String getCompilableText()
-    {
-        switch (type)
-        {
-            case TEXT:
-            case CDATA:
-            case WHITESPACE:
-            {
-                return getContents();
-            }
-
-            case ASDOC:
-            case COMMENT:
-            {
-                return "";
-            }
-        }
-
-        assert false;
-        return null;
-    }
-
-    @Override
-    public int getCompilableTextStart()
-    {
-        return getContentsStart();
-    }
-
-    @Override
-    public int getCompilableTextEnd()
-    {
-        return getContentsEnd();
-    }
-
-    @Override
-    public int getCompilableTextLine()
-    {
-        return getLine();
-    }
-
-    @Override
-    public int getCompilableTextColumn()
-    {
-        return (getContentsStart() - getAbsoluteStart()) + getColumn();
-    }
-
-    /**
-     * Return the text contained within this unit, without any opening or
-     * closing delimiters
-     * 
-     * @return a normalized string
-     */
-    public String getContents()
-    {
-        String tokenString = text;
-
-        switch (type)
-        {
-            case CDATA:
-            {
-                if (tokenString.endsWith(cDataEnd))
-                {
-                    tokenString = tokenString.substring(cDataStart.length(), tokenString.length() - cDataEnd.length());
-                }
-                else
-                {
-                    tokenString = tokenString.substring(cDataStart.length());
-                }
-                return tokenString;
-            }
-            case ASDOC:
-            {
-                if (tokenString.endsWith(asDocEnd))
-                {
-                    tokenString = tokenString.substring(asDocStart.length(), tokenString.length() - asDocEnd.length());
-                }
-                else
-                {
-                    tokenString = tokenString.substring(asDocStart.length());
-                }
-                return tokenString;
-            }
-            case COMMENT:
-            {
-                if (tokenString.endsWith(commentEnd))
-                {
-                    tokenString = tokenString.substring(commentStart.length(), tokenString.length() - commentEnd.length());
-                }
-                else
-                {
-                    tokenString = tokenString.substring(commentStart.length());
-                }
-                return tokenString;
-            }
-            default:
-            {
-                break;
-            }
-        }
-
-        return text;
-    }
-
-    /**
-     * @return The start offset of actual content
-     */
-    public int getContentsStart()
-    {
-        switch (type)
-        {
-            case CDATA:
-                return getAbsoluteStart() + cDataStart.length();
-
-            case ASDOC:
-                return getAbsoluteStart() + asDocStart.length();
-
-            case COMMENT:
-                return getAbsoluteStart() + commentStart.length();
-
-            case OTHER:
-                return getAbsoluteStart();
-        }
-
-        return getAbsoluteStart();
-    }
-
-    /**
-     * @return The end offset of content
-     */
-    public int getContentsEnd()
-    {
-        switch (type)
-        {
-            case CDATA:
-                return text.endsWith(cDataEnd) ? getAbsoluteEnd() - cDataEnd.length() : getAbsoluteEnd();
-
-            case ASDOC:
-                return text.endsWith(asDocEnd) ? getAbsoluteEnd() - asDocEnd.length() : getAbsoluteEnd();
-
-            case COMMENT:
-                return text.endsWith(commentEnd) ? getAbsoluteEnd() - commentEnd.length() : getAbsoluteEnd();
-
-            case OTHER:
-                return getAbsoluteEnd();
-        }
-
-        return getAbsoluteEnd();
-    }
-
-    public int getContentsLine()
-    {
-        return getLine();
-    }
-
-    public int getContentsColumn()
-    {
-        switch (type)
-        {
-            case CDATA:
-                return getColumn() + cDataStart.length();
-
-            case ASDOC:
-                return getColumn() + asDocStart.length();
-
-            case COMMENT:
-                return getColumn() + commentStart.length();
-
-            case OTHER:
-                return getColumn();
-        }
-
-        return getColumn();
-    }
-
-    @Override
-    public ISourceFragment[] getFragments(Collection<ICompilerProblem> problems)
-    {
-        ISourceLocation location = this;
-
-        switch (type)
-        {
-            case TEXT:
-            {
-                // TEXT might contain one or more entities,
-                // in which case we will return multiple fragments.
-                MXMLDialect mxmlDialect = getMXMLDialect();
-                return EntityProcessor.parse(text, location, mxmlDialect, problems);
-            }
-
-            case WHITESPACE:
-            {
-                // WHITESPACE creates only a single fragment.
-                ISourceFragment fragment = new SourceFragment(text, location);
-                return new ISourceFragment[] {fragment};
-            }
-
-            case CDATA:
-            {
-                // CDATA creates only a single fragment.
-                ISourceFragment fragment = new SourceFragment(text, getContents(), getContentsStart(), getContentsLine(), getContentsColumn());
-                return new ISourceFragment[] {fragment};
-            }
-
-            default:
-            {
-                assert false : "Unexpected type of MXMLTextData";
-            }
-        }
-
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLTextValue.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLTextValue.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLTextValue.java
deleted file mode 100644
index cdcf255..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLTextValue.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
-import org.apache.flex.compiler.mxml.IMXMLTextData.TextType;
-
-public class MXMLTextValue extends MXMLTagAttributeValue implements
-        IMXMLTextValue
-{
-    /**
-     * Constructor.
-     */
-    MXMLTextValue(MXMLToken textToken, IMXMLTagAttributeData parent)
-    {
-        super(parent);
-        setStart(textToken.getStart());
-        setEnd(textToken.getEnd());
-        setColumn(textToken.getColumn());
-        setLine(textToken.getLine());
-        text = textToken.getText();
-    }
-
-    private String text;
-
-    //
-    // Object overrides
-    //
-
-    /**
-     * For debugging only. This format is nice in the Eclipse debugger.
-     */
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append("|");
-        sb.append(getContent());
-        sb.append("| ");
-        sb.append(getLine());
-        sb.append(" ");
-        sb.append(getColumn());
-
-        return sb.toString();
-    }
-
-    //
-    // IMXMLTextData implementations
-    //
-
-    @Override
-    public String getContent()
-    {
-        return text;
-    }
-
-    @Override
-    public TextType getTextType()
-    {
-        return TextType.TEXT;
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLUnitData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLUnitData.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLUnitData.java
deleted file mode 100644
index 657be38..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLUnitData.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import org.apache.flex.compiler.common.SourceLocation;
-import org.apache.flex.compiler.filespecs.FileSpecification;
-import org.apache.flex.compiler.filespecs.IFileSpecification;
-import org.apache.flex.compiler.internal.mxml.MXMLDialect;
-import org.apache.flex.utils.FastStack;
-
-/**
- * Encapsulation of an MXML unit: an open/close/empty tag, a chunk of text
- * (perhaps whitespace, CDATA, or a comment), or a processing instruction.
- * <p>
- * An {@link MXMLData} object stores a linear list of MXML units, but it is
- * possible to walk them in a hierarchical way.
- */
-public abstract class MXMLUnitData extends SourceLocation implements
-        IMXMLUnitData
-{
-    /**
-     * Constructor.
-     */
-    public MXMLUnitData()
-    {
-        super();
-
-        parent = null;
-        index = -1;
-    }
-
-    /**
-     * Copy constructor.
-     */
-    public MXMLUnitData(MXMLUnitData other)
-    {
-        this.parent = other.parent;
-        this.index = other.index;
-    }
-
-    /**
-     * The {@link MXMLData} object that owns this unit.
-     */
-    private MXMLData parent;
-
-    /**
-     * This position of this unit in the linear list of units owned by the
-     * {@link MXMLData}.
-     */
-    protected int index;
-
-    /**
-     * The position of this unit's parent unit in the linear list of units owned
-     * by the {@link MXMLData}.
-     */
-    private int parentIndex;
-
-    @Override
-    public int getContentStart()
-    {
-        return getAbsoluteStart();
-    }
-
-    @Override
-    public int getContentEnd()
-    {
-        return getAbsoluteEnd();
-    }
-
-    /**
-     * Set this unit's position relative to its parent. Used in parsing.
-     * 
-     * @param parent MXML file containing the unit
-     * @param index this unit's position in the list
-     */
-    public void setLocation(MXMLData parent, int index)
-    {
-        this.parent = parent;
-        this.index = index;
-        setSourcePath(parent.getPath());
-    }
-
-    /**
-     * Sets the index of this tags hierarchical parent in its parents array of
-     * MXMLUnitData objects
-     * 
-     * @param parentIndex The index of the parent tag.
-     */
-    public void setParentUnitDataIndex(int parentIndex)
-    {
-        this.parentIndex = parentIndex;
-    }
-
-    @Override
-    public final IMXMLUnitData getParentUnitData()
-    {
-        return parent.getUnit(parentIndex);
-    }
-
-    /**
-     * Gets the index of this tags hierarchical parent in its parents array of
-     * MXMLUnitData objects
-     * 
-     * @return the index, or -1
-     */
-    public final int getParentUnitDataIndex()
-    {
-        return parentIndex;
-    }
-
-    /**
-     * Set this unit's start and end offsets. Used in parsing.
-     * 
-     * @param start start offset
-     * @param end end offset
-     */
-    public void setOffsets(int start, int end)
-    {
-        setStart(start);
-        setEnd(end);
-    }
-
-    /**
-     * Adjust all associated offsets by the adjustment amount
-     * 
-     * @param offsetAdjustment amount to add to offsets
-     */
-    public void adjustOffsets(int offsetAdjustment)
-    {
-        setStart(getAbsoluteStart() + offsetAdjustment);
-        setEnd(getAbsoluteEnd() + offsetAdjustment);
-    }
-
-    @Override
-    public final IFileSpecification getSource()
-    {
-        return new FileSpecification(getParent().getPath().toString());
-    }
-
-    @Override
-    public final int getIndex()
-    {
-        return index;
-    }
-
-    @Override
-    public boolean isText()
-    {
-        return false;
-    }
-
-    @Override
-    public boolean isTag()
-    {
-        return false;
-    }
-
-    @Override
-    public boolean isOpenTag()
-    {
-        return false;
-    }
-
-    @Override
-    public boolean isOpenAndNotEmptyTag()
-    {
-        return false;
-    }
-
-    @Override
-    public boolean isCloseTag()
-    {
-        return false;
-    }
-
-    @Override
-    public final IMXMLData getParent()
-    {
-        return parent;
-    }
-
-    @Override
-    public final IMXMLUnitData getPrevious()
-    {
-        return parent.getUnit(index - 1);
-    }
-
-    @Override
-    public final IMXMLUnitData getNext()
-    {
-        return parent.getUnit(index + 1);
-    }
-
-    @Override
-    public final IMXMLUnitData getNextSiblingUnit()
-    {
-        IMXMLUnitData unit = this;
-
-        if (isOpenAndNotEmptyTag())
-            unit = ((IMXMLTagData)unit).findMatchingEndTag();
-
-        if (unit != null)
-        {
-            unit = unit.getNext();
-
-            if (unit != null && (unit.getParentUnitData() != getParentUnitData()))
-                unit = null;
-        }
-        return unit;
-    }
-
-    @Override
-    public final IMXMLTagData getNextTag()
-    {
-        IMXMLUnitData nextUnit = getNext();
-
-        while (true)
-        {
-            if (nextUnit == null)
-                return null;
-
-            if (nextUnit.isTag())
-                return (IMXMLTagData)nextUnit;
-
-            nextUnit = nextUnit.getNext();
-        }
-    }
-
-    @Override
-    public boolean containsOffset(int offset)
-    {
-        return MXMLData.contains(getAbsoluteStart(), getAbsoluteEnd(), offset);
-    }
-
-    @Override
-    public final IMXMLTagData getContainingTag(int offset)
-    {
-        FastStack<String> tagNames = new FastStack<String>();
-        IMXMLUnitData current = getPrevious();
-        IMXMLTagData containingTag = null;
-
-        if (containsOffset(offset) && isCloseTag())
-        {
-            IMXMLTagData tag = (IMXMLTagData)this;
-            tagNames.push(tag.getName());
-        }
-
-        while (current != null && containingTag == null)
-        {
-            if (current.isTag())
-            {
-                IMXMLTagData currentTag = (IMXMLTagData)current;
-
-                if (currentTag.isCloseTag())
-                {
-                    tagNames.push(currentTag.getName());
-                }
-                else if (currentTag.isOpenTag() && !currentTag.isEmptyTag())
-                {
-                    String stackName = "";
-                    while (stackName.compareTo(currentTag.getName()) != 0 && !tagNames.isEmpty())
-                    {
-                        stackName = tagNames.pop();
-                    }
-                    if (stackName.compareTo(currentTag.getName()) != 0)
-                        containingTag = currentTag;
-                }
-            }
-
-            current = current.getPrevious();
-        }
-
-        return containingTag;
-    }
-
-    @Override
-    public MXMLDialect getMXMLDialect()
-    {
-        return getParent().getMXMLDialect();
-    }
-
-    protected String getTypeString()
-    {
-        return getClass().getSimpleName();
-    }
-
-    /**
-     * For debugging only. This format is nice in a text file.
-     */
-    public String toDumpString()
-    {
-        return buildDumpString(false);
-    }
-
-    public String buildDumpString(boolean skipSrcPath)
-    {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append('[');
-        sb.append(getIndex());
-        sb.append(']');
-
-        sb.append('\t');
-        if (!skipSrcPath)
-        {
-            sb.append(getLine() + 1);
-            sb.append('\t');
-            sb.append(getColumn() + 1);
-            sb.append('\t');
-        }
-        sb.append(getAbsoluteStart());
-        sb.append('\t');
-        sb.append(getAbsoluteEnd());
-        sb.append('\t');
-
-        String type = getTypeString();
-        sb.append(type);
-        int n = 32 - type.length();
-        for (int i = 0; i < n; i++)
-            sb.append(' ');
-        sb.append('\t');
-
-        sb.append('^');
-        sb.append('[');
-        sb.append(parentIndex);
-        sb.append(']');
-
-        return sb.toString();
-    }
-
-    /**
-     * Verifies that this unit has its source location information set.
-     * <p>
-     * This is used only in asserts.
-     */
-    public boolean verify()
-    {
-        // Verify the source location.
-        assert getSourcePath() != null : "MXMLUnitData has null source path: " + toString();
-        assert getStart() != UNKNOWN : "MXMLUnitData has unknown start: " + toString();
-        assert getEnd() != UNKNOWN : "MXMLUnitData has unknown end: " + toString();
-        assert getLine() != UNKNOWN : "MXMLUnitData has unknown line: " + toString();
-        assert getColumn() != UNKNOWN : "MXMLUnitData has unknown column: " + toString();
-
-        return true;
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/StateDefinition.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/StateDefinition.java b/compiler/src/org/apache/flex/compiler/mxml/StateDefinition.java
deleted file mode 100644
index c6897b5..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/StateDefinition.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.flex.compiler.scopes.IASScope;
-import org.apache.flex.compiler.tree.mxml.IMXMLStateNode;
-
-/**
- * {@code StateDefinition} represents a state in MXML 2009 or later. States are
- * per-class, so these objects are owned by the {@code ClassDefinitionNodes}
- * that define classes in MXML.
- */
-public class StateDefinition extends StateDefinitionBase implements
-        IStateDefinition
-{
-    private IMXMLStateNode node;
-
-    /**
-     * Constructor.
-     */
-    public StateDefinition(IMXMLStateNode node, IASScope containingScope, String name, int nameStart, int nameEnd)
-    {
-        super(name, node.getClassDefinitionNode().getDefinition(), containingScope, nameStart, nameEnd);
-        this.node = node;
-    }
-
-    /**
-     * A map mapping group names to {@code IStateGroup} objects. This is
-     * effectively the set of groups that include this state, but we use a map
-     * because we're interested in this set both as a set of group names (the
-     * String keys) and a set of group objects (the {@code IStateGroup} values).
-     */
-    private Map<String, IStateGroupDefinition> groupMap;
-
-    @Override
-    public IMXMLStateNode getNode()
-    {
-        return node;
-    }
-
-    @Override
-    public String[] getStateGroups()
-    {
-        return groupMap != null ? groupMap.keySet().toArray(new String[0]) : new String[0];
-    }
-
-    @Override
-    public IStateGroupDefinition[] resolveStateGroups()
-    {
-        return groupMap.values().toArray(new IStateGroupDefinition[0]);
-    }
-
-    @Override
-    public boolean isIncludedInStateGroup(String group)
-    {
-        return groupMap.containsKey(group);
-    }
-
-    /**
-     * Records that this state belongs to a specified group.
-     * 
-     * @param group An {@code IStateGroup} to which this state belongs.
-     */
-    public void addGroup(IStateGroupDefinition group)
-    {
-        if (groupMap == null)
-            groupMap = new HashMap<String, IStateGroupDefinition>(0);
-
-        groupMap.put(group.getBaseName(), group);
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/StateDefinitionBase.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/StateDefinitionBase.java b/compiler/src/org/apache/flex/compiler/mxml/StateDefinitionBase.java
deleted file mode 100644
index 49c675c..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/StateDefinitionBase.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import org.apache.flex.compiler.definitions.IClassDefinition;
-import org.apache.flex.compiler.internal.definitions.DefinitionBase;
-import org.apache.flex.compiler.scopes.IASScope;
-
-/**
- * {@code StateDefinitionBase} is an abstract base class for
- * {@code StateDefinition} and {@code StateGroupDefinition}, which represent
- * states and state groups in MXML 2009 and later.
- */
-public abstract class StateDefinitionBase extends DefinitionBase implements
-        IStateDefinitionBase
-{
-    /**
-     * Constructor.
-     */
-    public StateDefinitionBase(String name, IClassDefinition containingClass, IASScope containingScope, int nameStart, int nameEnd)
-    {
-        super(name);
-        this.containingClass = containingClass;
-        setNameLocation(nameStart, nameEnd);
-        setContainingScope(containingScope);
-    }
-
-    private final IClassDefinition containingClass;
-
-    @Override
-    public boolean isImplicit()
-    {
-        return true; //this node will always be implicit, even though it will have offsets
-    }
-
-    @Override
-    public int compareTo(IStateDefinitionBase other)
-    {
-        return getNameStart() - other.getNameStart();
-    }
-
-    /**
-     * For debugging only.
-     */
-    @Override
-    public String toString()
-    {
-        return getBaseName();
-    }
-
-    @Override
-    public IClassDefinition getContainingClass()
-    {
-        return containingClass;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/StateGroupDefinition.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/StateGroupDefinition.java b/compiler/src/org/apache/flex/compiler/mxml/StateGroupDefinition.java
deleted file mode 100644
index 19fc74f..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/StateGroupDefinition.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.flex.compiler.definitions.IClassDefinition;
-
-/**
- * {@code StateGroupDefinition} represents a state group in an MXML class.
- */
-public class StateGroupDefinition extends StateDefinitionBase implements
-        IStateGroupDefinition
-{
-    /**
-     * Constructor.
-     */
-    public StateGroupDefinition(String name, IClassDefinition containingClass)
-    {
-        super(name, containingClass, containingClass.getContainedScope(), -1, -1);
-
-    }
-
-    /**
-     * A map mapping state names to {@code IStateDefinition} objects. This is
-     * effectively the set of states included in this group, but we use a map
-     * because we're interested in this set both as a set of state names (the
-     * String keys) and a set of state objects (the {@code IStateDefinition}
-     * values).
-     */
-    private Map<String, IStateDefinition> stateMap;
-
-    @Override
-    public String[] getIncludedStates()
-    {
-        return stateMap.keySet().toArray(new String[0]);
-    }
-
-    @Override
-    public IStateDefinition[] resolveIncludedStates()
-    {
-        return stateMap.values().toArray(new IStateDefinition[0]);
-    }
-
-    @Override
-    public boolean isStateIncluded(String state)
-    {
-        return stateMap.containsKey(state);
-    }
-
-    /**
-     * Records that this group includes a specified state.
-     * 
-     * @param state An {@code IStateDefinition} that this group includes.
-     */
-    public void addState(IStateDefinition state)
-    {
-        if (stateMap == null)
-            stateMap = new HashMap<String, IStateDefinition>(0);
-
-        stateMap.put(state.getBaseName(), state);
-    }
-
-}


[3/4] Moved MXMLData-related classes into internal package

Posted by go...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagAttributeValue.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagAttributeValue.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagAttributeValue.java
new file mode 100644
index 0000000..994cf14
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagAttributeValue.java
@@ -0,0 +1,53 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import org.apache.flex.compiler.common.SourceLocation;
+import org.apache.flex.compiler.mxml.IMXMLTagAttributeData;
+import org.apache.flex.compiler.mxml.IMXMLTagAttributeValue;
+
+public abstract class MXMLTagAttributeValue extends SourceLocation implements
+        IMXMLTagAttributeValue
+{
+    /**
+     * Constructor.
+     */
+    public MXMLTagAttributeValue(IMXMLTagAttributeData parent)
+    {
+        this.parent = parent;
+
+        if (parent != null)
+            setSourcePath(parent.getSourcePath());
+    }
+
+    /**
+     * The MXML attribute that contains this unit
+     */
+    private IMXMLTagAttributeData parent;
+
+    //
+    // Other methods
+    //
+
+    public IMXMLTagAttributeData getContainingAttribute()
+    {
+        return parent;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagBlobData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagBlobData.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagBlobData.java
new file mode 100644
index 0000000..78b167d
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagBlobData.java
@@ -0,0 +1,66 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
+import org.apache.flex.compiler.mxml.IMXMLTagBlobData;
+
+/**
+ * An MXML blob is a large chunk of MXML data that was passed over during
+ * tokenization. A blob, for example could be the contents of an fx:Private tag.
+ */
+public class MXMLTagBlobData extends MXMLUnitData implements IMXMLTagBlobData
+{
+    /**
+     * Constructor.
+     * 
+     * @param token
+     */
+    MXMLTagBlobData(MXMLToken token)
+    {
+        String text = token.getText();
+        int length = text.length();
+        int pos = 1;
+        while (pos < length)
+        {
+            if (Character.isWhitespace(text.charAt(pos)))
+                break;
+            pos++;
+        }
+        name = text.substring(1, pos - 1);
+
+        setStart(token.getStart());
+        setEnd(token.getEnd());
+        setLine(token.getLine());
+        setColumn(token.getColumn());
+    }
+
+    private String name;
+
+    //
+    // IMXMLTagBlobData implementations
+    //
+
+    @Override
+    public String getName()
+    {
+        return name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagData.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagData.java
new file mode 100644
index 0000000..b72da1d
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagData.java
@@ -0,0 +1,1135 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.apache.flex.compiler.common.ISourceLocation;
+import org.apache.flex.compiler.common.MutablePrefixMap;
+import org.apache.flex.compiler.common.PrefixMap;
+import org.apache.flex.compiler.common.PrefixedXMLName;
+import org.apache.flex.compiler.common.SourceLocation;
+import org.apache.flex.compiler.common.XMLName;
+import org.apache.flex.compiler.filespecs.IFileSpecification;
+import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
+import org.apache.flex.compiler.mxml.IMXMLData;
+import org.apache.flex.compiler.mxml.IMXMLNamespaceAttributeData;
+import org.apache.flex.compiler.mxml.IMXMLTagAttributeData;
+import org.apache.flex.compiler.mxml.IMXMLTagData;
+import org.apache.flex.compiler.mxml.IMXMLTextData;
+import org.apache.flex.compiler.mxml.IMXMLUnitData;
+import org.apache.flex.compiler.mxml.IMXMLTextData.TextType;
+import org.apache.flex.compiler.parsing.IMXMLToken;
+import org.apache.flex.compiler.parsing.MXMLTokenTypes;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.problems.MXMLDuplicateAttributeProblem;
+import org.apache.flex.compiler.problems.SyntaxProblem;
+import org.apache.flex.utils.FastStack;
+
+/**
+ * Encapsulation of an open tag, a close tag, or an empty tag in MXML.
+ */
+public class MXMLTagData extends MXMLUnitData implements IMXMLTagData
+{
+    private static final IMXMLTagAttributeData[] NO_ATTRIBUTES = new IMXMLTagAttributeData[0];
+
+    /**
+     * Constructor.
+     */
+    public MXMLTagData()
+    {
+        // Although we don't normally rely on the default ctor to make a completely valid object,
+        // in some cases we don't end up calling init, and we end up with a partially construced object.
+        // So let's init enough stuff so that the object is well behaved.
+        this.attributeMap = Collections.emptyMap();
+        this.attributes = NO_ATTRIBUTES;
+    }
+
+    /**
+     * Copy constructor.
+     */
+    protected MXMLTagData(MXMLTagData other)
+    {
+        super(other);
+        this.nameStart = other.nameStart;
+        this.contentEnd = other.contentEnd;
+        this.tagName = other.tagName;
+        this.nameType = other.nameType;
+        this.commentToken = other.commentToken;
+        this.stateStart = other.stateStart;
+        this.stateName = other.stateName;
+        this.attributesStart = other.attributesStart;
+        this.emptyTag = other.emptyTag;
+        this.explicitCloseToken = other.explicitCloseToken;
+        this.attributeMap = other.attributeMap;
+        this.attributes = other.attributes;
+        this.uri = other.uri;
+
+        this.setOffsets(other.getStart(), other.getEnd());
+        this.setLine(other.getLine());
+        this.setColumn(other.getColumn());
+    }
+
+    protected String tagName;
+
+    /**
+     * The URI specified by this tag's prefix.
+     */
+    protected String uri;
+
+    protected String stateName;
+
+    /**
+     * In-order list of MXML attributes
+     */
+    protected IMXMLTagAttributeData[] attributes;
+
+    /**
+     * Map of attribute name to MXML attribute
+     */
+    protected Map<String, IMXMLTagAttributeData> attributeMap;
+
+    /*
+     * offset where the tag name starts Note that we also use the for
+     * offsetContains(), as it is the first "real" character in the tag
+     */
+    protected int nameStart;
+
+    /*
+     * this is the offset of the end of the "stuff inside the punctuation
+     */
+    protected int contentEnd;
+
+    protected int nameType;
+
+    /**
+     * MXML Comment
+     */
+    protected IMXMLToken commentToken;
+
+    protected int stateStart;
+
+    /**
+     * Start of the attribute list (after the tag name + whitespace)
+     */
+    protected int attributesStart;
+
+    /**
+     * Is this an empty tag (ending with "/>")?
+     */
+    protected boolean emptyTag;
+
+    /**
+     * Indicates if we have an explicit close tag
+     */
+    protected boolean explicitCloseToken;
+
+    /*
+     * unlike most MXML units, our "content" bounds are not the same as the
+     * {@link SourceLocation#getStart()} For tags, we don't count the outer
+     * punctuation as "content", although we do count spaces. Example:
+     * 0123456789 <foo /> start ==0 contentStart==1 contentEnd== 6 end == 8
+     */
+    @Override
+    public int getContentStart()
+    {
+        return nameStart;
+    }
+
+    @Override
+    public int getContentEnd()
+    {
+        return contentEnd;
+    }
+
+    @SuppressWarnings("fallthrough")
+    MutablePrefixMap init(IMXMLData mxmlData, MXMLToken nameToken, ListIterator<MXMLToken> tokenIterator, MXMLDialect dialect, IFileSpecification spec, Collection<ICompilerProblem> problems)
+    {
+        setSourcePath(mxmlData.getPath());
+        MutablePrefixMap map = null;
+        emptyTag = false;
+        explicitCloseToken = false;
+
+        // the start offset will by where '<' is. We strip that text off, but need to remember correct offset first
+        int startOffset = nameToken.getStart();
+        if (nameToken.getType() == MXMLTokenTypes.TOKEN_OPEN_TAG_START)
+            nameToken.truncate(1, 0);
+        else if (nameToken.getType() == MXMLTokenTypes.TOKEN_CLOSE_TAG_START)
+            nameToken.truncate(2, 0);
+        else
+        {
+            problems.add(new SyntaxProblem(nameToken));
+            return map;
+        }
+
+        // Deal with name if it is of the form name.state
+        int nameStart = nameToken.getStart();
+        MXMLStateSplitter splitState = new MXMLStateSplitter(nameToken, dialect, problems, spec);
+        tagName = splitState.baseName;
+        if (splitState.stateName != null)
+        {
+            stateName = splitState.stateName;
+            stateStart = nameToken.getStart() + splitState.stateNameOffset;
+        }
+
+        nameType = nameToken.getType();
+
+        int nameEnd = nameStart + tagName.length();
+        int contentEnd = nameEnd;
+        setTagOffsets(startOffset, nameEnd, nameStart, contentEnd);
+        setColumn(nameToken.getColumn());
+        setLine(nameToken.getLine());
+        attributesStart = getNameEnd();
+        ArrayList<IMXMLTagAttributeData> attrs = new ArrayList<IMXMLTagAttributeData>();
+        attributeMap = new LinkedHashMap<String, IMXMLTagAttributeData>(); //preserve order of attrs
+        boolean foundTagEnd = false;
+        boolean putTokenBack = false; // This is a pre-falcon algorithm that helped recover from tag nesting errors
+                                      // I am bringing it back to life
+        while (tokenIterator.hasNext() && !foundTagEnd)
+        {
+            MXMLToken token = tokenIterator.next();
+            MXMLTagAttributeData attribute = null;
+            switch (token.getType())
+            {
+                case MXMLTokenTypes.TOKEN_NAME:
+                    if (nameType == MXMLTokenTypes.TOKEN_CLOSE_TAG_START)
+                    {
+                        problems.add(new SyntaxProblem(token));
+                        //burn forward until the end tag
+                        //TODO do we want to mark each token as an error, or just the first?
+                        while (tokenIterator.hasNext() && !foundTagEnd)
+                        {
+                            token = tokenIterator.next();
+                            switch (token.getType())
+                            {
+                                case MXMLTokenTypes.TOKEN_TAG_END:
+                                case MXMLTokenTypes.TOKEN_EMPTY_TAG_END:
+                                    foundTagEnd = true;
+                                    break;
+                            }
+                        }
+                        break;
+                    }
+                    if (token.getText().startsWith("xmlns"))
+                    {
+                        attribute = new MXMLNamespaceAttributeData(token, tokenIterator, dialect, spec, problems);
+                        if (map == null)
+                            map = new MutablePrefixMap();
+                        map.add(((IMXMLNamespaceAttributeData)attribute).getNamespacePrefix(), ((IMXMLNamespaceAttributeData)attribute).getNamespace());
+                    }
+                    else
+                    {
+                        attribute = new MXMLTagAttributeData(token, tokenIterator, dialect, spec, problems);
+                    }
+                    attribute.setParent(this);
+                    // add the attribute to the attributes list even if it is duplicate
+                    // otherwise code-hinting will not work properly
+                    if (attributeMap.containsKey(token.getText()))
+                    {
+                        MXMLDuplicateAttributeProblem problem = new MXMLDuplicateAttributeProblem(attribute);
+                        problems.add(problem);
+                    }
+                    attrs.add(attribute);
+                    attributeMap.put(token.getText(), attribute);
+
+                    // Now advance the offsets to include the newly parsed attributes
+                    contentEnd = attribute.getAbsoluteEnd();
+                    setTagOffsets(startOffset, contentEnd, nameStart, contentEnd);
+                    break;
+                case MXMLTokenTypes.TOKEN_TAG_END:
+                    foundTagEnd = true;
+                    explicitCloseToken = !token.isImplicit();
+                    break;
+                case MXMLTokenTypes.TOKEN_EMPTY_TAG_END:
+                    emptyTag = true;
+                    explicitCloseToken = !token.isImplicit();
+                    foundTagEnd = true;
+                    break;
+                case MXMLTokenTypes.TOKEN_OPEN_TAG_START:
+                case MXMLTokenTypes.TOKEN_CLOSE_TAG_START:
+                    problems.add(new SyntaxProblem(token));
+                    foundTagEnd = true; // Don't keep going - bail from malformed tag
+                    putTokenBack = true;
+
+                    // if we added 	this.fEmptyTag = true; then we could repair the damage here, 
+                    // but it's better to let the balancer repair it (in case there is a matching close lurking somewhere)
+                    break;
+                default:
+                    problems.add(new SyntaxProblem(token));
+                    break;
+            }
+            if (foundTagEnd)
+            {
+                if (token.isImplicit() && token.getStart() == -1)
+                {
+                    explicitCloseToken = false;
+                    //let's try to end at the start of the next token if one exists
+                    if (tokenIterator.hasNext())
+                    {
+                        MXMLToken next = tokenIterator.next();
+                        if (next != null)
+                        {
+                            // extend the end, but not the content end
+                            setTagOffsets(getAbsoluteStart() == -1 ? next.getStart() : getAbsoluteStart(), getAbsoluteEnd() == -1 ? next.getStart() : getAbsoluteEnd(), nameStart == -1 ? next.getStart() : nameStart, contentEnd == -1 ? next.getStart() : contentEnd);
+                            tokenIterator.previous();
+                        }
+                    }
+                    else
+                    {
+                        // TODO: if we hit this case do we need to call setTagOffset.
+                        // and is getNameEnd() correct in any case?
+                        setOffsets(startOffset, getNameEnd());
+                    }
+                }
+                else
+                {
+                    // A Tag's content extends all the way to the end token,
+                    // so use the token to set content end
+                    contentEnd = token.getStart();
+                    if (!putTokenBack)
+                    {
+                        // if we are terminating on a "real" close tag, then the "end"
+                        // of our tag will be the end of the TOKEN_TAG_END
+                        setTagOffsets(startOffset, token.getEnd(), nameStart, contentEnd);
+                    }
+                    else
+                    {
+                        // ... conversely, if we are terminating on some other kind of token
+                        // and are going to push the token back, we definietly don't
+                        // want to adjust our bounds based on the end of THAT token.
+                        //
+                        // So.. use the token start to set the conent end (above) and the end
+                        setTagOffsets(startOffset, contentEnd, nameStart, contentEnd);
+                        tokenIterator.previous();
+                    }
+                }
+            }
+            else if (getAbsoluteEnd() < token.getEnd())
+            {
+                contentEnd = token.getEnd();
+                setTagOffsets(startOffset, contentEnd, nameStart, contentEnd);
+            }
+        }
+        attributes = attrs.toArray(new MXMLTagAttributeData[0]);
+        return map;
+    }
+
+    /**
+     * For tags, we "contain" an offset if our content contains the offset. This
+     * means that we return false for the outside "<", ">", "</", "/>"
+     */
+    @Override
+    public boolean containsOffset(int offset)
+    {
+        boolean ret = offset >= nameStart && offset <= contentEnd;
+        return ret;
+    }
+
+    private void setTagOffsets(int start, int end, int contentStart, int contentEnd)
+    {
+        assert (start <= contentStart) && ((contentStart <= contentEnd) || contentEnd == -1) && ((contentEnd <= end) || (end == -1));
+        setOffsets(start, end);
+        nameStart = contentStart;
+
+        if (contentEnd != -1)
+            this.contentEnd = contentEnd;
+    }
+
+    public void setCommentToken(IMXMLToken commentToken)
+    {
+        this.commentToken = commentToken;
+    }
+
+    public IMXMLToken getCommentToken()
+    {
+        return commentToken;
+    }
+
+    @Override
+    public void setParentUnitDataIndex(int parentIndex)
+    {
+        //when we fixup tokens, we don't have enough context to determine if we are a root tag.  When we're a root tag, we cannot be
+        //an emty 
+        if (emptyTag && !explicitCloseToken)
+        {
+            if (parentIndex == -1)
+            {
+                emptyTag = false;
+            }
+        }
+        super.setParentUnitDataIndex(parentIndex);
+    }
+
+    /**
+     * Adjust all associated offsets by the adjustment amount
+     * 
+     * @param offsetAdjustment amount to add to offsets
+     */
+    @Override
+    public void adjustOffsets(int offsetAdjustment)
+    {
+        super.adjustOffsets(offsetAdjustment);
+        nameStart += offsetAdjustment;
+        contentEnd += offsetAdjustment;
+        if (stateName != null)
+        {
+            stateStart += offsetAdjustment;
+        }
+        attributesStart += offsetAdjustment;
+        for (int i = 0; i < attributes.length; i++)
+        {
+            IMXMLTagAttributeData attribute = attributes[i];
+            ((MXMLTagAttributeData)attribute).adjustOffsets(offsetAdjustment);
+        }
+    }
+
+    @Override
+    public boolean isTag()
+    {
+        return true;
+    }
+
+    @Override
+    public boolean isEmptyTag()
+    {
+        return emptyTag;
+    }
+
+    /**
+     * accessor for repair. This lets the balancer mark a tag as empty.
+     */
+    public void setEmptyTag()
+    {
+        emptyTag = true;
+    }
+
+    /**
+     * True if this MXMLTagData object has an actual close token, and was not
+     * closed as a post-process step of MXML repair
+     * 
+     * @return if we have an explicit close tag
+     */
+    public boolean hasExplicitCloseTag()
+    {
+        return explicitCloseToken;
+    }
+
+    /**
+     * Returns true if this tag is the root tag of the containing MXML document
+     * 
+     * @return true if we are the root tag
+     */
+    public boolean isDocumentRoot()
+    {
+        if (isOpenTag())
+        {
+            if (getParentUnitDataIndex() == -1)
+            {
+                int index = getIndex();
+                if (index == 0)
+                    return true;
+                //if we are not zero, scan backwards to see if there is a tag before us
+                index--;
+                while (index >= 0)
+                {
+                    IMXMLUnitData unit = getParent().getUnit(index);
+                    if (unit == null || unit.isTag())
+                        return false;
+                    index--;
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Is this MXML unit an open tag? (i.e. &lt;foo&gt; OR &lt;foo/&gt;, note
+     * that the latter is also an empty tag)
+     * 
+     * @return true if the unit is an open tag
+     */
+    @Override
+    public boolean isOpenTag()
+    {
+        return nameType == MXMLTokenTypes.TOKEN_OPEN_TAG_START;
+    }
+
+    @Override
+    public boolean isOpenAndNotEmptyTag()
+    {
+        return (isOpenTag() && !isEmptyTag());
+    }
+
+    @Override
+    public boolean isCloseTag()
+    {
+        return nameType == MXMLTokenTypes.TOKEN_CLOSE_TAG_START;
+    }
+
+    @Override
+    public String getName()
+    {
+        return tagName;
+    }
+
+    /**
+     * Get the tag name as an {@link PrefixedXMLName}
+     * 
+     * @return the tag name as an {@link PrefixedXMLName}
+     */
+    public PrefixedXMLName getPrefixedXMLName()
+    {
+        return new PrefixedXMLName(getName(), getURI());
+    }
+
+    @Override
+    public XMLName getXMLName()
+    {
+        return new XMLName(getURI(), getShortName());
+    }
+
+    @Override
+    public PrefixMap getPrefixMap()
+    {
+        return getParent().getPrefixMapForData(this);
+    }
+
+    @Override
+    public PrefixMap getCompositePrefixMap()
+    {
+        MutablePrefixMap compMap = new MutablePrefixMap();
+        IMXMLTagData lookingAt = this;
+        while (lookingAt != null)
+        {
+            PrefixMap depth = getParent().getPrefixMapForData(lookingAt);
+            if (depth != null)
+            {
+                compMap.addAll(depth, true);
+            }
+            lookingAt = lookingAt.getParentTag();
+        }
+        return compMap;
+    }
+
+    @Override
+    public String getPrefix()
+    {
+        String name = getName();
+        int i = name.indexOf(':');
+        return i != -1 ? name.substring(0, i) : "";
+    }
+
+    @Override
+    public String getShortName()
+    {
+        String name = getName();
+        int i = name.indexOf(':');
+        return i != -1 ? name.substring(i + 1) : name;
+    }
+
+    @Override
+    public String getURI()
+    {
+        if (uri == null)
+        {
+            //walk up our chain to find the correct uri for our namespace.  first one wins
+            String prefix = getPrefix();
+            IMXMLTagData lookingAt = this;
+            while (lookingAt != null)
+            {
+                PrefixMap depth = getParent().getPrefixMapForData(lookingAt);
+                if (depth != null && depth.containsPrefix(prefix))
+                {
+                    uri = depth.getNamespaceForPrefix(prefix);
+                    break;
+                }
+                lookingAt = lookingAt.getParentTag();
+            }
+        }
+        return uri;
+    }
+
+    public void invalidateURI()
+    {
+        uri = null;
+        int length = attributes.length;
+        for (int i = 0; i < length; i++)
+        {
+            ((MXMLTagAttributeData)attributes[i]).invalidateURI();
+        }
+    }
+
+    @Override
+    public String getStateName()
+    {
+        return stateName != null ? stateName : "";
+    }
+
+    /**
+     * Find out if this tag contains the specified attribute.
+     * 
+     * @param attributeName name of the attribute
+     * @return true if the attribute is present
+     */
+    public boolean hasAttribute(String attributeName)
+    {
+        return attributeMap.containsKey(attributeName);
+    }
+
+    public boolean hasState()
+    {
+        return stateName != null;
+    }
+
+    public int getStateStart()
+    {
+        return stateStart;
+    }
+
+    public int getStateEnd()
+    {
+        return stateName != null ? stateName.length() + stateStart : 0;
+    }
+
+    @Override
+    public String getRawAttributeValue(String attributeName)
+    {
+        IMXMLTagAttributeData attributeData = attributeMap.get(attributeName);
+        if (attributeData != null)
+            return attributeData.getRawValue();
+        return null;
+    }
+
+    @Override
+    public IMXMLTagAttributeData getTagAttributeData(String attributeName)
+    {
+        return attributeMap.get(attributeName);
+    }
+
+    /**
+     * Get the start position of the tag name
+     * 
+     * @return the start position of the tag name
+     */
+    public int getNameStart()
+    {
+        return nameStart;
+    }
+
+    /**
+     * Get the end position of the tag name
+     * 
+     * @return the end position of the tag name
+     */
+    public int getNameEnd()
+    {
+        return nameStart + tagName.length();
+    }
+
+    /**
+     * Get the start position of the state name
+     * 
+     * @return the start position of the tag name
+     */
+    public int getStateNameStart()
+    {
+        return stateName != null ? stateStart : -1;
+    }
+
+    /**
+     * Get the end position of the state name
+     * 
+     * @return the end position of the tag name
+     */
+    public int getStateNameEnd()
+    {
+        return getStateEnd();
+    }
+
+    /**
+     * Get the start position of the attribute list (after the first whitespace
+     * after the tag name).
+     * 
+     * @return the start position of the attribute list
+     */
+    public int getAttributesStart()
+    {
+        return attributesStart;
+    }
+
+    /**
+     * Get the end position of the attribute list (before the ">" or "/>" or the
+     * start of the next tag).
+     * 
+     * @return the end position of the attribute list
+     */
+    public int getAttributesEnd()
+    {
+        return getAbsoluteEnd(); //attr end is just the end of this tag unit
+    }
+
+    @Override
+    public boolean isOffsetInAttributeList(int offset)
+    {
+        return MXMLData.contains(attributesStart, getAbsoluteEnd(), offset);
+    }
+
+    public boolean isInsideStateName(int offset)
+    {
+        if (stateName != null)
+            return MXMLData.contains(getStateStart(), getStateEnd(), offset);
+        return false;
+    }
+
+    /**
+     * Does the offset fall inside this tag's contents?
+     * 
+     * @param offset test offset
+     * @return true iff the offset falls inside this tag's contents
+     */
+    public boolean isOffsetInsideContents(int offset)
+    {
+        return MXMLData.contains(getContentStart(), getContentEnd(), // was getContentsEnd (plural)
+                offset);
+    }
+
+    /**
+     * Get all of the attribute names in this tag
+     * 
+     * @return all of the attribute names (as a String [])
+     */
+    public String[] getAttributeNames()
+    {
+        String[] attributeNames = new String[attributes.length];
+        for (int i = 0; i < attributeNames.length; i++)
+        {
+            attributeNames[i] = attributes[i].getName();
+        }
+        return attributeNames;
+    }
+
+    @Override
+    public IMXMLTagAttributeData[] getAttributeDatas()
+    {
+        return attributes;
+    }
+
+    /**
+     * Find the attribute that contains the offset
+     * 
+     * @param offset test offset
+     * @return the attribute (or null, if no attribute contains the offset)
+     */
+    public IMXMLTagAttributeData findAttributeContainingOffset(int offset)
+    {
+        // Find the last attribute that starts to the left of offset
+        IMXMLTagAttributeData lastAttribute = null;
+        IMXMLTagAttributeData attribute = null;
+        for (int i = 0; i < attributes.length; i++)
+        {
+            attribute = attributes[i];
+            if (attribute.getAbsoluteStart() < offset)
+                lastAttribute = attribute;
+            else
+                break;
+        }
+        // That last attribute is good if it's unfinished or if it contains the offset in question
+        if (lastAttribute != null && (lastAttribute.getAbsoluteEnd() == -1 || lastAttribute.getAbsoluteEnd() >= offset))
+            return lastAttribute;
+        return null;
+    }
+
+    /**
+     * Collect the text contents of this tag (like <mx:Script> or <mx:Style>)
+     * 
+     * @return the text contents of this tag
+     */
+    public int[] getTextContentOffsets()
+    {
+        int startOffset = -1;
+        int endOffset = -1;
+        if (!isEmptyTag() && isOpenTag())
+        {
+            IMXMLUnitData[] list = getParent().getUnits();
+            int index = getIndex() + 1;
+            for (int i = index; i < list.length; i++)
+            {
+                IMXMLUnitData next = list[i];
+                if (next instanceof IMXMLTextData && ((IMXMLTextData)next).getTextType() == TextType.WHITESPACE)
+                    continue;
+                if (next.isText())
+                {
+                    startOffset = startOffset == -1 ? next.getAbsoluteStart() : startOffset;
+                    endOffset = next.getAbsoluteEnd();
+                }
+                else
+                {
+                    if (startOffset == -1 && endOffset == -1)
+                    {
+                        startOffset = getAbsoluteEnd();
+                        endOffset = next.getAbsoluteStart();
+                    }
+                    break;
+                }
+            }
+        }
+        return new int[] {startOffset, endOffset};
+    }
+
+    @Override
+    public String getCompilableText()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        for (IMXMLUnitData unit = getFirstChildUnit(); unit != null; unit = unit.getNextSiblingUnit())
+        {
+            if (unit.isText())
+                sb.append(((IMXMLTextData)unit).getCompilableText());
+        }
+
+        return sb.toString();
+    }
+
+    @Override
+    public IMXMLTagData findMatchingEndTag()
+    {
+        return findMatchingEndTag(false);
+    }
+
+    /**
+     * Finds the close tag that matches this tag.
+     * <p>
+     * Returns null if this tag is a close or empty tag.
+     * <p>
+     * Returns null if a surrounding tag is unbalanced ONLY if includeImplicit
+     * is false; this is determined by backing up to the innermost parent tag
+     * with a different tag.
+     * <p>
+     * {@code <a> <b> <b> <-- find matching for this one will return null
+     * </b> </a> * }
+     */
+    public IMXMLTagData findMatchingEndTag(boolean includeImplicit)
+    {
+        if (isCloseTag() || isEmptyTag())
+            return null;
+        // Back up to the first surrounding tag that has a different name, and ensure
+        // that *it* is balanced, saving our expected return value along the way.
+        IMXMLTagData startTag = this;
+        while (true)
+        {
+            IMXMLTagData parentTag = startTag.getContainingTag(startTag.getAbsoluteStart());
+            if (parentTag == null)
+                break;
+            startTag = parentTag;
+            if (!parentTag.getName().equals(this.getName()))
+            {
+                break;
+            }
+        }
+        // Now walk through the tags starting at startTag.  Once we pop ourselves
+        // off the tagStack, we've found our candidate result -- but keep going
+        // until the stack is null, to ensure that we're balanced out to the
+        // surrounding tag.
+        IMXMLUnitData[] list = getParent().getUnits();
+        FastStack<IMXMLTagData> tagStack = new FastStack<IMXMLTagData>();
+        IMXMLTagData result = null;
+        for (int i = startTag.getIndex(); i < list.length; i++)
+        {
+            IMXMLUnitData curUnit = list[i];
+            if (curUnit.isTag())
+            {
+                IMXMLTagData curTag = (IMXMLTagData)curUnit;
+                if (curTag.isEmptyTag())
+                {
+                    // do nothing for empty tags.
+                }
+                else if (curTag.isOpenTag())
+                {
+                    tagStack.push(curTag);
+                }
+                else if (curTag.isCloseTag())
+                {
+                    if (tagStack.isEmpty())
+                    {
+                        // document is unbalanced.
+                        return null;
+                    }
+                    IMXMLTagData pop = tagStack.pop();
+
+                    //check the short name in case the namespace is not spelled properly
+                    if (!pop.getName().equals(curTag.getName()) && !pop.getShortName().equals(curTag.getShortName()))
+                    {
+                        // document is unbalanced.
+                        return null;
+                    }
+                    if (pop == this)
+                    {
+                        // This is our result -- remember it.
+                        result = curTag;
+                    }
+                    if (tagStack.isEmpty())
+                    {
+                        if (result.isImplicit() && !includeImplicit)
+                            return null;
+                        return result;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public boolean isImplicit()
+    {
+        return false;
+    }
+
+    /**
+     * determines if the current tag has an end tag. Will return true if this
+     * tag is a close tag or an end tag. If the document is not balanced, we
+     * will return false. If the end tag was implicit, we will return false
+     * 
+     * @return true if this tag has an end tag
+     */
+    public boolean hasEndTag()
+    {
+        if (isCloseTag() || isEmptyTag())
+            return explicitCloseToken;
+        IMXMLTagData tagData = findMatchingEndTag();
+        return tagData != null && !tagData.isImplicit();
+    }
+
+    @Override
+    public IMXMLUnitData getFirstChildUnit()
+    {
+        // If this tag is <foo/> then it has no child units.
+        if (!isOpenAndNotEmptyTag())
+            return null;
+
+        IMXMLUnitData next = getNext();
+
+        // If this tag is followed immediately by its end tag,
+        // as in <foo></foo>, then it has no child units.
+        if (next == findMatchingEndTag())
+            return null;
+
+        // Otherwise, the first child unit is the unit after the tag.
+        return next;
+    }
+
+    @Override
+    public IMXMLTagData getFirstChild(boolean includeEmptyTags)
+    {
+        IMXMLTagData nextTag = null;
+        if (isEmptyTag())
+            return null;
+        if (isOpenTag())
+        {
+            nextTag = getNextTag();
+        }
+        else
+        {
+            // This is a close tag.  Start at the corresponding open tag.
+            IMXMLTagData openTag = getContainingTag(getAbsoluteStart());
+            nextTag = openTag.getNextTag();
+        }
+        // Skip any text blocks to find the next actual tag.  If it's an open tag,
+        // that is our first child.  Otherwise it's a close tag, return null.
+        while (true)
+        {
+            if (nextTag == null || nextTag.isCloseTag())
+                return null;
+            if (nextTag.isOpenAndNotEmptyTag() || (nextTag.isEmptyTag() && includeEmptyTags))
+                return nextTag;
+            nextTag = nextTag.getNextTag();
+        }
+    }
+
+    @Override
+    public IMXMLTagData getNextSibling(boolean includeEmptyTags)
+    {
+        IMXMLTagData nextTag = null;
+        // Be sure we're starting at the close tag, then get the next tag.
+        if (isCloseTag() || isEmptyTag())
+        {
+            nextTag = getNextTag();
+        }
+        else
+        {
+            IMXMLTagData endTag = findMatchingEndTag();
+            if (endTag == null)
+                return null;
+            nextTag = endTag.getNextTag();
+        }
+        while (true)
+        {
+            if (nextTag == null || nextTag.isCloseTag())
+                return null;
+            if (nextTag.isOpenAndNotEmptyTag() || (nextTag.isEmptyTag() && includeEmptyTags))
+                return nextTag;
+            nextTag = nextTag.getNextTag();
+        }
+    }
+
+    /**
+     * Get the start tags for all children of this tag.
+     * 
+     * @param includeEmptyTags <code>true</code> if empty tags should be
+     * included.
+     * @return Array of children.
+     */
+    public IMXMLTagData[] getChildren(boolean includeEmptyTags)
+    {
+        ArrayList<IMXMLTagData> children = new ArrayList<IMXMLTagData>();
+        IMXMLTagData child = getFirstChild(includeEmptyTags);
+        while (child != null)
+        {
+            children.add(child);
+            child = child.getNextSibling(includeEmptyTags);
+        }
+        return children.toArray(new IMXMLTagData[0]);
+    }
+
+    /**
+     * Return the parent tag of this tag. If the document is not balanced before
+     * this tag, returns null.
+     */
+    public IMXMLTagData getParentTag()
+    {
+        IMXMLUnitData data = getParentUnitData();
+        if (data instanceof IMXMLTagData)
+            return (IMXMLTagData)data;
+        return null;
+    }
+
+    @Override
+    public ISourceLocation getLocationOfChildUnits()
+    {
+        String sourcePath = getSourcePath();
+        int start = getStart();
+        int end = getEnd();
+        int line = getLine();
+        int column = getColumn();
+
+        boolean foundFirstChild = false;
+
+        for (IMXMLUnitData unit = getFirstChildUnit(); unit != null; unit = unit.getNextSiblingUnit())
+        {
+            if (!foundFirstChild)
+            {
+                sourcePath = unit.getSourcePath();
+                start = unit.getStart();
+                line = unit.getLine();
+                column = unit.getColumn();
+
+                foundFirstChild = true;
+            }
+
+            end = unit.getEnd();
+        }
+
+        return new SourceLocation(sourcePath, start, end, line, column);
+    }
+
+    /**
+     * Verifies that this tag and its attributes have their source location
+     * information set.
+     * <p>
+     * This is used only in asserts.
+     */
+    @Override
+    public boolean verify()
+    {
+        // Verify the source location.
+        super.verify();
+
+        // Verify the attributes.
+        for (IMXMLTagAttributeData attribute : getAttributeDatas())
+        {
+            ((MXMLTagAttributeData)attribute).verify();
+        }
+
+        return true;
+    }
+
+    /**
+     * For debugging only. This format is nice in the Eclipse debugger.
+     */
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append('<');
+        if (isCloseTag())
+            sb.append('/');
+        sb.append(getName());
+        if (isEmptyTag())
+            sb.append('/');
+        sb.append('>');
+
+        sb.append(' ');
+
+        // Display line, column, start, end as "17:5 160-188"
+        sb.append(super.toString());
+
+        // add content range as "(161-187)"
+        sb.append(' ');
+        sb.append('(');
+        sb.append(nameStart);
+        sb.append('-');
+        sb.append(contentEnd);
+        sb.append(')');
+
+        return sb.toString();
+    }
+
+    /**
+     * For debugging only. This format is nice in a text file.
+     */
+    @Override
+    public String toDumpString()
+    {
+        return buildDumpString(false);
+    }
+
+    @Override
+    public String buildDumpString(boolean skipSrcPath)
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append(super.buildDumpString(skipSrcPath));
+
+        sb.append('\t');
+
+        sb.append('|');
+        sb.append(getName());
+        sb.append('|');
+
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTextData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTextData.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTextData.java
new file mode 100644
index 0000000..c09f7a1
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTextData.java
@@ -0,0 +1,404 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import static org.apache.flex.compiler.constants.IMXMLCoreConstants.*;
+
+import java.util.Collection;
+
+import org.apache.flex.compiler.common.ISourceLocation;
+import org.apache.flex.compiler.internal.parsing.ISourceFragment;
+import org.apache.flex.compiler.internal.parsing.SourceFragment;
+import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
+import org.apache.flex.compiler.mxml.IMXMLTextData;
+import org.apache.flex.compiler.parsing.MXMLTokenTypes;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+
+/**
+ * Encapsulation of a block of text in MXML
+ */
+public class MXMLTextData extends MXMLUnitData implements IMXMLTextData
+{
+    /**
+     * Constructor.
+     */
+    MXMLTextData(MXMLToken textToken)
+    {
+        text = textToken.getText();
+
+        setOffsets(textToken.getStart(), textToken.getEnd());
+        setLine(textToken.getLine());
+        setColumn(textToken.getColumn());
+
+        switch (textToken.getType())
+        {
+            case MXMLTokenTypes.TOKEN_TEXT:
+            {
+                type = TextType.TEXT;
+                break;
+            }
+            case MXMLTokenTypes.TOKEN_WHITESPACE:
+            {
+                type = TextType.WHITESPACE;
+                break;
+            }
+            case MXMLTokenTypes.TOKEN_CDATA:
+            {
+                type = TextType.CDATA;
+                break;
+            }
+            case MXMLTokenTypes.TOKEN_COMMENT:
+            {
+                type = TextType.COMMENT;
+                break;
+            }
+            case MXMLTokenTypes.TOKEN_ASDOC_COMMENT:
+            {
+                type = TextType.ASDOC;
+                break;
+            }
+            default:
+            {
+                type = TextType.OTHER;
+                break;
+            }
+        }
+    }
+
+    /**
+     * The represented text
+     */
+    private String text;
+
+    private TextType type;
+
+    //
+    // Object overrides
+    //
+
+    // For debugging only. This format is nice in the Eclipse debugger.
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        // Display TEXT, WHITESPACE, etc.
+        sb.append(getTextType());
+
+        sb.append(' ');
+
+        // Display the text characters.
+        sb.append('"');
+        sb.append(getEscapedContent());
+        sb.append('"');
+
+        sb.append(' ');
+
+        // Display line, column, start, and end as "17:5 160-188".
+        sb.append(super.toString());
+
+        return sb.toString();
+    }
+
+    //
+    // MXMLUnitData overrides
+    //
+
+    @Override
+    public boolean isText()
+    {
+        return true;
+    }
+
+    // For debugging only.
+    @Override
+    public String getTypeString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append(super.getTypeString());
+        sb.append(":");
+        sb.append(getTextType());
+
+        return sb.toString();
+    }
+
+    // For debugging only. This format is nice in a text file.
+    @Override
+    public String toDumpString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append(super.toDumpString());
+
+        sb.append('\t');
+
+        sb.append('|');
+        sb.append(getEscapedContent());
+        sb.append('|');
+
+        return sb.toString();
+    }
+
+    //
+    // IMXMLTextData implementations
+    //
+
+    @Override
+    public String getContent()
+    {
+        return text;
+    }
+
+    @Override
+    public TextType getTextType()
+    {
+        return type;
+    }
+
+    //
+    // Other methods
+    //
+
+    // For debugging only.
+    private String getEscapedContent()
+    {
+        String s = getContent();
+
+        s = s.replaceAll("\n", "\\\\n");
+        s = s.replaceAll("\r", "\\\\r");
+        s = s.replaceAll("\t", "\\\\t");
+
+        return s;
+    }
+
+    @Override
+    public String getCompilableText()
+    {
+        switch (type)
+        {
+            case TEXT:
+            case CDATA:
+            case WHITESPACE:
+            {
+                return getContents();
+            }
+
+            case ASDOC:
+            case COMMENT:
+            {
+                return "";
+            }
+        }
+
+        assert false;
+        return null;
+    }
+
+    @Override
+    public int getCompilableTextStart()
+    {
+        return getContentsStart();
+    }
+
+    @Override
+    public int getCompilableTextEnd()
+    {
+        return getContentsEnd();
+    }
+
+    @Override
+    public int getCompilableTextLine()
+    {
+        return getLine();
+    }
+
+    @Override
+    public int getCompilableTextColumn()
+    {
+        return (getContentsStart() - getAbsoluteStart()) + getColumn();
+    }
+
+    /**
+     * Return the text contained within this unit, without any opening or
+     * closing delimiters
+     * 
+     * @return a normalized string
+     */
+    public String getContents()
+    {
+        String tokenString = text;
+
+        switch (type)
+        {
+            case CDATA:
+            {
+                if (tokenString.endsWith(cDataEnd))
+                {
+                    tokenString = tokenString.substring(cDataStart.length(), tokenString.length() - cDataEnd.length());
+                }
+                else
+                {
+                    tokenString = tokenString.substring(cDataStart.length());
+                }
+                return tokenString;
+            }
+            case ASDOC:
+            {
+                if (tokenString.endsWith(asDocEnd))
+                {
+                    tokenString = tokenString.substring(asDocStart.length(), tokenString.length() - asDocEnd.length());
+                }
+                else
+                {
+                    tokenString = tokenString.substring(asDocStart.length());
+                }
+                return tokenString;
+            }
+            case COMMENT:
+            {
+                if (tokenString.endsWith(commentEnd))
+                {
+                    tokenString = tokenString.substring(commentStart.length(), tokenString.length() - commentEnd.length());
+                }
+                else
+                {
+                    tokenString = tokenString.substring(commentStart.length());
+                }
+                return tokenString;
+            }
+            default:
+            {
+                break;
+            }
+        }
+
+        return text;
+    }
+
+    /**
+     * @return The start offset of actual content
+     */
+    public int getContentsStart()
+    {
+        switch (type)
+        {
+            case CDATA:
+                return getAbsoluteStart() + cDataStart.length();
+
+            case ASDOC:
+                return getAbsoluteStart() + asDocStart.length();
+
+            case COMMENT:
+                return getAbsoluteStart() + commentStart.length();
+
+            case OTHER:
+                return getAbsoluteStart();
+        }
+
+        return getAbsoluteStart();
+    }
+
+    /**
+     * @return The end offset of content
+     */
+    public int getContentsEnd()
+    {
+        switch (type)
+        {
+            case CDATA:
+                return text.endsWith(cDataEnd) ? getAbsoluteEnd() - cDataEnd.length() : getAbsoluteEnd();
+
+            case ASDOC:
+                return text.endsWith(asDocEnd) ? getAbsoluteEnd() - asDocEnd.length() : getAbsoluteEnd();
+
+            case COMMENT:
+                return text.endsWith(commentEnd) ? getAbsoluteEnd() - commentEnd.length() : getAbsoluteEnd();
+
+            case OTHER:
+                return getAbsoluteEnd();
+        }
+
+        return getAbsoluteEnd();
+    }
+
+    public int getContentsLine()
+    {
+        return getLine();
+    }
+
+    public int getContentsColumn()
+    {
+        switch (type)
+        {
+            case CDATA:
+                return getColumn() + cDataStart.length();
+
+            case ASDOC:
+                return getColumn() + asDocStart.length();
+
+            case COMMENT:
+                return getColumn() + commentStart.length();
+
+            case OTHER:
+                return getColumn();
+        }
+
+        return getColumn();
+    }
+
+    @Override
+    public ISourceFragment[] getFragments(Collection<ICompilerProblem> problems)
+    {
+        ISourceLocation location = this;
+
+        switch (type)
+        {
+            case TEXT:
+            {
+                // TEXT might contain one or more entities,
+                // in which case we will return multiple fragments.
+                MXMLDialect mxmlDialect = getMXMLDialect();
+                return EntityProcessor.parse(text, location, mxmlDialect, problems);
+            }
+
+            case WHITESPACE:
+            {
+                // WHITESPACE creates only a single fragment.
+                ISourceFragment fragment = new SourceFragment(text, location);
+                return new ISourceFragment[] {fragment};
+            }
+
+            case CDATA:
+            {
+                // CDATA creates only a single fragment.
+                ISourceFragment fragment = new SourceFragment(text, getContents(), getContentsStart(), getContentsLine(), getContentsColumn());
+                return new ISourceFragment[] {fragment};
+            }
+
+            default:
+            {
+                assert false : "Unexpected type of MXMLTextData";
+            }
+        }
+
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTextValue.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTextValue.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTextValue.java
new file mode 100644
index 0000000..790aa7a
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTextValue.java
@@ -0,0 +1,82 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
+import org.apache.flex.compiler.mxml.IMXMLTagAttributeData;
+import org.apache.flex.compiler.mxml.IMXMLTextValue;
+import org.apache.flex.compiler.mxml.IMXMLTextData.TextType;
+
+public class MXMLTextValue extends MXMLTagAttributeValue implements
+        IMXMLTextValue
+{
+    /**
+     * Constructor.
+     */
+    MXMLTextValue(MXMLToken textToken, IMXMLTagAttributeData parent)
+    {
+        super(parent);
+        setStart(textToken.getStart());
+        setEnd(textToken.getEnd());
+        setColumn(textToken.getColumn());
+        setLine(textToken.getLine());
+        text = textToken.getText();
+    }
+
+    private String text;
+
+    //
+    // Object overrides
+    //
+
+    /**
+     * For debugging only. This format is nice in the Eclipse debugger.
+     */
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append("|");
+        sb.append(getContent());
+        sb.append("| ");
+        sb.append(getLine());
+        sb.append(" ");
+        sb.append(getColumn());
+
+        return sb.toString();
+    }
+
+    //
+    // IMXMLTextData implementations
+    //
+
+    @Override
+    public String getContent()
+    {
+        return text;
+    }
+
+    @Override
+    public TextType getTextType()
+    {
+        return TextType.TEXT;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLUnitData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLUnitData.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLUnitData.java
new file mode 100644
index 0000000..0bd07ec
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLUnitData.java
@@ -0,0 +1,366 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import org.apache.flex.compiler.common.SourceLocation;
+import org.apache.flex.compiler.filespecs.FileSpecification;
+import org.apache.flex.compiler.filespecs.IFileSpecification;
+import org.apache.flex.compiler.mxml.IMXMLData;
+import org.apache.flex.compiler.mxml.IMXMLTagData;
+import org.apache.flex.compiler.mxml.IMXMLUnitData;
+import org.apache.flex.utils.FastStack;
+
+/**
+ * Encapsulation of an MXML unit: an open/close/empty tag, a chunk of text
+ * (perhaps whitespace, CDATA, or a comment), or a processing instruction.
+ * <p>
+ * An {@link MXMLData} object stores a linear list of MXML units, but it is
+ * possible to walk them in a hierarchical way.
+ */
+public abstract class MXMLUnitData extends SourceLocation implements
+        IMXMLUnitData
+{
+    /**
+     * Constructor.
+     */
+    public MXMLUnitData()
+    {
+        super();
+
+        parent = null;
+        index = -1;
+    }
+
+    /**
+     * Copy constructor.
+     */
+    public MXMLUnitData(MXMLUnitData other)
+    {
+        this.parent = other.parent;
+        this.index = other.index;
+    }
+
+    /**
+     * The {@link MXMLData} object that owns this unit.
+     */
+    private MXMLData parent;
+
+    /**
+     * This position of this unit in the linear list of units owned by the
+     * {@link MXMLData}.
+     */
+    protected int index;
+
+    /**
+     * The position of this unit's parent unit in the linear list of units owned
+     * by the {@link MXMLData}.
+     */
+    private int parentIndex;
+
+    @Override
+    public int getContentStart()
+    {
+        return getAbsoluteStart();
+    }
+
+    @Override
+    public int getContentEnd()
+    {
+        return getAbsoluteEnd();
+    }
+
+    /**
+     * Set this unit's position relative to its parent. Used in parsing.
+     * 
+     * @param parent MXML file containing the unit
+     * @param index this unit's position in the list
+     */
+    public void setLocation(MXMLData parent, int index)
+    {
+        this.parent = parent;
+        this.index = index;
+        setSourcePath(parent.getPath());
+    }
+
+    /**
+     * Sets the index of this tags hierarchical parent in its parents array of
+     * MXMLUnitData objects
+     * 
+     * @param parentIndex The index of the parent tag.
+     */
+    public void setParentUnitDataIndex(int parentIndex)
+    {
+        this.parentIndex = parentIndex;
+    }
+
+    @Override
+    public final IMXMLUnitData getParentUnitData()
+    {
+        return parent.getUnit(parentIndex);
+    }
+
+    /**
+     * Gets the index of this tags hierarchical parent in its parents array of
+     * MXMLUnitData objects
+     * 
+     * @return the index, or -1
+     */
+    public final int getParentUnitDataIndex()
+    {
+        return parentIndex;
+    }
+
+    /**
+     * Set this unit's start and end offsets. Used in parsing.
+     * 
+     * @param start start offset
+     * @param end end offset
+     */
+    public void setOffsets(int start, int end)
+    {
+        setStart(start);
+        setEnd(end);
+    }
+
+    /**
+     * Adjust all associated offsets by the adjustment amount
+     * 
+     * @param offsetAdjustment amount to add to offsets
+     */
+    public void adjustOffsets(int offsetAdjustment)
+    {
+        setStart(getAbsoluteStart() + offsetAdjustment);
+        setEnd(getAbsoluteEnd() + offsetAdjustment);
+    }
+
+    @Override
+    public final IFileSpecification getSource()
+    {
+        return new FileSpecification(getParent().getPath().toString());
+    }
+
+    @Override
+    public final int getIndex()
+    {
+        return index;
+    }
+
+    @Override
+    public boolean isText()
+    {
+        return false;
+    }
+
+    @Override
+    public boolean isTag()
+    {
+        return false;
+    }
+
+    @Override
+    public boolean isOpenTag()
+    {
+        return false;
+    }
+
+    @Override
+    public boolean isOpenAndNotEmptyTag()
+    {
+        return false;
+    }
+
+    @Override
+    public boolean isCloseTag()
+    {
+        return false;
+    }
+
+    @Override
+    public final IMXMLData getParent()
+    {
+        return parent;
+    }
+
+    @Override
+    public final IMXMLUnitData getPrevious()
+    {
+        return parent.getUnit(index - 1);
+    }
+
+    @Override
+    public final IMXMLUnitData getNext()
+    {
+        return parent.getUnit(index + 1);
+    }
+
+    @Override
+    public final IMXMLUnitData getNextSiblingUnit()
+    {
+        IMXMLUnitData unit = this;
+
+        if (isOpenAndNotEmptyTag())
+            unit = ((IMXMLTagData)unit).findMatchingEndTag();
+
+        if (unit != null)
+        {
+            unit = unit.getNext();
+
+            if (unit != null && (unit.getParentUnitData() != getParentUnitData()))
+                unit = null;
+        }
+        return unit;
+    }
+
+    @Override
+    public final IMXMLTagData getNextTag()
+    {
+        IMXMLUnitData nextUnit = getNext();
+
+        while (true)
+        {
+            if (nextUnit == null)
+                return null;
+
+            if (nextUnit.isTag())
+                return (IMXMLTagData)nextUnit;
+
+            nextUnit = nextUnit.getNext();
+        }
+    }
+
+    @Override
+    public boolean containsOffset(int offset)
+    {
+        return MXMLData.contains(getAbsoluteStart(), getAbsoluteEnd(), offset);
+    }
+
+    @Override
+    public final IMXMLTagData getContainingTag(int offset)
+    {
+        FastStack<String> tagNames = new FastStack<String>();
+        IMXMLUnitData current = getPrevious();
+        IMXMLTagData containingTag = null;
+
+        if (containsOffset(offset) && isCloseTag())
+        {
+            IMXMLTagData tag = (IMXMLTagData)this;
+            tagNames.push(tag.getName());
+        }
+
+        while (current != null && containingTag == null)
+        {
+            if (current.isTag())
+            {
+                IMXMLTagData currentTag = (IMXMLTagData)current;
+
+                if (currentTag.isCloseTag())
+                {
+                    tagNames.push(currentTag.getName());
+                }
+                else if (currentTag.isOpenTag() && !currentTag.isEmptyTag())
+                {
+                    String stackName = "";
+                    while (stackName.compareTo(currentTag.getName()) != 0 && !tagNames.isEmpty())
+                    {
+                        stackName = tagNames.pop();
+                    }
+                    if (stackName.compareTo(currentTag.getName()) != 0)
+                        containingTag = currentTag;
+                }
+            }
+
+            current = current.getPrevious();
+        }
+
+        return containingTag;
+    }
+
+    @Override
+    public MXMLDialect getMXMLDialect()
+    {
+        return getParent().getMXMLDialect();
+    }
+
+    protected String getTypeString()
+    {
+        return getClass().getSimpleName();
+    }
+
+    /**
+     * For debugging only. This format is nice in a text file.
+     */
+    public String toDumpString()
+    {
+        return buildDumpString(false);
+    }
+
+    public String buildDumpString(boolean skipSrcPath)
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append('[');
+        sb.append(getIndex());
+        sb.append(']');
+
+        sb.append('\t');
+        if (!skipSrcPath)
+        {
+            sb.append(getLine() + 1);
+            sb.append('\t');
+            sb.append(getColumn() + 1);
+            sb.append('\t');
+        }
+        sb.append(getAbsoluteStart());
+        sb.append('\t');
+        sb.append(getAbsoluteEnd());
+        sb.append('\t');
+
+        String type = getTypeString();
+        sb.append(type);
+        int n = 32 - type.length();
+        for (int i = 0; i < n; i++)
+            sb.append(' ');
+        sb.append('\t');
+
+        sb.append('^');
+        sb.append('[');
+        sb.append(parentIndex);
+        sb.append(']');
+
+        return sb.toString();
+    }
+
+    /**
+     * Verifies that this unit has its source location information set.
+     * <p>
+     * This is used only in asserts.
+     */
+    public boolean verify()
+    {
+        // Verify the source location.
+        assert getSourcePath() != null : "MXMLUnitData has null source path: " + toString();
+        assert getStart() != UNKNOWN : "MXMLUnitData has unknown start: " + toString();
+        assert getEnd() != UNKNOWN : "MXMLUnitData has unknown end: " + toString();
+        assert getLine() != UNKNOWN : "MXMLUnitData has unknown line: " + toString();
+        assert getColumn() != UNKNOWN : "MXMLUnitData has unknown column: " + toString();
+
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/StateDefinition.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/StateDefinition.java b/compiler/src/org/apache/flex/compiler/internal/mxml/StateDefinition.java
new file mode 100644
index 0000000..f8af599
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/StateDefinition.java
@@ -0,0 +1,93 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.flex.compiler.mxml.IStateDefinition;
+import org.apache.flex.compiler.mxml.IStateGroupDefinition;
+import org.apache.flex.compiler.scopes.IASScope;
+import org.apache.flex.compiler.tree.mxml.IMXMLStateNode;
+
+/**
+ * {@code StateDefinition} represents a state in MXML 2009 or later. States are
+ * per-class, so these objects are owned by the {@code ClassDefinitionNodes}
+ * that define classes in MXML.
+ */
+public class StateDefinition extends StateDefinitionBase implements
+        IStateDefinition
+{
+    private IMXMLStateNode node;
+
+    /**
+     * Constructor.
+     */
+    public StateDefinition(IMXMLStateNode node, IASScope containingScope, String name, int nameStart, int nameEnd)
+    {
+        super(name, node.getClassDefinitionNode().getDefinition(), containingScope, nameStart, nameEnd);
+        this.node = node;
+    }
+
+    /**
+     * A map mapping group names to {@code IStateGroup} objects. This is
+     * effectively the set of groups that include this state, but we use a map
+     * because we're interested in this set both as a set of group names (the
+     * String keys) and a set of group objects (the {@code IStateGroup} values).
+     */
+    private Map<String, IStateGroupDefinition> groupMap;
+
+    @Override
+    public IMXMLStateNode getNode()
+    {
+        return node;
+    }
+
+    @Override
+    public String[] getStateGroups()
+    {
+        return groupMap != null ? groupMap.keySet().toArray(new String[0]) : new String[0];
+    }
+
+    @Override
+    public IStateGroupDefinition[] resolveStateGroups()
+    {
+        return groupMap.values().toArray(new IStateGroupDefinition[0]);
+    }
+
+    @Override
+    public boolean isIncludedInStateGroup(String group)
+    {
+        return groupMap.containsKey(group);
+    }
+
+    /**
+     * Records that this state belongs to a specified group.
+     * 
+     * @param group An {@code IStateGroup} to which this state belongs.
+     */
+    public void addGroup(IStateGroupDefinition group)
+    {
+        if (groupMap == null)
+            groupMap = new HashMap<String, IStateGroupDefinition>(0);
+
+        groupMap.put(group.getBaseName(), group);
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/StateDefinitionBase.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/StateDefinitionBase.java b/compiler/src/org/apache/flex/compiler/internal/mxml/StateDefinitionBase.java
new file mode 100644
index 0000000..db786d9
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/StateDefinitionBase.java
@@ -0,0 +1,75 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.internal.definitions.DefinitionBase;
+import org.apache.flex.compiler.mxml.IStateDefinitionBase;
+import org.apache.flex.compiler.scopes.IASScope;
+
+/**
+ * {@code StateDefinitionBase} is an abstract base class for
+ * {@code StateDefinition} and {@code StateGroupDefinition}, which represent
+ * states and state groups in MXML 2009 and later.
+ */
+public abstract class StateDefinitionBase extends DefinitionBase implements
+        IStateDefinitionBase
+{
+    /**
+     * Constructor.
+     */
+    public StateDefinitionBase(String name, IClassDefinition containingClass, IASScope containingScope, int nameStart, int nameEnd)
+    {
+        super(name);
+        this.containingClass = containingClass;
+        setNameLocation(nameStart, nameEnd);
+        setContainingScope(containingScope);
+    }
+
+    private final IClassDefinition containingClass;
+
+    @Override
+    public boolean isImplicit()
+    {
+        return true; //this node will always be implicit, even though it will have offsets
+    }
+
+    @Override
+    public int compareTo(IStateDefinitionBase other)
+    {
+        return getNameStart() - other.getNameStart();
+    }
+
+    /**
+     * For debugging only.
+     */
+    @Override
+    public String toString()
+    {
+        return getBaseName();
+    }
+
+    @Override
+    public IClassDefinition getContainingClass()
+    {
+        return containingClass;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/StateGroupDefinition.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/StateGroupDefinition.java b/compiler/src/org/apache/flex/compiler/internal/mxml/StateGroupDefinition.java
new file mode 100644
index 0000000..927132b
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/StateGroupDefinition.java
@@ -0,0 +1,84 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.mxml.IStateDefinition;
+import org.apache.flex.compiler.mxml.IStateGroupDefinition;
+
+/**
+ * {@code StateGroupDefinition} represents a state group in an MXML class.
+ */
+public class StateGroupDefinition extends StateDefinitionBase implements
+        IStateGroupDefinition
+{
+    /**
+     * Constructor.
+     */
+    public StateGroupDefinition(String name, IClassDefinition containingClass)
+    {
+        super(name, containingClass, containingClass.getContainedScope(), -1, -1);
+
+    }
+
+    /**
+     * A map mapping state names to {@code IStateDefinition} objects. This is
+     * effectively the set of states included in this group, but we use a map
+     * because we're interested in this set both as a set of state names (the
+     * String keys) and a set of state objects (the {@code IStateDefinition}
+     * values).
+     */
+    private Map<String, IStateDefinition> stateMap;
+
+    @Override
+    public String[] getIncludedStates()
+    {
+        return stateMap.keySet().toArray(new String[0]);
+    }
+
+    @Override
+    public IStateDefinition[] resolveIncludedStates()
+    {
+        return stateMap.values().toArray(new IStateDefinition[0]);
+    }
+
+    @Override
+    public boolean isStateIncluded(String state)
+    {
+        return stateMap.containsKey(state);
+    }
+
+    /**
+     * Records that this group includes a specified state.
+     * 
+     * @param state An {@code IStateDefinition} that this group includes.
+     */
+    public void addState(IStateDefinition state)
+    {
+        if (stateMap == null)
+            stateMap = new HashMap<String, IStateDefinition>(0);
+
+        stateMap.put(state.getBaseName(), state);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/parsing/mxml/MXMLTagDataDepth.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/parsing/mxml/MXMLTagDataDepth.java b/compiler/src/org/apache/flex/compiler/internal/parsing/mxml/MXMLTagDataDepth.java
index 1e4bd8b..1b8e745 100644
--- a/compiler/src/org/apache/flex/compiler/internal/parsing/mxml/MXMLTagDataDepth.java
+++ b/compiler/src/org/apache/flex/compiler/internal/parsing/mxml/MXMLTagDataDepth.java
@@ -28,11 +28,11 @@ import java.util.Map;
 
 import org.apache.flex.compiler.common.PrefixMap;
 import org.apache.flex.compiler.filespecs.IFileSpecification;
+import org.apache.flex.compiler.internal.mxml.MXMLTagData;
 import org.apache.flex.compiler.mxml.IMXMLData;
 import org.apache.flex.compiler.mxml.IMXMLTagData;
 import org.apache.flex.compiler.mxml.IMXMLTagAttributeData;
 import org.apache.flex.compiler.mxml.IMXMLUnitData;
-import org.apache.flex.compiler.mxml.MXMLTagData;
 import org.apache.flex.compiler.parsing.MXMLTokenTypes;
 import org.apache.flex.compiler.problems.ICompilerProblem;
 import org.apache.flex.compiler.problems.SyntaxProblem;

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/projects/FlexProject.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/projects/FlexProject.java b/compiler/src/org/apache/flex/compiler/internal/projects/FlexProject.java
index 1ae3ae9..f5cfd9b 100644
--- a/compiler/src/org/apache/flex/compiler/internal/projects/FlexProject.java
+++ b/compiler/src/org/apache/flex/compiler/internal/projects/FlexProject.java
@@ -56,6 +56,7 @@ import org.apache.flex.compiler.internal.definitions.ClassDefinition;
 import org.apache.flex.compiler.internal.definitions.PackageDefinition;
 import org.apache.flex.compiler.internal.mxml.MXMLDialect;
 import org.apache.flex.compiler.internal.mxml.MXMLManifestManager;
+import org.apache.flex.compiler.internal.mxml.MXMLNamespaceMapping;
 import org.apache.flex.compiler.internal.projects.DependencyGraph.Edge;
 import org.apache.flex.compiler.internal.scopes.ASProjectScope;
 import org.apache.flex.compiler.internal.scopes.ASScope;
@@ -66,7 +67,6 @@ import org.apache.flex.compiler.internal.tree.mxml.MXMLImplicitImportNode;
 import org.apache.flex.compiler.internal.workspaces.Workspace;
 import org.apache.flex.compiler.mxml.IMXMLLanguageConstants;
 import org.apache.flex.compiler.mxml.IMXMLNamespaceMapping;
-import org.apache.flex.compiler.mxml.MXMLNamespaceMapping;
 import org.apache.flex.compiler.projects.IFlexProject;
 import org.apache.flex.compiler.scopes.IDefinitionSet;
 import org.apache.flex.compiler.targets.ISWCTarget;

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/tree/mxml/MXMLClassDefinitionNode.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/tree/mxml/MXMLClassDefinitionNode.java b/compiler/src/org/apache/flex/compiler/internal/tree/mxml/MXMLClassDefinitionNode.java
index 1159a0e..96093b0 100644
--- a/compiler/src/org/apache/flex/compiler/internal/tree/mxml/MXMLClassDefinitionNode.java
+++ b/compiler/src/org/apache/flex/compiler/internal/tree/mxml/MXMLClassDefinitionNode.java
@@ -37,6 +37,8 @@ import org.apache.flex.compiler.definitions.IClassDefinition.ClassClassification
 import org.apache.flex.compiler.definitions.metadata.IMetaTag;
 import org.apache.flex.compiler.internal.definitions.ClassDefinition;
 import org.apache.flex.compiler.internal.mxml.MXMLDialect;
+import org.apache.flex.compiler.internal.mxml.StateDefinition;
+import org.apache.flex.compiler.internal.mxml.StateGroupDefinition;
 import org.apache.flex.compiler.internal.projects.FlexProject;
 import org.apache.flex.compiler.internal.scopes.MXMLFileScope;
 import org.apache.flex.compiler.internal.scopes.TypeScope;
@@ -46,8 +48,6 @@ import org.apache.flex.compiler.mxml.IMXMLTagAttributeData;
 import org.apache.flex.compiler.mxml.IMXMLTagData;
 import org.apache.flex.compiler.mxml.IStateDefinition;
 import org.apache.flex.compiler.mxml.IStateGroupDefinition;
-import org.apache.flex.compiler.mxml.StateDefinition;
-import org.apache.flex.compiler.mxml.StateGroupDefinition;
 import org.apache.flex.compiler.projects.ICompilerProject;
 import org.apache.flex.compiler.scopes.IASScope;
 import org.apache.flex.compiler.tree.ASTNodeID;

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/tree/mxml/MXMLStateNode.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/tree/mxml/MXMLStateNode.java b/compiler/src/org/apache/flex/compiler/internal/tree/mxml/MXMLStateNode.java
index 8aabdd2..db8658c 100644
--- a/compiler/src/org/apache/flex/compiler/internal/tree/mxml/MXMLStateNode.java
+++ b/compiler/src/org/apache/flex/compiler/internal/tree/mxml/MXMLStateNode.java
@@ -23,11 +23,11 @@ import org.apache.flex.compiler.common.ASModifier;
 import org.apache.flex.compiler.common.IMetaInfo;
 import org.apache.flex.compiler.constants.INamespaceConstants;
 import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.internal.mxml.StateDefinition;
 import org.apache.flex.compiler.internal.tree.as.NodeBase;
 import org.apache.flex.compiler.mxml.IMXMLTagAttributeData;
 import org.apache.flex.compiler.mxml.IMXMLTagData;
 import org.apache.flex.compiler.mxml.IStateDefinition;
-import org.apache.flex.compiler.mxml.StateDefinition;
 import org.apache.flex.compiler.problems.ICompilerProblem;
 import org.apache.flex.compiler.problems.MXMLSemanticProblem;
 import org.apache.flex.compiler.tree.ASTNodeID;

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/IMXMLData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/IMXMLData.java b/compiler/src/org/apache/flex/compiler/mxml/IMXMLData.java
index 01621db..f5f0fb5 100644
--- a/compiler/src/org/apache/flex/compiler/mxml/IMXMLData.java
+++ b/compiler/src/org/apache/flex/compiler/mxml/IMXMLData.java
@@ -23,6 +23,7 @@ import java.util.Collection;
 
 import org.apache.flex.compiler.common.PrefixMap;
 import org.apache.flex.compiler.filespecs.IFileSpecification;
+import org.apache.flex.compiler.internal.mxml.MXMLData;
 import org.apache.flex.compiler.internal.mxml.MXMLDialect;
 import org.apache.flex.compiler.problems.ICompilerProblem;
 


[2/4] Moved MXMLData-related classes into internal package

Posted by go...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLData.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLData.java
deleted file mode 100644
index 1134bfb..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLData.java
+++ /dev/null
@@ -1,977 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-
-import org.apache.commons.io.IOUtils;
-
-import org.apache.flex.compiler.common.MutablePrefixMap;
-import org.apache.flex.compiler.common.PrefixMap;
-import org.apache.flex.compiler.filespecs.FileSpecification;
-import org.apache.flex.compiler.filespecs.IFileSpecification;
-import org.apache.flex.compiler.internal.mxml.MXMLDialect;
-import org.apache.flex.compiler.internal.parsing.mxml.BalancingMXMLProcessor;
-import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
-import org.apache.flex.compiler.internal.parsing.mxml.MXMLTokenizer;
-import org.apache.flex.compiler.internal.parsing.mxml.MXMLUnitDataIterator;
-import org.apache.flex.compiler.parsing.MXMLTokenTypes;
-import org.apache.flex.compiler.problems.ICompilerProblem;
-import org.apache.flex.compiler.problems.SyntaxProblem;
-import org.apache.flex.utils.FastStack;
-import org.apache.flex.utils.FastStack.IFastStackDecorator;
-
-/**
- * Encapsulation of an MXML file, with individual units for each open tag, close
- * tag, and block of text.
- */
-public class MXMLData implements IMXMLData
-{
-
-    private final class TokenizerPayload
-    {
-        private List<MXMLToken> tokens;
-
-        private PrefixMap prefixMap;
-
-        public TokenizerPayload(List<MXMLToken> tokens, PrefixMap prefixMap)
-        {
-            this.tokens = tokens;
-            this.prefixMap = prefixMap;
-        }
-
-        public List<MXMLToken> getMXMLTokens()
-        {
-            return tokens;
-        }
-
-        public PrefixMap getPrefixMap()
-        {
-            return prefixMap;
-        }
-    }
-
-    /**
-     * A cursor represents the offset into the document and the index of the
-     * MXML unit that contains that offset
-     */
-    public class Cursor
-    {
-        /**
-         * Offset into the document
-         */
-        private int offset;
-        /**
-         * Index of the unit that contains that offset
-         */
-        private int unitIndex;
-
-        /**
-         * Constructor (points to beginning of the MXMLData)
-         */
-        public Cursor()
-        {
-            reset();
-        }
-
-        /**
-         * Reset cursor to the beginning of the MXMLData
-         */
-        public void reset()
-        {
-            offset = 0;
-            unitIndex = 0;
-        }
-
-        /**
-         * Set the cursor to a particular offset/unit
-         * 
-         * @param offset offset into the document
-         * @param unitIndex index of the unit containing that offset
-         */
-        public void setCursor(int offset, int unitIndex)
-        {
-            this.offset = offset;
-            this.unitIndex = unitIndex;
-        }
-
-        /**
-         * Get the offset the cursor is pointing to
-         * 
-         * @return current document offset
-         */
-        public int getOffset()
-        {
-            return offset;
-        }
-
-        /**
-         * Get the index of the unit the cursor is pointing to
-         * 
-         * @return current unit index
-         */
-        public int getUnitIndex()
-        {
-            return unitIndex;
-        }
-    }
-
-    private String path = null;
-
-    /**
-     * Individual units for each open tag, close tag, and block of text
-     */
-    private IMXMLUnitData[] units;
-
-    /**
-     * Flag indicating that the tokens underlying this structure were fixed
-     */
-    private boolean wasRepaired;
-
-    private boolean shouldRepair = true;
-
-    /**
-     * This maps {@link IMXMLTagData} objects to their explicit
-     * {@link PrefixMap} if it exist
-     */
-    private HashMap<IMXMLTagData, PrefixMap> nsMap;
-
-    /**
-     * The cursor holds the result of last offset lookup into the MXMLData (see
-     * findNearestUnit, below). When an edit happens that causes the code
-     * coloring engine to recompute everything from the edit position to the end
-     * of the document, it will request MXMLOffsetInformations in order. Having
-     * the cursor speeds this up tremendously.
-     */
-    private Cursor cursor;
-
-    /**
-     * The dialect of MXML being used.
-     */
-    private MXMLDialect mxmlDialect;
-
-    private Collection<ICompilerProblem> problems = new ArrayList<ICompilerProblem>(2);
-
-    /**
-     * Tells us if we are currently processing full MXML, or a fragment
-     */
-    private boolean fullContent = true;
-
-    /**
-     * Constructor
-     * 
-     * @param tokens MXML tokens to build the MXMLData object from
-     * @param map the {@link PrefixMap} for the document, containing the
-     * namespace/prefix mappings
-     */
-    public MXMLData(List<MXMLToken> tokens, PrefixMap map, IFileSpecification fileSpec)
-    {
-        path = fileSpec.getPath();
-        init(tokens, map);
-    }
-
-    public MXMLData(List<MXMLToken> tokens, PrefixMap map, IFileSpecification fileSpec, boolean shouldRepair)
-    {
-        path = fileSpec.getPath();
-        this.shouldRepair = false;
-        init(tokens, map);
-    }
-
-    /**
-     * Constructor
-     * 
-     * @param mxmlText input build our {@link MXMLData} from
-     */
-    public MXMLData(int startOffset, Reader mxmlText, IFileSpecification fileSpec)
-    {
-        TokenizerPayload payload = getTokens(startOffset, mxmlText);
-        path = fileSpec.getPath();
-        init(payload.getMXMLTokens(), payload.getPrefixMap());
-    }
-
-    /**
-     * Constructor
-     * 
-     * @param mxmlText input build our {@link MXMLData} from
-     */
-    public MXMLData(int startOffset, Reader mxmlText, String path, boolean fullContent)
-    {
-        this.fullContent = fullContent;
-        TokenizerPayload payload = getTokens(startOffset, mxmlText);
-        this.path = path;
-        init(payload.getMXMLTokens(), payload.getPrefixMap());
-    }
-
-    public MXMLData(Reader mxmlText, IFileSpecification fileSpec)
-    {
-        this(0, mxmlText, fileSpec);
-    }
-
-    public MXMLData(Reader mxmlText, String path)
-    {
-        // Some clients of MXML data pass in a null IPath for the source path.
-        // Specifically this seems to happen in the code that builds a new
-        // mxml document from a template.
-        this(0, mxmlText, path != null ? path : null, true);
-    }
-
-    /**
-     * Constructor
-     * 
-     * @param specification input build our {@link MXMLData} from
-     */
-    public MXMLData(IFileSpecification specification)
-    {
-        TokenizerPayload payload;
-        try
-        {
-            path = specification.getPath();
-            payload = getTokens(specification.createReader());
-            init(payload.getMXMLTokens(), payload.getPrefixMap());
-        }
-        catch (FileNotFoundException e)
-        {
-            //do nothing
-        }
-    }
-
-    private void init(List<MXMLToken> tokens, PrefixMap map)
-    {
-        mxmlDialect = MXMLDialect.getMXMLDialect(map);
-        initializeFromTokens(tokens);
-    }
-
-    /**
-     * Update the version of the mxml data
-     * 
-     * @param map the prefix map
-     */
-    public void updateMXMLVersion(PrefixMap map)
-    {
-        mxmlDialect = MXMLDialect.getMXMLDialect(map);
-    }
-
-    /**
-     * Get the namespaces defined on the root tag
-     * 
-     * @param reader The reader which would provide the root tag information
-     * @return {@link PrefixMap} for the root tag
-     * @throws IOException error
-     */
-    public static PrefixMap getRootNamespaces(Reader reader) throws IOException
-    {
-        MXMLTokenizer tokenizer = new MXMLTokenizer();
-        try
-        {
-            tokenizer.setReader(reader);
-            return tokenizer.getRootTagPrefixMap().clone();
-        }
-        finally
-        {
-            tokenizer.close();
-        }
-    }
-
-    protected TokenizerPayload getTokens(Reader reader)
-    {
-        return getTokens(0, reader);
-    }
-
-    protected TokenizerPayload getTokens(int startOffset, Reader reader)
-    {
-        List<MXMLToken> tokens = null;
-        MXMLTokenizer tokenizer = new MXMLTokenizer(startOffset);
-        try
-        {
-            tokenizer.setIsRepairing(true);
-            tokens = tokenizer.parseTokens(reader);
-            wasRepaired = tokenizer.tokensWereRepaired();
-            return new TokenizerPayload(tokens, tokenizer.getPrefixMap());
-        }
-        finally
-        {
-            IOUtils.closeQuietly(tokenizer);
-        }
-    }
-
-    @Override
-    public MXMLDialect getMXMLDialect()
-    {
-        return mxmlDialect;
-    }
-
-    @Override
-    public PrefixMap getPrefixMapForData(IMXMLTagData data)
-    {
-        PrefixMap result = nsMap.get(data);
-        if (result != null)
-            return result;
-        if (data.isCloseTag())
-        {
-            IMXMLTagData openTagData = data.getParent().findTagOrSurroundingTagContainingOffset(data.getAbsoluteStart());
-            if (openTagData != null)
-                return nsMap.get(openTagData);
-        }
-        return null;
-    }
-
-    void removePrefixMappingForTag(IMXMLTagData data)
-    {
-        nsMap.remove(data);
-    }
-
-    void clearPrefixMappings()
-    {
-        nsMap.clear();
-    }
-
-    public void setPrefixMappings(HashMap<IMXMLTagData, PrefixMap> map)
-    {
-        if (nsMap != null)
-            nsMap.clear();
-        nsMap = map;
-    }
-
-    public Map<IMXMLTagData, PrefixMap> getTagToPrefixMap()
-    {
-        return nsMap;
-    }
-
-    /**
-     * Returns a collection of prefix->namespaces mappings found within this
-     * document. This map DOES NOT maintain order, and for more fine-grained
-     * information, the getPrefixMap call on individual {@link IMXMLTagData} and
-     * {@link IMXMLTagAttributeData} objects should be called
-     * 
-     * @return a prefix map
-     */
-    public PrefixMap getDocumentPrefixMap()
-    {
-        MutablePrefixMap map = new MutablePrefixMap();
-        for (PrefixMap tagMap : nsMap.values())
-        {
-            assert tagMap != null;
-            map.addAll(tagMap);
-        }
-        return map.toImmutable();
-    }
-
-    /**
-     * Returns the PrefixMap for the root tag of this {@link MXMLData} object
-     * 
-     * @return a {@link PrefixMap} or null
-     */
-    public PrefixMap getRootTagPrefixMap()
-    {
-        IMXMLTagData rootTag = getRootTag();
-        if (rootTag != null)
-        {
-            return nsMap.get(rootTag);
-        }
-        return null;
-    }
-
-    @Override
-    public Collection<ICompilerProblem> getProblems()
-    {
-        return problems;
-    }
-
-    public boolean hasProblems()
-    {
-        return problems.size() > 0;
-    }
-
-    /**
-     * Determines if this data was built from a source that was repaired
-     * 
-     * @return true if the underlying source was repaired
-     */
-    public boolean isDataRepaired()
-    {
-        return wasRepaired;
-    }
-
-    public void setWasRepaired(boolean wasRepaired)
-    {
-        this.wasRepaired = wasRepaired;
-    }
-
-    @Override
-    public IFileSpecification getFileSpecification()
-    {
-        return new FileSpecification(path);
-    }
-
-    @Override
-    public String getPath()
-    {
-        return path;
-    }
-
-    /**
-     * API to change the path after MXMLData creation. An MXMLDocument makes an
-     * MXMLData before the actual location is known.
-     * 
-     * @param path is the absolute path to the backing source file
-     */
-    public void setPath(String path)
-    {
-        this.path = path;
-    }
-
-    /**
-     * Common code from the two constructors
-     * 
-     * @param tokens A list of MXML tokens.
-     */
-    protected void initializeFromTokens(List<MXMLToken> tokens)
-    {
-        cursor = new Cursor();
-        parse(this, tokens, mxmlDialect, problems);
-        cursor.reset();
-    }
-
-    /**
-     * Use the MXML tokens to build MXMLUnitData.
-     * 
-     * @param data the {@link MXMLData} object
-     * @param tokens the list of tokens to build this data from
-     * @param dialect the {@link MXMLDialect} we are working against
-     * @param incremental true if this data is being built incrementally. All
-     * location updates will need to be done outside this element
-     */
-    private void parse(MXMLData data, List<MXMLToken> tokens, MXMLDialect dialect, Collection<ICompilerProblem> problems)
-    {
-        ArrayList<MXMLUnitData> units = new ArrayList<MXMLUnitData>(tokens.size() / 6);
-        nsMap = new HashMap<IMXMLTagData, PrefixMap>();
-        MXMLUnitData unit = null;
-        MXMLToken currentComment = null;
-        FastStack<Integer> depth = new FastStack<Integer>(tokens.size() / 8);
-        IFileSpecification spec = new FileSpecification(data.getPath() != null ? data.getPath() : "");
-        depth.setStackDecorator(new IFastStackDecorator<Integer>() {
-            @Override
-            public Integer decorate(Integer e)
-            {
-                if (e == null)
-                    return -1;
-                return e;
-            }
-
-        });
-        int index = -1;
-        int balancingIndex = 0;
-        depth.push(index);
-        ListIterator<MXMLToken> tokenIterator = tokens.listIterator();
-        BalancingMXMLProcessor processor = new BalancingMXMLProcessor(getFileSpecification(), problems);
-        while (tokenIterator.hasNext())
-        {
-            MXMLToken token = tokenIterator.next();
-            switch (token.getType())
-            {
-                case MXMLTokenTypes.TOKEN_ASDOC_COMMENT:
-                    currentComment = token;
-                    //treat this like text.
-                    unit = new MXMLTextData(token);
-                    units.add(unit);
-                    index++;
-                    if (fullContent)
-                    {
-                        unit.setParentUnitDataIndex(depth.peek());
-                        unit.setLocation(data, index);
-                    }
-                    break;
-                case MXMLTokenTypes.TOKEN_COMMENT:
-                case MXMLTokenTypes.TOKEN_CDATA:
-                case MXMLTokenTypes.TOKEN_WHITESPACE:
-                    //treat this like text.
-                    unit = new MXMLTextData(token);
-                    units.add(unit);
-                    index++;
-                    if (fullContent)
-                    {
-                        unit.setParentUnitDataIndex(depth.peek());
-                        unit.setLocation(data, index);
-                    }
-                    break;
-                case MXMLTokenTypes.TOKEN_OPEN_TAG_START:
-                    unit = new MXMLTagData();
-                    MutablePrefixMap map = ((MXMLTagData)unit).init(this, token, tokenIterator, dialect, spec, problems);
-                    ((MXMLTagData)unit).setCommentToken(currentComment);
-                    currentComment = null;
-                    units.add(unit);
-                    index++;
-                    if (fullContent)
-                    {
-                        unit.setParentUnitDataIndex(depth.peek());
-                        unit.setLocation(data, index);
-                        if (!((MXMLTagData)unit).isEmptyTag())
-                            processor.addOpenTag((MXMLTagData)unit, balancingIndex);
-                    }
-                    if (map != null)
-                        nsMap.put((MXMLTagData)unit, map.toImmutable());
-                    if (!((MXMLTagData)unit).isEmptyTag())
-                    {
-                        depth.push(index);
-                        balancingIndex++;
-                    }
-                    break;
-                case MXMLTokenTypes.TOKEN_CLOSE_TAG_START:
-                    unit = new MXMLTagData();
-                    ((MXMLTagData)unit).init(this, token, tokenIterator, dialect, spec, problems);
-                    ((MXMLTagData)unit).setCommentToken(currentComment);
-                    if (!((MXMLTagData)unit).isEmptyTag())
-                    {
-                        depth.pop();
-                        balancingIndex--;
-                    }
-                    index++;
-                    if (fullContent)
-                    {
-                        unit.setLocation(data, index);
-                        unit.setParentUnitDataIndex(depth.peek());
-                        processor.addCloseTag((MXMLTagData)unit, balancingIndex);
-                    }
-                    currentComment = null;
-                    units.add(unit);
-                    break;
-                case MXMLTokenTypes.TOKEN_TEXT:
-                    unit = new MXMLTextData(token);
-                    units.add(unit);
-                    index++;
-                    if (fullContent)
-                    {
-                        unit.setParentUnitDataIndex(depth.peek());
-                        unit.setLocation(data, index);
-                    }
-                    break;
-                case MXMLTokenTypes.TOKEN_MXML_BLOB:
-                    unit = new MXMLTagBlobData(token);
-                    units.add(unit);
-                    index++;
-                    if (fullContent)
-                    {
-                        unit.setParentUnitDataIndex(depth.peek());
-                        unit.setLocation(data, index);
-                    }
-                    break;
-                case MXMLTokenTypes.TOKEN_DATABINDING_START:
-                    unit = new MXMLDatabindingData(token, tokenIterator);
-                    units.add(unit);
-                    index++;
-                    if (fullContent)
-                    {
-                        unit.setParentUnitDataIndex(depth.peek());
-                        unit.setLocation(data, index);
-                    }
-                    break;
-                case MXMLTokenTypes.TOKEN_PROCESSING_INSTRUCTION:
-                    unit = new MXMLInstructionData(token);
-                    units.add(unit);
-                    index++;
-                    if (fullContent)
-                    {
-                        unit.setParentUnitDataIndex(depth.peek());
-                        unit.setLocation(data, index);
-                    }
-                    break;
-                default:
-                    if (token.isEntity())
-                    {
-                        unit = new MXMLEntityData(token);
-                        units.add(unit);
-                        index++;
-                        if (fullContent)
-                        {
-                            unit.setParentUnitDataIndex(depth.peek());
-                            unit.setLocation(data, index);
-                        }
-                        break;
-                    }
-                    else
-                    {
-                        problems.add(new SyntaxProblem(token));
-                        break;
-                    }
-            }
-        }
-        this.units = units.toArray(new IMXMLUnitData[0]);
-        if (fullContent && shouldRepair)
-        {
-            this.units = processor.balance(this.units, this, nsMap);
-            if (processor.wasRepaired())
-            { //repaired, so let's rebuild our prefix maps and tag depths
-                refreshPositionData();
-            }
-        }
-    }
-
-    /**
-     * Used to rebuild the structures inside of the MXMLData, refreshing prefix
-     * maps, depth and position data. Should only be used after calls that
-     * rebuild the internal structure are called
-     */
-    public void refreshPositionData()
-    {
-        FastStack<Integer> depth = new FastStack<Integer>(units.length / 2);
-        depth.setStackDecorator(new IFastStackDecorator<Integer>() {
-            @Override
-            public Integer decorate(Integer e)
-            {
-                if (e == null)
-                    return -1;
-                return e;
-            }
-
-        });
-        depth.clear();
-        depth.push(-1);
-        for (int i = 0; i < units.length; i++)
-        {
-            if (units[i] instanceof IMXMLTagData)
-            {
-                IMXMLTagData currentTag = (IMXMLTagData)units[i];
-                if (currentTag.isCloseTag())
-                {
-                    if (!currentTag.isEmptyTag())
-                        depth.pop();
-                }
-                ((MXMLTagData)currentTag).setParentUnitDataIndex(depth.peek());
-                ((MXMLTagData)currentTag).setLocation(this, i);
-                if (currentTag.isOpenTag())
-                {
-                    if (!currentTag.isEmptyTag())
-                    {
-                        depth.push(i);
-                    }
-                }
-            }
-            else
-            {
-                ((MXMLUnitData)units[i]).setParentUnitDataIndex(depth.peek());
-                ((MXMLUnitData)units[i]).setLocation(this, i);
-            }
-        }
-    }
-
-    @Override
-    public IMXMLUnitData[] getUnits()
-    {
-        return units;
-    }
-
-    public Iterator<IMXMLUnitData> getUnitIterator()
-    {
-        return new MXMLUnitDataIterator(units);
-    }
-
-    /**
-     * Replace the list of units in this MXMLData.
-     * 
-     * @param units units to add
-     */
-    public void setUnits(IMXMLUnitData[] units)
-    {
-        this.units = units;
-    }
-
-    @Override
-    public IMXMLUnitData getUnit(int i)
-    {
-        if (i < 0 || i >= units.length)
-            return null;
-        return units[i];
-    }
-
-    @Override
-    public int getNumUnits()
-    {
-        return units.length;
-    }
-
-    /**
-     * If the offset is contained within an MXML unit, get that unit. If it's
-     * not, then get the first unit that follows the offset.
-     * 
-     * @param offset test offset
-     * @return unit that contains (or immediately follows) the offset A few
-     * subtleties: In Falcon we have endeavored to preserve the existing
-     * definition of "nearest", so that for a given MXML file, falcon will find
-     * the same "nearest" unit.
-     */
-
-    protected IMXMLUnitData findNearestUnit(int offset)
-    {
-
-        // Use the cursor as a fast search hint. But only if the cursor is at or before the
-        // are of interest.
-        // TODO: do we care that this is not thread safe?
-        int startOffset = 0;
-        if (cursor.getOffset() <= offset)
-            startOffset = cursor.getUnitIndex();
-
-        // Sanity check
-        if (startOffset < 0 || startOffset >= units.length)
-            startOffset = 0;
-
-        // Now iterate though the units and find the first one that is acceptable
-        IMXMLUnitData ret = null;
-        for (int i = startOffset; (i < units.length) && (ret == null); i++)
-        {
-            IMXMLUnitData unit = units[i];
-
-            // unit is a match if it "contains" the offset.
-            // We are using a somewhat bizarre form of "contains" here, in that we are
-            // using getStart() and getConentEnd(). This asymmetric mismatch is for several reasons:
-            //      * it's the only way to match the existing (non-falcon) behavior
-            //      * If our cursor is before the <, we want to match the tag.
-            //              example:     |<foo   >  will find "foo" as the nearest tag.
-            //      So we need to use start here (not content start)
-            //      * If our cursor is between two tags, we want to match the NEXT one, not the previous one
-            //              example:   <bar >|<foo>  should match foo, not bar
-
-            if (MXMLData.contains(unit.getAbsoluteStart(), unit.getContentEnd(), offset))
-            {
-                ret = unit;
-            }
-            // if we find a unit that starts after the offset, then it must
-            // be the "first one after", so return it
-            else if (unit.getAbsoluteStart() >= offset)
-            {
-                ret = unit;
-            }
-        }
-
-        // If we found something, update the cursor for the next search
-        if (ret != null)
-            cursor.setCursor(offset, ret.getIndex());
-        return ret;
-    }
-
-    /**
-     * Get the unit that should be referenced when looking at what tags contain
-     * this offset (i.e. tags that are opened and not closed before this offset)
-     * 
-     * @param offset test offset
-     * @return reference unit for containment searches
-     */
-    public IMXMLUnitData findContainmentReferenceUnit(int offset)
-    {
-        return findNearestUnit(offset);
-    }
-
-    /**
-     * Get the unit that contains this offset
-     * 
-     * @param offset test offset
-     * @return the containing unit (or null if no unit contains this offset)
-     */
-    public IMXMLUnitData findUnitContainingOffset(int offset)
-    {
-        IMXMLUnitData unit = findNearestUnit(offset);
-        if (unit != null && unit.containsOffset(offset))
-            return unit;
-
-        return null;
-    }
-
-    /**
-     * Get the open, close, or empty tag that contains this offset. Note that if
-     * offset is inside a text node, this returns null. If you want the
-     * surrounding tag in that case, use
-     * findTagOrSurroundingTagContainingOffset.
-     * 
-     * @param offset test offset
-     * @return the containing tag (or null, if no tag contains this offset)
-     */
-    public IMXMLTagData findTagContainingOffset(int offset)
-    {
-        IMXMLUnitData unit = findUnitContainingOffset(offset);
-        if (unit != null && unit.isTag())
-            return (IMXMLTagData)unit;
-
-        return null;
-    }
-
-    @Override
-    public IMXMLTagData findTagOrSurroundingTagContainingOffset(int offset)
-    {
-        IMXMLUnitData unit = findUnitContainingOffset(offset);
-        if (unit != null)
-        {
-            if (unit.isTag())
-            {
-                return (IMXMLTagData)unit;
-            }
-            else if (unit.isText())
-            {
-                IMXMLTagData containingTag = unit.getContainingTag(unit.getAbsoluteStart());
-                return containingTag;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Get the open or empty tag whose attribute list contains this offset. A
-     * tag's attribute list extends from after the tag name + first whitespace
-     * until before the closing ">" or "/>".
-     * 
-     * @param offset test offset
-     * @return tag whose attribute list contains this offset (or null, if the
-     * offset isn't in any attribute lists
-     */
-    public IMXMLTagData findAttributeListContainingOffset(int offset)
-    {
-        IMXMLTagData tag = findTagContainingOffset(offset);
-        if (tag != null && tag.isOpenTag())
-            return tag.isOffsetInAttributeList(offset) ? tag : null;
-
-        return null;
-    }
-
-    /**
-     * Test whether the offset is contained within the range from start to end.
-     * This test excludes the start position and includes the end position,
-     * which is how you want things to work for code hints.
-     * 
-     * @param start start of the range (excluded)
-     * @param end end of the range (included)
-     * @param offset test offset
-     * @return true iff the offset is contained in the range
-     */
-    public static boolean contains(int start, int end, int offset)
-    {
-        return start < offset && end >= offset;
-    }
-
-    @Override
-    public IMXMLTagData getRootTag()
-    {
-        int n = units.length;
-        for (int i = 0; i < n; i++)
-        {
-            IMXMLUnitData unit = units[i];
-            if (unit instanceof IMXMLTagData)
-                return (IMXMLTagData)unit;
-        }
-        return null;
-    }
-
-    @Override
-    public int getEnd()
-    {
-        final int n = getNumUnits();
-        return n > 0 ? getUnit(n - 1).getAbsoluteEnd() : 0;
-    }
-
-    public Cursor getCursor()
-    {
-        return cursor;
-    }
-
-    /**
-     * Verifies that all units (plus all attributes on units that are tags) have
-     * their source location information set.
-     * <p>
-     * This is used only in asserts.
-     */
-    public boolean verify()
-    {
-        for (IMXMLUnitData unit : getUnits())
-        {
-            ((MXMLUnitData)unit).verify();
-        }
-
-        return true;
-    }
-
-    // For debugging only.
-    void dumpUnits()
-    {
-        for (IMXMLUnitData unit : getUnits())
-        {
-            System.out.println(((MXMLUnitData)unit).toDumpString());
-        }
-    }
-
-    /**
-     * For debugging only.
-     */
-    @Override
-    public String toString()
-    {
-        StringBuffer sb = new StringBuffer();
-
-        IMXMLUnitData[] units = getUnits();
-        int n = units.length;
-        for (int i = 0; i < n; i++)
-        {
-            // Display the unit's index as, for example, [3].
-            sb.append('[');
-            sb.append(i);
-            sb.append(']');
-
-            sb.append(' ');
-
-            // Display the unit's information.
-            sb.append(units[i].toString());
-
-            sb.append('\n');
-        }
-
-        return sb.toString();
-    }
-
-    public static void main(String[] args)
-    {
-        final FileSpecification fileSpec = new FileSpecification(args[0]);
-        final MXMLTokenizer tokenizer = new MXMLTokenizer(fileSpec);
-        List<MXMLToken> tokens = null;
-        try
-        {
-            tokens = tokenizer.parseTokens(fileSpec.createReader());
-
-            // Build tags and attributes from the tokens.
-            final MXMLData mxmlData = new MXMLData(tokens, tokenizer.getPrefixMap(), fileSpec);
-
-            mxmlData.dumpUnits();
-        }
-        catch (FileNotFoundException e)
-        {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-        finally
-        {
-            IOUtils.closeQuietly(tokenizer);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLDatabindingData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLDatabindingData.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLDatabindingData.java
deleted file mode 100644
index 6647263..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLDatabindingData.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import java.util.ListIterator;
-
-import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
-import org.apache.flex.compiler.parsing.IASToken;
-
-/**
- * Represents a databinding expression found within content of MXML
- */
-public class MXMLDatabindingData extends MXMLUnitData implements
-        IMXMLDatabindingData
-{
-    /**
-     * Constructor.
-     */
-    MXMLDatabindingData(MXMLToken start, ListIterator<MXMLToken> iterator)
-    {
-        bindingValue = new MXMLDatabindingValue(start, iterator);
-
-        setOffsets(bindingValue.getAbsoluteStart(), bindingValue.getAbsoluteEnd());
-        setLine(start.getLine());
-        setColumn(start.getColumn());
-    }
-
-    private IMXMLDatabindingValue bindingValue;
-
-    //
-    // IMXMLDatabindingData implementations
-    //
-
-    @Override
-    public IASToken[] getDatabindingContent()
-    {
-        return bindingValue.getDatabindingContent();
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLDatabindingValue.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLDatabindingValue.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLDatabindingValue.java
deleted file mode 100644
index ab24ad7..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLDatabindingValue.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import java.util.ArrayList;
-import java.util.ListIterator;
-
-import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
-import org.apache.flex.compiler.mxml.IMXMLTextData.TextType;
-import org.apache.flex.compiler.parsing.IASToken;
-
-/**
- * Represents a databinding expression found within an attribute value
- */
-public class MXMLDatabindingValue extends MXMLTagAttributeValue implements
-        IMXMLDatabindingValue
-{
-    /**
-     * Constructor.
-     */
-    MXMLDatabindingValue(MXMLToken start, ListIterator<MXMLToken> iterator, IMXMLTagAttributeData parent)
-    {
-        super(parent);
-
-        setStart(start.getStart());
-        setColumn(start.getColumn());
-        setLine(start.getLine());
-
-        while (iterator.hasNext())
-        {
-            MXMLToken token = iterator.next();
-
-            setEnd(token.getEnd());
-
-            if (token.isASToken())
-                tokens.add(token);
-            else
-                break;
-        }
-    }
-
-    /**
-     * Constructor.
-     */
-    MXMLDatabindingValue(MXMLToken start, ListIterator<MXMLToken> iterator)
-    {
-        this(start, iterator, null);
-    }
-
-    private ArrayList<IASToken> tokens = new ArrayList<IASToken>(5);
-
-    //
-    // IMXMLTextData implementations
-    //
-
-    @Override
-    public String getContent()
-    {
-        StringBuilder builder = new StringBuilder();
-
-        final int size = tokens.size();
-        IASToken lastToken = null;
-        for (int i = 0; i < size; i++)
-        {
-            IASToken currentToken = tokens.get(i);
-            if (lastToken != null)
-            {
-                int spaces = currentToken.getStart() - lastToken.getEnd();
-                for (int s = 0; s < spaces; s++)
-                    builder.append(" ");
-            }
-            builder.append(currentToken.getText());
-            lastToken = currentToken;
-        }
-
-        return builder.toString();
-    }
-
-    @Override
-    public TextType getTextType()
-    {
-        return TextType.DATABINDING;
-    }
-
-    //
-    // IMXMLDatabindingData implementations
-    //
-
-    @Override
-    public IASToken[] getDatabindingContent()
-    {
-        return tokens.toArray(new IASToken[0]);
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLEntityData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLEntityData.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLEntityData.java
deleted file mode 100644
index 376af19..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLEntityData.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
-
-public class MXMLEntityData extends MXMLTextData implements IMXMLEntityData
-{
-    /**
-     * Constructor.
-     */
-    MXMLEntityData(MXMLToken textToken)
-    {
-        super(textToken);
-
-        type = textToken.getType();
-    }
-
-    private int type;
-
-    //
-    // Object overrides
-    //
-
-    // This method is only used for debugging.
-    @Override
-    public String toString()
-    {
-        String s = getCompilableText();
-
-        s = s.replaceAll("\n", "\\\\n");
-        s = s.replaceAll("\r", "\\\\r");
-        s = s.replaceAll("\t", "\\\\t");
-
-        StringBuilder sb = new StringBuilder();
-        sb.append(type);
-        sb.append(" \"");
-        sb.append(s);
-        sb.append("\"");
-        return sb.toString();
-    }
-
-    //
-    // MXMLTextData overrides
-    // 
-
-    @Override
-    public String getCompilableText()
-    {
-        return getDecodedContent();
-    }
-
-    //
-    // IMXMLEntityData implementations
-    //
-
-    @Override
-    public String getDecodedContent()
-    {
-        return MXMLEntityValue.getDecodedContent(getContents(), type);
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLEntityValue.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLEntityValue.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLEntityValue.java
deleted file mode 100644
index 68e6a70..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLEntityValue.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.flex.compiler.mxml.IMXMLTextData.TextType;
-import org.apache.flex.compiler.parsing.IMXMLToken;
-import org.apache.flex.compiler.parsing.MXMLTokenTypes;
-
-public class MXMLEntityValue extends MXMLTagAttributeValue implements
-        IMXMLEntityValue
-{
-    private static final Map<String, String> NAMED_ENTITIES;
-
-    static
-    {
-        NAMED_ENTITIES = new HashMap<String, String>(5);
-
-        NAMED_ENTITIES.put("&amp;", "&");
-        NAMED_ENTITIES.put("&apos;", "'");
-        NAMED_ENTITIES.put("&gt;", ">");
-        NAMED_ENTITIES.put("&lt;", "<");
-        NAMED_ENTITIES.put("&quot;", "\"");
-
-        // TODO HTML 4 supports about 250 named characters
-        // HTML 5 supports about 2500. How many should MXML support
-        // beyond these required 5? What did Xerces/mxmlc support?
-    }
-
-    static final String getDecodedContent(String content, int type)
-    {
-        switch (type)
-        {
-            case MXMLTokenTypes.TOKEN_ENTITY:
-            {
-                return NAMED_ENTITIES.get(content);
-            }
-            case MXMLTokenTypes.TOKEN_HEX_ENTITY:
-            {
-                //thanks to the lexer, we are always: &#x00000;
-                //strip off the first 3 chars and the trailing semicolon
-                return String.valueOf(Integer.parseInt(content.substring(3, content.length() - 1), 16));
-            }
-            case MXMLTokenTypes.TOKEN_DECIMAL_ENTITY:
-            {
-                //thanks to the lexer, we are always: &#\21267;
-                //strip off the first 3 chars and the trailing semicolon
-                return String.valueOf(Integer.parseInt(content.substring(3, content.length() - 1)));
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Constructor.
-     */
-    MXMLEntityValue(IMXMLToken token, IMXMLTagAttributeData parent)
-    {
-        super(parent);
-
-        content = token.getText();
-        type = token.getType();
-
-        setStart(token.getStart());
-        setEnd(token.getEnd());
-        setColumn(token.getColumn());
-        setLine(token.getLine());
-    }
-
-    private final String content;
-
-    /**
-     * Token type which tells us what kind of entity we are dealing with
-     */
-    private final int type;
-
-    //
-    // Object overrides
-    //
-
-    // For debugging only. This format is nice in the Eclipse debugger.
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append("|");
-        sb.append(getContent());
-        sb.append("| ");
-        sb.append(getLine());
-        sb.append(" ");
-        sb.append(getColumn());
-
-        return sb.toString();
-    }
-
-    //
-    // IMXMLTagAttributeValue implementations
-    //
-
-    @Override
-    public String getContent()
-    {
-        return content;
-    }
-
-    @Override
-    public TextType getTextType()
-    {
-        return TextType.ENTITY;
-    }
-
-    //
-    // IMXMLEntityValue implementations
-    //
-
-    @Override
-    public String getDecodedContent()
-    {
-        return getDecodedContent(content, type);
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLInstructionData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLInstructionData.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLInstructionData.java
deleted file mode 100644
index aca282c..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLInstructionData.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import org.apache.flex.compiler.parsing.IMXMLToken;
-
-public class MXMLInstructionData extends MXMLUnitData implements
-        IMXMLInstructionData
-{
-    /**
-     * Constructor.
-     */
-    MXMLInstructionData(IMXMLToken token)
-    {
-        instructionText = token.getText();
-
-        setOffsets(token.getStart(), token.getEnd());
-        setColumn(token.getColumn());
-        setLine(token.getLine());
-    }
-
-    private String instructionText;
-
-    //
-    // Object overrides
-    //
-
-    // For debugging only. This format is nice in the Eclipse debugger.
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append('|');
-        sb.append(getInstructionText());
-        sb.append('|');
-
-        sb.append(' ');
-
-        // Display line, column, start, and end as "17:5 160-188".
-        sb.append(super.toString());
-
-        return sb.toString();
-    }
-
-    //
-    // MXMLUnitData overrides
-    //
-
-    // For debugging only. This format is nice in a text file.
-    @Override
-    public String toDumpString()
-    {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append(super.toDumpString());
-
-        sb.append('\t');
-
-        sb.append('"');
-        sb.append(getInstructionText());
-        sb.append('"');
-
-        return sb.toString();
-    }
-
-    //
-    // IMXMLInstructionData implementations
-    //
-
-    /**
-     * Returns the raw processing instruction. It is up to clients to parse
-     * this.
-     */
-    public String getInstructionText()
-    {
-        return instructionText;
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLNamespaceAttributeData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLNamespaceAttributeData.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLNamespaceAttributeData.java
deleted file mode 100644
index 90a42f0..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLNamespaceAttributeData.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import java.util.Collection;
-import java.util.ListIterator;
-
-import org.apache.flex.compiler.filespecs.IFileSpecification;
-import org.apache.flex.compiler.internal.mxml.MXMLDialect;
-import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
-import org.apache.flex.compiler.problems.ICompilerProblem;
-
-/**
- * Represents an xmlns style namespace import found within the MXML language
- */
-public class MXMLNamespaceAttributeData extends MXMLTagAttributeData implements
-        IMXMLNamespaceAttributeData
-{
-    /**
-     * Constructor.
-     */
-    MXMLNamespaceAttributeData(MXMLToken nameToken, ListIterator<MXMLToken> tokenIterator, MXMLDialect mxmlDialect, IFileSpecification spec, Collection<ICompilerProblem> problems)
-    {
-        super(nameToken, tokenIterator, mxmlDialect, spec, problems);
-
-        if (attributeName.startsWith("xmlns:"))
-            prefix = attributeName.substring(6);
-    }
-
-    private String prefix = "";
-
-    //
-    // IMXMLNamepsaceAttributeData implementations
-    //
-
-    @Override
-    public String getNamespacePrefix()
-    {
-        return prefix;
-    }
-
-    @Override
-    public String getNamespace()
-    {
-        return getRawValue();
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLNamespaceMapping.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLNamespaceMapping.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLNamespaceMapping.java
deleted file mode 100644
index d6c4292..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLNamespaceMapping.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-/**
- * This class stores a MXML-namespace-URI-to-manifest-file mapping.
- */
-public class MXMLNamespaceMapping implements IMXMLNamespaceMapping
-{
-    public MXMLNamespaceMapping(String uri, String manifestFileName)
-    {
-        assert uri != null;
-        assert manifestFileName != null;
-        this.uri = uri;
-        this.manifestFileName = manifestFileName;
-    }
-
-    private String uri;
-    private String manifestFileName;
-
-    @Override
-    public String getURI()
-    {
-        return uri;
-    }
-
-    @Override
-    public String getManifestFileName()
-    {
-        return manifestFileName;
-    }
-
-    /**
-     * For debugging.
-     * 
-     * @return Debug string representation of this object.
-     */
-    @Override
-    public String toString()
-    {
-        return uri + "->" + manifestFileName;
-    }
-
-    @Override
-    public boolean equals(Object obj)
-    {
-        if (obj == this)
-            return true;
-        if (!(obj instanceof MXMLNamespaceMapping))
-            return false;
-        MXMLNamespaceMapping other = (MXMLNamespaceMapping)obj;
-        if (!(uri.equals(other.uri)))
-            return false;
-        return manifestFileName.equals(other.manifestFileName);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLStateSplitter.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLStateSplitter.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLStateSplitter.java
deleted file mode 100644
index 0631088..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLStateSplitter.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import java.util.Collection;
-
-import org.apache.flex.compiler.filespecs.IFileSpecification;
-import org.apache.flex.compiler.internal.mxml.MXMLDialect;
-import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
-import org.apache.flex.compiler.parsing.IMXMLToken;
-import org.apache.flex.compiler.problems.ICompilerProblem;
-import org.apache.flex.compiler.problems.SyntaxProblem;
-
-/**
- * Simple utility for parsing attribute.state phrases.
- */
-public class MXMLStateSplitter
-{
-    /**
-     * Constructor.
-     */
-    public MXMLStateSplitter(IMXMLToken nameToken, MXMLDialect mxmlDialect, Collection<ICompilerProblem> problems, IFileSpecification fileSpec)
-    {
-        // Is there a dot in the name?
-        String name = nameToken.getText();
-        int i = name.indexOf('.');
-        if (i >= 0)
-        {
-            if (mxmlDialect != null && mxmlDialect.isEqualToOrAfter(MXMLDialect.MXML_2009))
-            {
-                baseName = name.substring(0, i);
-                stateName = name.substring(i + 1);
-                stateNameOffset = i + 1;
-            }
-            else
-            {
-                stateNameOffset = -1;
-                baseName = name;
-                stateName = null;
-
-                // TODO: I don't think is going to make the right kind of "problem"
-                // This is how the old code worked, but I think it will give a strange message
-                if (problems != null && fileSpec != null)
-                    problems.add(new SyntaxProblem((MXMLToken)nameToken, "Spark state overrides not supported by current language version"));
-            }
-        }
-        else
-        {
-            // no dot.
-            baseName = name;
-            stateNameOffset = -1;
-            stateName = null;
-        }
-    }
-
-    /**
-     * The part of the name before the dot, or the whole name if no dot.
-     */
-    public final String baseName;
-
-    /**
-     * What's after the first dot (state override), or null if no dot
-     */
-    public final String stateName;
-
-    /**
-     * offset of state name, where zero is the first character in the name
-     */
-    public final int stateNameOffset;
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLTagAttributeData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLTagAttributeData.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLTagAttributeData.java
deleted file mode 100644
index 0729af6..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLTagAttributeData.java
+++ /dev/null
@@ -1,635 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.ListIterator;
-
-import org.apache.flex.compiler.common.ISourceLocation;
-import org.apache.flex.compiler.common.PrefixMap;
-import org.apache.flex.compiler.common.SourceLocation;
-import org.apache.flex.compiler.common.XMLName;
-import org.apache.flex.compiler.filespecs.IFileSpecification;
-import org.apache.flex.compiler.internal.mxml.EntityProcessor;
-import org.apache.flex.compiler.internal.mxml.MXMLDialect;
-import org.apache.flex.compiler.internal.parsing.ISourceFragment;
-import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
-import org.apache.flex.compiler.parsing.IMXMLToken;
-import org.apache.flex.compiler.parsing.MXMLTokenTypes;
-import org.apache.flex.compiler.problems.ICompilerProblem;
-import org.apache.flex.compiler.problems.SyntaxProblem;
-
-/**
- * Encapsulation of a tag attribute in MXML
- */
-public class MXMLTagAttributeData extends SourceLocation implements
-        IMXMLTagAttributeData
-{
-    /**
-     * Constructor.
-     */
-    MXMLTagAttributeData(MXMLToken nameToken, ListIterator<MXMLToken> tokenIterator, MXMLDialect mxmlDialect, IFileSpecification spec, Collection<ICompilerProblem> problems)
-    {
-        setStart(nameToken.getStart());
-        setLine(nameToken.getLine());
-        setColumn(nameToken.getColumn());
-        setEnd(nameToken.getEnd());
-
-        // Deal with name if it is of the form name.state
-        MXMLStateSplitter splitState = new MXMLStateSplitter(nameToken, mxmlDialect, problems, spec);
-        attributeName = splitState.baseName;
-        if (splitState.stateName != null)
-        {
-            stateName = splitState.stateName;
-            stateStart = nameToken.getStart() + splitState.stateNameOffset;
-        }
-
-        MXMLToken token = null;
-
-        // Look for "=" token
-        if (tokenIterator.hasNext())
-        {
-            token = tokenIterator.next();
-
-            if (token.getType() != MXMLTokenTypes.TOKEN_EQUALS)
-            {
-                problems.add(new SyntaxProblem(token));
-                // need to restore the token position in the error
-                // case to handle error recovery otherwise the any
-                // trees after this won't be created
-                tokenIterator.previous();
-                return;
-            }
-
-            valueStart = token.getEnd() + 1; //set the attributes start to right after the equals until we have a value
-            valueLine = token.getLine();
-            valueColumn = token.getColumn();
-        }
-
-        // Look for value token
-        ArrayList<IMXMLTagAttributeValue> values = new ArrayList<IMXMLTagAttributeValue>(3);
-        while (tokenIterator.hasNext())
-        {
-            token = tokenIterator.next();
-            if (token.getType() == MXMLTokenTypes.TOKEN_DATABINDING_START)
-            {
-                values.add(new MXMLDatabindingValue(token, tokenIterator, this));
-            }
-            else if (token.getType() == MXMLTokenTypes.TOKEN_STRING)
-            {
-                values.add(new MXMLTextValue(token, this));
-            }
-            else if (token.isEntity())
-            {
-                values.add(new MXMLEntityValue(token, this));
-            }
-            else
-            {
-                if (!MXMLToken.isTagEnd(token.getType()) && token.getType() != MXMLTokenTypes.TOKEN_NAME)
-                {
-                    // if we error out early, push back token - it may be start of next tag
-                    // this is "pre-falcon" repair that was lost
-                    tokenIterator.previous();
-                    problems.add(new SyntaxProblem(token));
-                }
-                else
-                {
-                    tokenIterator.previous();
-                }
-                break;
-            }
-        }
-
-        this.values = values.toArray(new MXMLTagAttributeValue[0]);
-
-        if (this.values.length > 0)
-        {
-            //set the start value
-            IMXMLTagAttributeValue value = this.values[0];
-            valueStart = value.getAbsoluteStart();
-            valueLine = value.getLine();
-            valueColumn = value.getColumn();
-            final int valueEnd = getValueEnd();
-            setEnd(valueEnd + 1);
-        }
-    }
-
-    /**
-     * The MXML tag that contains this attribute
-     */
-    protected IMXMLTagData parent;
-
-    /**
-     * The name of this attribute.
-     */
-    protected String attributeName;
-
-    /**
-     * The offset at which the attribute value starts
-     */
-    protected int valueStart;
-
-    /**
-     * The line on which the attribute value starts
-     */
-    protected int valueLine;
-
-    /**
-     * The column at which the attribute value starts
-     */
-    protected int valueColumn;
-
-    /**
-     * Array of values inside this attribute data.
-     */
-    private IMXMLTagAttributeValue[] values = new IMXMLTagAttributeValue[0];
-
-    /**
-     * The name of this state, if it exists
-     */
-    protected String stateName;
-
-    /**
-     * The offset at which the optional state starts
-     */
-    protected int stateStart;
-
-    /**
-     * The URI specified by this attribute's prefix.
-     */
-    protected String uri;
-
-    //
-    // Object overrides.
-    //
-
-    // For debugging only. This format is nice in the Eclipse debugger.
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder();
-        buildAttributeString(false);
-        return sb.toString();
-    }
-
-    /**
-     * For unit tests only.
-     * 
-     * @return name value and offsets in string form
-     */
-    public String buildAttributeString(boolean skipSrcPath)
-    {
-        StringBuilder sb = new StringBuilder();
-        sb.append(getName());
-        sb.append('=');
-        sb.append('"');
-        sb.append(getRawValue());
-        sb.append('"');
-
-        sb.append(' ');
-
-        // Display line, column, start, and end as "17:5 160-188".
-        if (skipSrcPath)
-            sb.append(getOffsetsString());
-        else
-            sb.append(super.toString());
-        return sb.toString();
-    }
-
-    //
-    // Other methods
-    //
-
-    @Override
-    public IMXMLTagData getParent()
-    {
-        return parent;
-    }
-
-    /**
-     * Sets this attribute's tag.
-     * 
-     * @param parent MXML tag containing this attribute
-     */
-    public void setParent(IMXMLTagData parent)
-    {
-        this.parent = parent;
-        setSourcePath(parent.getSourcePath());
-    }
-
-    /**
-     * Adjust all associated offsets by the adjustment amount
-     * 
-     * @param offsetAdjustment amount to add to offsets
-     */
-    public void adjustOffsets(int offsetAdjustment)
-    {
-        if (attributeName != null)
-        {
-            setStart(getAbsoluteStart() + offsetAdjustment);
-            setEnd(getAbsoluteEnd() + offsetAdjustment);
-        }
-
-        if (hasValue())
-        {
-            valueStart += offsetAdjustment;
-            for (int i = 0; i < values.length; i++)
-            {
-                ((MXMLTagAttributeValue)values[i]).setStart(values[i].getAbsoluteStart() + offsetAdjustment);
-                ((MXMLTagAttributeValue)values[i]).setEnd(values[i].getAbsoluteEnd() + offsetAdjustment);
-            }
-        }
-
-        if (stateName != null)
-            stateStart += offsetAdjustment;
-    }
-
-    @Override
-    public String getName()
-    {
-        return attributeName;
-    }
-
-    @Override
-    public String getStateName()
-    {
-        return stateName != null ? stateName : "";
-    }
-
-    /**
-     * Checks whether this attribute is associated with a state.
-     * 
-     * @return True if a state association exists.
-     */
-    public boolean hasState()
-    {
-        return stateName != null;
-    }
-
-    @Override
-    public boolean hasValue()
-    {
-        return values.length > 0;
-    }
-
-    @Override
-    public IMXMLTagAttributeValue[] getValues()
-    {
-        return values;
-    }
-
-    /**
-     * Get the attribute value as a String (with quotes)
-     * 
-     * @return attribute value (with quotes)
-     */
-    public String getValueWithQuotes()
-    {
-        StringBuilder value = new StringBuilder();
-
-        final int size = values.length;
-        IMXMLTagAttributeValue lastData = null;
-        for (int i = 0; i < size; i++)
-        {
-            IMXMLTagAttributeValue data = values[i];
-            if (lastData != null)
-            {
-                for (int s = 0; s < data.getAbsoluteStart() - lastData.getAbsoluteEnd(); i++)
-                {
-                    value.append(" ");
-                }
-            }
-            value.append(data.getContent());
-        }
-
-        return value.toString();
-    }
-
-    @Override
-    public String getRawValue()
-    {
-        String value = getValueWithQuotes();
-
-        if (value != null && value.length() > 0)
-        {
-            // length can be one in case of invalid data and then the substring() call fails
-            // so, handle it here
-            if (value.charAt(0) == value.charAt(value.length() - 1) && value.length() != 1)
-                value = value.substring(1, value.length() - 1);
-            else
-                value = value.substring(1);
-        }
-
-        return value;
-    }
-
-    @Override
-    public ISourceFragment[] getValueFragments(Collection<ICompilerProblem> problems)
-    {
-        String value = getRawValue();
-        ISourceLocation location = getValueLocation();
-        MXMLDialect mxmlDialect = getMXMLDialect();
-
-        return EntityProcessor.parse(value, location, mxmlDialect, problems);
-    }
-
-    /**
-     * Returns the value of the raw token (without quotes) only if only one
-     * value exists and it is a string value New clients should take into
-     * account that multiple values exist inside of an attribute value
-     * 
-     * @return a value token, or null
-     */
-    // TODO Rename to getValueToken()
-    public IMXMLToken getRawValueToken()
-    {
-        if (hasState() && values.length == 1 && values[0] instanceof IMXMLTextValue)
-        {
-            String value = getRawValue();
-            if (value != null)
-            {
-                return new MXMLToken(MXMLTokenTypes.TOKEN_STRING, getValueStart() + 1, getValueStart() + 1 + value.length(), -1, -1, value);
-            }
-        }
-        return null;
-    }
-
-    public IFileSpecification getSource()
-    {
-        return getParent().getSource();
-    }
-
-    /**
-     * Get this unit's line number.
-     * 
-     * @return end offset
-     */
-    public final int getNameLine()
-    {
-        return getLine();
-    }
-
-    /**
-     * Get this unit's column number.
-     * 
-     * @return end offset
-     */
-    public final int getNameColumn()
-    {
-        return getColumn();
-    }
-
-    public int getNameStart()
-    {
-        return getAbsoluteStart();
-    }
-
-    /**
-     * Get this attribute's name's end offset
-     * 
-     * @return name end offset
-     */
-    public int getNameEnd()
-    {
-        return getAbsoluteStart() + attributeName.length();
-    }
-
-    @Override
-    public int getValueStart()
-    {
-        return hasValue() ? valueStart + 1 : 0;
-    }
-
-    @Override
-    public int getValueEnd()
-    {
-        if (hasValue())
-        {
-            String lastContent = values[values.length - 1].getContent();
-
-            if (lastContent.charAt(0) == lastContent.charAt(lastContent.length() - 1))
-                return getValueStart() + lastContent.length() - 2;
-
-            return getValueStart() + lastContent.length();
-        }
-
-        // If there is no valid "end", then we must return -1. Callers depend on this.
-        // See MXMLTagData.findArttributeContainingOffset for an example
-        return -1;
-    }
-
-    @Override
-    public int getValueLine()
-    {
-        return hasValue() ? valueLine : 0;
-    }
-
-    @Override
-    public int getValueColumn()
-    {
-        return hasValue() ? valueColumn + 1 : 0;
-    }
-
-    @Override
-    public SourceLocation getValueLocation()
-    {
-        return new SourceLocation(getSourcePath(), getValueStart(), getValueEnd(), getValueLine(), getValueColumn());
-    }
-
-    /**
-     * Get this attribute's state start offset if a state token is present other
-     * wise zero.
-     * 
-     * @return state start offset or zero
-     */
-    public int getStateStart()
-    {
-        return stateName != null ? stateStart : 0;
-    }
-
-    /**
-     * Get this attribute's state tokens end offset if a state token is present
-     * other wise zero.
-     * 
-     * @return state start offset or zero
-     */
-    public int getStateEnd()
-    {
-        return stateName != null ? stateStart + stateName.length() : 0;
-    }
-
-    /**
-     * Does this value have a closing quote character?
-     * 
-     * @return true if this value has a closing quote character
-     */
-    protected boolean valueIsWellFormed()
-    {
-        // If there is a value, it came from a string token.  We know (from the
-        // RawTagTokenizer) that this means it starts with a quote character.  If
-        // it ends with the same quote character, it's well formed.
-        if (hasValue())
-        {
-            String lastContent = values[values.length - 1].getContent();
-            return (lastContent.charAt(0) == lastContent.charAt(lastContent.length() - 1));
-        }
-
-        return false;
-    }
-
-    /**
-     * Returns the {@link PrefixMap} that represents all prefix->namespace
-     * mappings are in play on this tag. For example, if a parent tag defines
-     * <code>xmlns:m="falcon"</code> and this tag defines
-     * <code>xmlns:m="eagle"</code> then in this prefix map, m will equal
-     * "eagle"
-     * 
-     * @return a {@link PrefixMap} or null
-     */
-    public PrefixMap getCompositePrefixMap()
-    {
-        return parent.getCompositePrefixMap();
-    }
-
-    /**
-     * Does the offset fall inside the bounds of the attribute name?
-     * 
-     * @param offset test offset
-     * @return true if the offset falls within the attribute name
-     */
-    public boolean isInsideName(int offset)
-    {
-        if (attributeName != null)
-            return MXMLData.contains(getNameStart(), getNameEnd(), offset);
-
-        return false;
-    }
-
-    public boolean isInsideStateName(int offset)
-    {
-        if (stateName != null)
-            return MXMLData.contains(getStateStart(), getStateEnd(), offset);
-
-        return false;
-    }
-
-    /**
-     * Does the offset fall inside the bounds of the attribute value?
-     * 
-     * @param offset test offset
-     * @return true if the offset falls within the attribute value
-     */
-    public boolean isInsideValue(int offset)
-    {
-        if (hasValue())
-            return MXMLData.contains(getValueStart() - 1, getValueEnd(), offset);
-
-        return false;
-    }
-
-    @Override
-    public String getPrefix()
-    {
-        String name = getName();
-        int i = name.indexOf(':');
-        return i != -1 ? name.substring(0, i) : null;
-    }
-
-    @Override
-    public String getShortName()
-    {
-        String name = getName();
-        int i = name.indexOf(':');
-        return i != -1 ? name.substring(i + 1) : name;
-    }
-
-    @Override
-    public XMLName getXMLName()
-    {
-        return new XMLName(getURI(), getShortName());
-    }
-
-    @Override
-    public String getURI()
-    {
-        if (uri == null)
-        {
-            //walk up our chain to find the correct uri for our namespace.  first one wins
-            String prefix = getPrefix();
-            if (prefix == null)
-                return null;
-
-            IMXMLTagData lookingAt = parent;
-
-            // For attributes with prefix, parent's parent can be null if
-            // parent is the root tag 
-            while (lookingAt != null && lookingAt.getParent() != null)
-            {
-                PrefixMap depth = lookingAt.getParent().getPrefixMapForData(lookingAt);
-                if (depth != null && depth.containsPrefix(prefix))
-                {
-                    uri = depth.getNamespaceForPrefix(prefix);
-                    break;
-                }
-
-                lookingAt = lookingAt.getParentTag();
-            }
-        }
-
-        return uri;
-    }
-
-    void invalidateURI()
-    {
-        uri = null;
-    }
-
-    @Override
-    public MXMLDialect getMXMLDialect()
-    {
-        return getParent().getParent().getMXMLDialect();
-    }
-
-    @Override
-    public boolean isSpecialAttribute(String name)
-    {
-        String languageURI = getMXMLDialect().getLanguageNamespace();
-
-        return getName().equals(name) && (getPrefix() == null || getURI() == languageURI);
-    }
-
-    /**
-     * Verifies that this attrobite has its source location information set.
-     * <p>
-     * This is used only in asserts.
-     */
-    public boolean verify()
-    {
-        // Verify the source location.
-        assert getSourcePath() != null : "Attribute has null source path: " + toString();
-        assert getStart() != UNKNOWN : "Attribute has unknown start: " + toString();
-        assert getEnd() != UNKNOWN : "Attribute has unknown end: " + toString();
-        assert getLine() != UNKNOWN : "Attribute has unknown line: " + toString();
-        assert getColumn() != UNKNOWN : "Attribute has unknown column: " + toString();
-
-        return true;
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLTagAttributeValue.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLTagAttributeValue.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLTagAttributeValue.java
deleted file mode 100644
index d095df6..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLTagAttributeValue.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import org.apache.flex.compiler.common.SourceLocation;
-
-public abstract class MXMLTagAttributeValue extends SourceLocation implements
-        IMXMLTagAttributeValue
-{
-    /**
-     * Constructor.
-     */
-    public MXMLTagAttributeValue(IMXMLTagAttributeData parent)
-    {
-        this.parent = parent;
-
-        if (parent != null)
-            setSourcePath(parent.getSourcePath());
-    }
-
-    /**
-     * The MXML attribute that contains this unit
-     */
-    private IMXMLTagAttributeData parent;
-
-    //
-    // Other methods
-    //
-
-    public IMXMLTagAttributeData getContainingAttribute()
-    {
-        return parent;
-    }
-}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/mxml/MXMLTagBlobData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/mxml/MXMLTagBlobData.java b/compiler/src/org/apache/flex/compiler/mxml/MXMLTagBlobData.java
deleted file mode 100644
index 06cf0bd..0000000
--- a/compiler/src/org/apache/flex/compiler/mxml/MXMLTagBlobData.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *
- *  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.flex.compiler.mxml;
-
-import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
-
-/**
- * An MXML blob is a large chunk of MXML data that was passed over during
- * tokenization. A blob, for example could be the contents of an fx:Private tag.
- */
-public class MXMLTagBlobData extends MXMLUnitData implements IMXMLTagBlobData
-{
-    /**
-     * Constructor.
-     * 
-     * @param token
-     */
-    MXMLTagBlobData(MXMLToken token)
-    {
-        String text = token.getText();
-        int length = text.length();
-        int pos = 1;
-        while (pos < length)
-        {
-            if (Character.isWhitespace(text.charAt(pos)))
-                break;
-            pos++;
-        }
-        name = text.substring(1, pos - 1);
-
-        setStart(token.getStart());
-        setEnd(token.getEnd());
-        setLine(token.getLine());
-        setColumn(token.getColumn());
-    }
-
-    private String name;
-
-    //
-    // IMXMLTagBlobData implementations
-    //
-
-    @Override
-    public String getName()
-    {
-        return name;
-    }
-}


[4/4] git commit: [flex-falcon] - Moved MXMLData-related classes into internal package

Posted by go...@apache.org.
Moved MXMLData-related classes into internal package


Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/bec3ba00
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/bec3ba00
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/bec3ba00

Branch: refs/heads/develop
Commit: bec3ba0024522bcd14b27960fab667b648deef9b
Parents: 1c7ddc2
Author: Gordon Smith <go...@adobe.com>
Authored: Mon Apr 15 20:01:28 2013 -0700
Committer: Gordon Smith <go...@adobe.com>
Committed: Mon Apr 15 20:01:28 2013 -0700

----------------------------------------------------------------------
 .../compiler/internal/test/FlexJSTestBase.java     |    2 +-
 .../flex/compiler/internal/test/MXMLTestBase.java  |    2 +-
 .../internal/tree/mxml/MXMLNodeBaseTests.java      |    2 +-
 .../flex/compiler/common/PrefixedXMLName.java      |    2 +-
 .../apache/flex/compiler/config/Configuration.java |    2 +-
 .../compiler/internal/caches/MXMLDataCache.java    |    2 +-
 .../flex/compiler/internal/mxml/MXMLData.java      |  980 +++++++++++++
 .../compiler/internal/mxml/MXMLDataManager.java    |    1 -
 .../internal/mxml/MXMLDatabindingData.java         |   58 +
 .../internal/mxml/MXMLDatabindingValue.java        |  113 ++
 .../compiler/internal/mxml/MXMLEntityData.java     |   80 +
 .../compiler/internal/mxml/MXMLEntityValue.java    |  144 ++
 .../internal/mxml/MXMLInstructionData.java         |   97 ++
 .../internal/mxml/MXMLNamespaceAttributeData.java  |   64 +
 .../internal/mxml/MXMLNamespaceMapping.java        |   76 +
 .../compiler/internal/mxml/MXMLStateSplitter.java  |   86 ++
 .../internal/mxml/MXMLTagAttributeData.java        |  637 ++++++++
 .../internal/mxml/MXMLTagAttributeValue.java       |   53 +
 .../compiler/internal/mxml/MXMLTagBlobData.java    |   66 +
 .../flex/compiler/internal/mxml/MXMLTagData.java   | 1135 +++++++++++++++
 .../flex/compiler/internal/mxml/MXMLTextData.java  |  404 +++++
 .../flex/compiler/internal/mxml/MXMLTextValue.java |   82 ++
 .../flex/compiler/internal/mxml/MXMLUnitData.java  |  366 +++++
 .../compiler/internal/mxml/StateDefinition.java    |   93 ++
 .../internal/mxml/StateDefinitionBase.java         |   75 +
 .../internal/mxml/StateGroupDefinition.java        |   84 ++
 .../internal/parsing/mxml/MXMLTagDataDepth.java    |    2 +-
 .../compiler/internal/projects/FlexProject.java    |    2 +-
 .../tree/mxml/MXMLClassDefinitionNode.java         |    4 +-
 .../compiler/internal/tree/mxml/MXMLStateNode.java |    2 +-
 .../org/apache/flex/compiler/mxml/IMXMLData.java   |    1 +
 .../org/apache/flex/compiler/mxml/MXMLData.java    |  977 -------------
 .../flex/compiler/mxml/MXMLDatabindingData.java    |   56 -
 .../flex/compiler/mxml/MXMLDatabindingValue.java   |  111 --
 .../apache/flex/compiler/mxml/MXMLEntityData.java  |   79 -
 .../apache/flex/compiler/mxml/MXMLEntityValue.java |  142 --
 .../flex/compiler/mxml/MXMLInstructionData.java    |   96 --
 .../compiler/mxml/MXMLNamespaceAttributeData.java  |   64 -
 .../flex/compiler/mxml/MXMLNamespaceMapping.java   |   74 -
 .../flex/compiler/mxml/MXMLStateSplitter.java      |   87 --
 .../flex/compiler/mxml/MXMLTagAttributeData.java   |  635 --------
 .../flex/compiler/mxml/MXMLTagAttributeValue.java  |   51 -
 .../apache/flex/compiler/mxml/MXMLTagBlobData.java |   65 -
 .../org/apache/flex/compiler/mxml/MXMLTagData.java | 1130 --------------
 .../apache/flex/compiler/mxml/MXMLTextData.java    |  405 -----
 .../apache/flex/compiler/mxml/MXMLTextValue.java   |   80 -
 .../apache/flex/compiler/mxml/MXMLUnitData.java    |  364 -----
 .../apache/flex/compiler/mxml/StateDefinition.java |   91 --
 .../flex/compiler/mxml/StateDefinitionBase.java    |   74 -
 .../flex/compiler/mxml/StateGroupDefinition.java   |   82 --
 50 files changed, 4705 insertions(+), 4675 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/FlexJSTestBase.java
----------------------------------------------------------------------
diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/FlexJSTestBase.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/FlexJSTestBase.java
index 7b9a421..ce25e18 100644
--- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/FlexJSTestBase.java
+++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/FlexJSTestBase.java
@@ -5,9 +5,9 @@ import java.util.List;
 
 import org.apache.flex.compiler.driver.IBackend;
 import org.apache.flex.compiler.internal.driver.mxml.flexjs.MXMLFlexJSBackend;
+import org.apache.flex.compiler.internal.mxml.MXMLNamespaceMapping;
 import org.apache.flex.compiler.internal.projects.FlexJSProject;
 import org.apache.flex.compiler.mxml.IMXMLNamespaceMapping;
-import org.apache.flex.compiler.mxml.MXMLNamespaceMapping;
 import org.apache.flex.compiler.tree.mxml.IMXMLFileNode;
 import org.apache.flex.compiler.tree.mxml.IMXMLNode;
 import org.apache.flex.utils.FilenameNormalization;

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/MXMLTestBase.java
----------------------------------------------------------------------
diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/MXMLTestBase.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/MXMLTestBase.java
index d0f793a..c8a1041 100644
--- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/MXMLTestBase.java
+++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/MXMLTestBase.java
@@ -5,8 +5,8 @@ import java.util.List;
 
 import org.apache.flex.compiler.driver.IBackend;
 import org.apache.flex.compiler.internal.driver.mxml.MXMLBackend;
+import org.apache.flex.compiler.internal.mxml.MXMLNamespaceMapping;
 import org.apache.flex.compiler.mxml.IMXMLNamespaceMapping;
-import org.apache.flex.compiler.mxml.MXMLNamespaceMapping;
 import org.apache.flex.compiler.tree.mxml.IMXMLFileNode;
 import org.apache.flex.compiler.tree.mxml.IMXMLNode;
 import org.apache.flex.compiler.tree.mxml.IMXMLPropertySpecifierNode;

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler.tests/unit-tests/org/apache/flex/compiler/internal/tree/mxml/MXMLNodeBaseTests.java
----------------------------------------------------------------------
diff --git a/compiler.tests/unit-tests/org/apache/flex/compiler/internal/tree/mxml/MXMLNodeBaseTests.java b/compiler.tests/unit-tests/org/apache/flex/compiler/internal/tree/mxml/MXMLNodeBaseTests.java
index 684c6bc..3a82b9c 100644
--- a/compiler.tests/unit-tests/org/apache/flex/compiler/internal/tree/mxml/MXMLNodeBaseTests.java
+++ b/compiler.tests/unit-tests/org/apache/flex/compiler/internal/tree/mxml/MXMLNodeBaseTests.java
@@ -29,12 +29,12 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import org.apache.flex.compiler.internal.mxml.MXMLNamespaceMapping;
 import org.apache.flex.compiler.internal.projects.FlexProject;
 import org.apache.flex.compiler.internal.projects.FlexProjectConfigurator;
 import org.apache.flex.compiler.internal.units.SourceCompilationUnitFactory;
 import org.apache.flex.compiler.internal.workspaces.Workspace;
 import org.apache.flex.compiler.mxml.IMXMLNamespaceMapping;
-import org.apache.flex.compiler.mxml.MXMLNamespaceMapping;
 import org.apache.flex.compiler.tree.as.IASNode;
 import org.apache.flex.compiler.tree.mxml.IMXMLFileNode;
 import org.apache.flex.compiler.units.ICompilationUnit;

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/common/PrefixedXMLName.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/common/PrefixedXMLName.java b/compiler/src/org/apache/flex/compiler/common/PrefixedXMLName.java
index bce90e9..afcd6f9 100644
--- a/compiler/src/org/apache/flex/compiler/common/PrefixedXMLName.java
+++ b/compiler/src/org/apache/flex/compiler/common/PrefixedXMLName.java
@@ -20,7 +20,7 @@
 package org.apache.flex.compiler.common;
 
 import org.apache.flex.compiler.constants.IMXMLCoreConstants;
-import org.apache.flex.compiler.mxml.MXMLData;
+import org.apache.flex.compiler.internal.mxml.MXMLData;
 
 /**
  * A subclass of XMLName used by clients that need to manipulate the actual

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/config/Configuration.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/config/Configuration.java b/compiler/src/org/apache/flex/compiler/config/Configuration.java
index 362fbd7..6cbb8a7 100644
--- a/compiler/src/org/apache/flex/compiler/config/Configuration.java
+++ b/compiler/src/org/apache/flex/compiler/config/Configuration.java
@@ -79,8 +79,8 @@ import org.apache.flex.compiler.internal.config.annotations.InfiniteArguments;
 import org.apache.flex.compiler.internal.config.annotations.Mapping;
 import org.apache.flex.compiler.internal.config.annotations.SoftPrerequisites;
 import org.apache.flex.compiler.internal.config.localization.LocalizationManager;
+import org.apache.flex.compiler.internal.mxml.MXMLNamespaceMapping;
 import org.apache.flex.compiler.mxml.IMXMLTypeConstants;
-import org.apache.flex.compiler.mxml.MXMLNamespaceMapping;
 import org.apache.flex.compiler.problems.ConfigurationProblem;
 import org.apache.flex.compiler.problems.DeprecatedConfigurationOptionProblem;
 import org.apache.flex.compiler.problems.FlexOnlyConfigurationOptionNotSupported;

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/caches/MXMLDataCache.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/caches/MXMLDataCache.java b/compiler/src/org/apache/flex/compiler/internal/caches/MXMLDataCache.java
index 51ec3f0..7f06a2d 100644
--- a/compiler/src/org/apache/flex/compiler/internal/caches/MXMLDataCache.java
+++ b/compiler/src/org/apache/flex/compiler/internal/caches/MXMLDataCache.java
@@ -26,9 +26,9 @@ import java.util.List;
 import org.apache.commons.io.IOUtils;
 
 import org.apache.flex.compiler.filespecs.IFileSpecification;
+import org.apache.flex.compiler.internal.mxml.MXMLData;
 import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
 import org.apache.flex.compiler.internal.parsing.mxml.MXMLTokenizer;
-import org.apache.flex.compiler.mxml.MXMLData;
 
 /**
  * Concurrent cache for parsed MXML models. The cache is a list of key-value pairs.

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLData.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLData.java
new file mode 100644
index 0000000..9c4c093
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLData.java
@@ -0,0 +1,980 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.apache.commons.io.IOUtils;
+
+import org.apache.flex.compiler.common.MutablePrefixMap;
+import org.apache.flex.compiler.common.PrefixMap;
+import org.apache.flex.compiler.filespecs.FileSpecification;
+import org.apache.flex.compiler.filespecs.IFileSpecification;
+import org.apache.flex.compiler.internal.parsing.mxml.BalancingMXMLProcessor;
+import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
+import org.apache.flex.compiler.internal.parsing.mxml.MXMLTokenizer;
+import org.apache.flex.compiler.internal.parsing.mxml.MXMLUnitDataIterator;
+import org.apache.flex.compiler.mxml.IMXMLData;
+import org.apache.flex.compiler.mxml.IMXMLTagAttributeData;
+import org.apache.flex.compiler.mxml.IMXMLTagData;
+import org.apache.flex.compiler.mxml.IMXMLUnitData;
+import org.apache.flex.compiler.parsing.MXMLTokenTypes;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.problems.SyntaxProblem;
+import org.apache.flex.utils.FastStack;
+import org.apache.flex.utils.FastStack.IFastStackDecorator;
+
+/**
+ * Encapsulation of an MXML file, with individual units for each open tag, close
+ * tag, and block of text.
+ */
+public class MXMLData implements IMXMLData
+{
+
+    private final class TokenizerPayload
+    {
+        private List<MXMLToken> tokens;
+
+        private PrefixMap prefixMap;
+
+        public TokenizerPayload(List<MXMLToken> tokens, PrefixMap prefixMap)
+        {
+            this.tokens = tokens;
+            this.prefixMap = prefixMap;
+        }
+
+        public List<MXMLToken> getMXMLTokens()
+        {
+            return tokens;
+        }
+
+        public PrefixMap getPrefixMap()
+        {
+            return prefixMap;
+        }
+    }
+
+    /**
+     * A cursor represents the offset into the document and the index of the
+     * MXML unit that contains that offset
+     */
+    public class Cursor
+    {
+        /**
+         * Offset into the document
+         */
+        private int offset;
+        /**
+         * Index of the unit that contains that offset
+         */
+        private int unitIndex;
+
+        /**
+         * Constructor (points to beginning of the MXMLData)
+         */
+        public Cursor()
+        {
+            reset();
+        }
+
+        /**
+         * Reset cursor to the beginning of the MXMLData
+         */
+        public void reset()
+        {
+            offset = 0;
+            unitIndex = 0;
+        }
+
+        /**
+         * Set the cursor to a particular offset/unit
+         * 
+         * @param offset offset into the document
+         * @param unitIndex index of the unit containing that offset
+         */
+        public void setCursor(int offset, int unitIndex)
+        {
+            this.offset = offset;
+            this.unitIndex = unitIndex;
+        }
+
+        /**
+         * Get the offset the cursor is pointing to
+         * 
+         * @return current document offset
+         */
+        public int getOffset()
+        {
+            return offset;
+        }
+
+        /**
+         * Get the index of the unit the cursor is pointing to
+         * 
+         * @return current unit index
+         */
+        public int getUnitIndex()
+        {
+            return unitIndex;
+        }
+    }
+
+    private String path = null;
+
+    /**
+     * Individual units for each open tag, close tag, and block of text
+     */
+    private IMXMLUnitData[] units;
+
+    /**
+     * Flag indicating that the tokens underlying this structure were fixed
+     */
+    private boolean wasRepaired;
+
+    private boolean shouldRepair = true;
+
+    /**
+     * This maps {@link IMXMLTagData} objects to their explicit
+     * {@link PrefixMap} if it exist
+     */
+    private HashMap<IMXMLTagData, PrefixMap> nsMap;
+
+    /**
+     * The cursor holds the result of last offset lookup into the MXMLData (see
+     * findNearestUnit, below). When an edit happens that causes the code
+     * coloring engine to recompute everything from the edit position to the end
+     * of the document, it will request MXMLOffsetInformations in order. Having
+     * the cursor speeds this up tremendously.
+     */
+    private Cursor cursor;
+
+    /**
+     * The dialect of MXML being used.
+     */
+    private MXMLDialect mxmlDialect;
+
+    private Collection<ICompilerProblem> problems = new ArrayList<ICompilerProblem>(2);
+
+    /**
+     * Tells us if we are currently processing full MXML, or a fragment
+     */
+    private boolean fullContent = true;
+
+    /**
+     * Constructor
+     * 
+     * @param tokens MXML tokens to build the MXMLData object from
+     * @param map the {@link PrefixMap} for the document, containing the
+     * namespace/prefix mappings
+     */
+    public MXMLData(List<MXMLToken> tokens, PrefixMap map, IFileSpecification fileSpec)
+    {
+        path = fileSpec.getPath();
+        init(tokens, map);
+    }
+
+    public MXMLData(List<MXMLToken> tokens, PrefixMap map, IFileSpecification fileSpec, boolean shouldRepair)
+    {
+        path = fileSpec.getPath();
+        this.shouldRepair = false;
+        init(tokens, map);
+    }
+
+    /**
+     * Constructor
+     * 
+     * @param mxmlText input build our {@link MXMLData} from
+     */
+    public MXMLData(int startOffset, Reader mxmlText, IFileSpecification fileSpec)
+    {
+        TokenizerPayload payload = getTokens(startOffset, mxmlText);
+        path = fileSpec.getPath();
+        init(payload.getMXMLTokens(), payload.getPrefixMap());
+    }
+
+    /**
+     * Constructor
+     * 
+     * @param mxmlText input build our {@link MXMLData} from
+     */
+    public MXMLData(int startOffset, Reader mxmlText, String path, boolean fullContent)
+    {
+        this.fullContent = fullContent;
+        TokenizerPayload payload = getTokens(startOffset, mxmlText);
+        this.path = path;
+        init(payload.getMXMLTokens(), payload.getPrefixMap());
+    }
+
+    public MXMLData(Reader mxmlText, IFileSpecification fileSpec)
+    {
+        this(0, mxmlText, fileSpec);
+    }
+
+    public MXMLData(Reader mxmlText, String path)
+    {
+        // Some clients of MXML data pass in a null IPath for the source path.
+        // Specifically this seems to happen in the code that builds a new
+        // mxml document from a template.
+        this(0, mxmlText, path != null ? path : null, true);
+    }
+
+    /**
+     * Constructor
+     * 
+     * @param specification input build our {@link MXMLData} from
+     */
+    public MXMLData(IFileSpecification specification)
+    {
+        TokenizerPayload payload;
+        try
+        {
+            path = specification.getPath();
+            payload = getTokens(specification.createReader());
+            init(payload.getMXMLTokens(), payload.getPrefixMap());
+        }
+        catch (FileNotFoundException e)
+        {
+            //do nothing
+        }
+    }
+
+    private void init(List<MXMLToken> tokens, PrefixMap map)
+    {
+        mxmlDialect = MXMLDialect.getMXMLDialect(map);
+        initializeFromTokens(tokens);
+    }
+
+    /**
+     * Update the version of the mxml data
+     * 
+     * @param map the prefix map
+     */
+    public void updateMXMLVersion(PrefixMap map)
+    {
+        mxmlDialect = MXMLDialect.getMXMLDialect(map);
+    }
+
+    /**
+     * Get the namespaces defined on the root tag
+     * 
+     * @param reader The reader which would provide the root tag information
+     * @return {@link PrefixMap} for the root tag
+     * @throws IOException error
+     */
+    public static PrefixMap getRootNamespaces(Reader reader) throws IOException
+    {
+        MXMLTokenizer tokenizer = new MXMLTokenizer();
+        try
+        {
+            tokenizer.setReader(reader);
+            return tokenizer.getRootTagPrefixMap().clone();
+        }
+        finally
+        {
+            tokenizer.close();
+        }
+    }
+
+    protected TokenizerPayload getTokens(Reader reader)
+    {
+        return getTokens(0, reader);
+    }
+
+    protected TokenizerPayload getTokens(int startOffset, Reader reader)
+    {
+        List<MXMLToken> tokens = null;
+        MXMLTokenizer tokenizer = new MXMLTokenizer(startOffset);
+        try
+        {
+            tokenizer.setIsRepairing(true);
+            tokens = tokenizer.parseTokens(reader);
+            wasRepaired = tokenizer.tokensWereRepaired();
+            return new TokenizerPayload(tokens, tokenizer.getPrefixMap());
+        }
+        finally
+        {
+            IOUtils.closeQuietly(tokenizer);
+        }
+    }
+
+    @Override
+    public MXMLDialect getMXMLDialect()
+    {
+        return mxmlDialect;
+    }
+
+    @Override
+    public PrefixMap getPrefixMapForData(IMXMLTagData data)
+    {
+        PrefixMap result = nsMap.get(data);
+        if (result != null)
+            return result;
+        if (data.isCloseTag())
+        {
+            IMXMLTagData openTagData = data.getParent().findTagOrSurroundingTagContainingOffset(data.getAbsoluteStart());
+            if (openTagData != null)
+                return nsMap.get(openTagData);
+        }
+        return null;
+    }
+
+    void removePrefixMappingForTag(IMXMLTagData data)
+    {
+        nsMap.remove(data);
+    }
+
+    void clearPrefixMappings()
+    {
+        nsMap.clear();
+    }
+
+    public void setPrefixMappings(HashMap<IMXMLTagData, PrefixMap> map)
+    {
+        if (nsMap != null)
+            nsMap.clear();
+        nsMap = map;
+    }
+
+    public Map<IMXMLTagData, PrefixMap> getTagToPrefixMap()
+    {
+        return nsMap;
+    }
+
+    /**
+     * Returns a collection of prefix->namespaces mappings found within this
+     * document. This map DOES NOT maintain order, and for more fine-grained
+     * information, the getPrefixMap call on individual {@link IMXMLTagData} and
+     * {@link IMXMLTagAttributeData} objects should be called
+     * 
+     * @return a prefix map
+     */
+    public PrefixMap getDocumentPrefixMap()
+    {
+        MutablePrefixMap map = new MutablePrefixMap();
+        for (PrefixMap tagMap : nsMap.values())
+        {
+            assert tagMap != null;
+            map.addAll(tagMap);
+        }
+        return map.toImmutable();
+    }
+
+    /**
+     * Returns the PrefixMap for the root tag of this {@link MXMLData} object
+     * 
+     * @return a {@link PrefixMap} or null
+     */
+    public PrefixMap getRootTagPrefixMap()
+    {
+        IMXMLTagData rootTag = getRootTag();
+        if (rootTag != null)
+        {
+            return nsMap.get(rootTag);
+        }
+        return null;
+    }
+
+    @Override
+    public Collection<ICompilerProblem> getProblems()
+    {
+        return problems;
+    }
+
+    public boolean hasProblems()
+    {
+        return problems.size() > 0;
+    }
+
+    /**
+     * Determines if this data was built from a source that was repaired
+     * 
+     * @return true if the underlying source was repaired
+     */
+    public boolean isDataRepaired()
+    {
+        return wasRepaired;
+    }
+
+    public void setWasRepaired(boolean wasRepaired)
+    {
+        this.wasRepaired = wasRepaired;
+    }
+
+    @Override
+    public IFileSpecification getFileSpecification()
+    {
+        return new FileSpecification(path);
+    }
+
+    @Override
+    public String getPath()
+    {
+        return path;
+    }
+
+    /**
+     * API to change the path after MXMLData creation. An MXMLDocument makes an
+     * MXMLData before the actual location is known.
+     * 
+     * @param path is the absolute path to the backing source file
+     */
+    public void setPath(String path)
+    {
+        this.path = path;
+    }
+
+    /**
+     * Common code from the two constructors
+     * 
+     * @param tokens A list of MXML tokens.
+     */
+    protected void initializeFromTokens(List<MXMLToken> tokens)
+    {
+        cursor = new Cursor();
+        parse(this, tokens, mxmlDialect, problems);
+        cursor.reset();
+    }
+
+    /**
+     * Use the MXML tokens to build MXMLUnitData.
+     * 
+     * @param data the {@link MXMLData} object
+     * @param tokens the list of tokens to build this data from
+     * @param dialect the {@link MXMLDialect} we are working against
+     * @param incremental true if this data is being built incrementally. All
+     * location updates will need to be done outside this element
+     */
+    private void parse(MXMLData data, List<MXMLToken> tokens, MXMLDialect dialect, Collection<ICompilerProblem> problems)
+    {
+        ArrayList<MXMLUnitData> units = new ArrayList<MXMLUnitData>(tokens.size() / 6);
+        nsMap = new HashMap<IMXMLTagData, PrefixMap>();
+        MXMLUnitData unit = null;
+        MXMLToken currentComment = null;
+        FastStack<Integer> depth = new FastStack<Integer>(tokens.size() / 8);
+        IFileSpecification spec = new FileSpecification(data.getPath() != null ? data.getPath() : "");
+        depth.setStackDecorator(new IFastStackDecorator<Integer>() {
+            @Override
+            public Integer decorate(Integer e)
+            {
+                if (e == null)
+                    return -1;
+                return e;
+            }
+
+        });
+        int index = -1;
+        int balancingIndex = 0;
+        depth.push(index);
+        ListIterator<MXMLToken> tokenIterator = tokens.listIterator();
+        BalancingMXMLProcessor processor = new BalancingMXMLProcessor(getFileSpecification(), problems);
+        while (tokenIterator.hasNext())
+        {
+            MXMLToken token = tokenIterator.next();
+            switch (token.getType())
+            {
+                case MXMLTokenTypes.TOKEN_ASDOC_COMMENT:
+                    currentComment = token;
+                    //treat this like text.
+                    unit = new MXMLTextData(token);
+                    units.add(unit);
+                    index++;
+                    if (fullContent)
+                    {
+                        unit.setParentUnitDataIndex(depth.peek());
+                        unit.setLocation(data, index);
+                    }
+                    break;
+                case MXMLTokenTypes.TOKEN_COMMENT:
+                case MXMLTokenTypes.TOKEN_CDATA:
+                case MXMLTokenTypes.TOKEN_WHITESPACE:
+                    //treat this like text.
+                    unit = new MXMLTextData(token);
+                    units.add(unit);
+                    index++;
+                    if (fullContent)
+                    {
+                        unit.setParentUnitDataIndex(depth.peek());
+                        unit.setLocation(data, index);
+                    }
+                    break;
+                case MXMLTokenTypes.TOKEN_OPEN_TAG_START:
+                    unit = new MXMLTagData();
+                    MutablePrefixMap map = ((MXMLTagData)unit).init(this, token, tokenIterator, dialect, spec, problems);
+                    ((MXMLTagData)unit).setCommentToken(currentComment);
+                    currentComment = null;
+                    units.add(unit);
+                    index++;
+                    if (fullContent)
+                    {
+                        unit.setParentUnitDataIndex(depth.peek());
+                        unit.setLocation(data, index);
+                        if (!((MXMLTagData)unit).isEmptyTag())
+                            processor.addOpenTag((MXMLTagData)unit, balancingIndex);
+                    }
+                    if (map != null)
+                        nsMap.put((MXMLTagData)unit, map.toImmutable());
+                    if (!((MXMLTagData)unit).isEmptyTag())
+                    {
+                        depth.push(index);
+                        balancingIndex++;
+                    }
+                    break;
+                case MXMLTokenTypes.TOKEN_CLOSE_TAG_START:
+                    unit = new MXMLTagData();
+                    ((MXMLTagData)unit).init(this, token, tokenIterator, dialect, spec, problems);
+                    ((MXMLTagData)unit).setCommentToken(currentComment);
+                    if (!((MXMLTagData)unit).isEmptyTag())
+                    {
+                        depth.pop();
+                        balancingIndex--;
+                    }
+                    index++;
+                    if (fullContent)
+                    {
+                        unit.setLocation(data, index);
+                        unit.setParentUnitDataIndex(depth.peek());
+                        processor.addCloseTag((MXMLTagData)unit, balancingIndex);
+                    }
+                    currentComment = null;
+                    units.add(unit);
+                    break;
+                case MXMLTokenTypes.TOKEN_TEXT:
+                    unit = new MXMLTextData(token);
+                    units.add(unit);
+                    index++;
+                    if (fullContent)
+                    {
+                        unit.setParentUnitDataIndex(depth.peek());
+                        unit.setLocation(data, index);
+                    }
+                    break;
+                case MXMLTokenTypes.TOKEN_MXML_BLOB:
+                    unit = new MXMLTagBlobData(token);
+                    units.add(unit);
+                    index++;
+                    if (fullContent)
+                    {
+                        unit.setParentUnitDataIndex(depth.peek());
+                        unit.setLocation(data, index);
+                    }
+                    break;
+                case MXMLTokenTypes.TOKEN_DATABINDING_START:
+                    unit = new MXMLDatabindingData(token, tokenIterator);
+                    units.add(unit);
+                    index++;
+                    if (fullContent)
+                    {
+                        unit.setParentUnitDataIndex(depth.peek());
+                        unit.setLocation(data, index);
+                    }
+                    break;
+                case MXMLTokenTypes.TOKEN_PROCESSING_INSTRUCTION:
+                    unit = new MXMLInstructionData(token);
+                    units.add(unit);
+                    index++;
+                    if (fullContent)
+                    {
+                        unit.setParentUnitDataIndex(depth.peek());
+                        unit.setLocation(data, index);
+                    }
+                    break;
+                default:
+                    if (token.isEntity())
+                    {
+                        unit = new MXMLEntityData(token);
+                        units.add(unit);
+                        index++;
+                        if (fullContent)
+                        {
+                            unit.setParentUnitDataIndex(depth.peek());
+                            unit.setLocation(data, index);
+                        }
+                        break;
+                    }
+                    else
+                    {
+                        problems.add(new SyntaxProblem(token));
+                        break;
+                    }
+            }
+        }
+        this.units = units.toArray(new IMXMLUnitData[0]);
+        if (fullContent && shouldRepair)
+        {
+            this.units = processor.balance(this.units, this, nsMap);
+            if (processor.wasRepaired())
+            { //repaired, so let's rebuild our prefix maps and tag depths
+                refreshPositionData();
+            }
+        }
+    }
+
+    /**
+     * Used to rebuild the structures inside of the MXMLData, refreshing prefix
+     * maps, depth and position data. Should only be used after calls that
+     * rebuild the internal structure are called
+     */
+    public void refreshPositionData()
+    {
+        FastStack<Integer> depth = new FastStack<Integer>(units.length / 2);
+        depth.setStackDecorator(new IFastStackDecorator<Integer>() {
+            @Override
+            public Integer decorate(Integer e)
+            {
+                if (e == null)
+                    return -1;
+                return e;
+            }
+
+        });
+        depth.clear();
+        depth.push(-1);
+        for (int i = 0; i < units.length; i++)
+        {
+            if (units[i] instanceof IMXMLTagData)
+            {
+                IMXMLTagData currentTag = (IMXMLTagData)units[i];
+                if (currentTag.isCloseTag())
+                {
+                    if (!currentTag.isEmptyTag())
+                        depth.pop();
+                }
+                ((MXMLTagData)currentTag).setParentUnitDataIndex(depth.peek());
+                ((MXMLTagData)currentTag).setLocation(this, i);
+                if (currentTag.isOpenTag())
+                {
+                    if (!currentTag.isEmptyTag())
+                    {
+                        depth.push(i);
+                    }
+                }
+            }
+            else
+            {
+                ((MXMLUnitData)units[i]).setParentUnitDataIndex(depth.peek());
+                ((MXMLUnitData)units[i]).setLocation(this, i);
+            }
+        }
+    }
+
+    @Override
+    public IMXMLUnitData[] getUnits()
+    {
+        return units;
+    }
+
+    public Iterator<IMXMLUnitData> getUnitIterator()
+    {
+        return new MXMLUnitDataIterator(units);
+    }
+
+    /**
+     * Replace the list of units in this MXMLData.
+     * 
+     * @param units units to add
+     */
+    public void setUnits(IMXMLUnitData[] units)
+    {
+        this.units = units;
+    }
+
+    @Override
+    public IMXMLUnitData getUnit(int i)
+    {
+        if (i < 0 || i >= units.length)
+            return null;
+        return units[i];
+    }
+
+    @Override
+    public int getNumUnits()
+    {
+        return units.length;
+    }
+
+    /**
+     * If the offset is contained within an MXML unit, get that unit. If it's
+     * not, then get the first unit that follows the offset.
+     * 
+     * @param offset test offset
+     * @return unit that contains (or immediately follows) the offset A few
+     * subtleties: In Falcon we have endeavored to preserve the existing
+     * definition of "nearest", so that for a given MXML file, falcon will find
+     * the same "nearest" unit.
+     */
+
+    protected IMXMLUnitData findNearestUnit(int offset)
+    {
+
+        // Use the cursor as a fast search hint. But only if the cursor is at or before the
+        // are of interest.
+        // TODO: do we care that this is not thread safe?
+        int startOffset = 0;
+        if (cursor.getOffset() <= offset)
+            startOffset = cursor.getUnitIndex();
+
+        // Sanity check
+        if (startOffset < 0 || startOffset >= units.length)
+            startOffset = 0;
+
+        // Now iterate though the units and find the first one that is acceptable
+        IMXMLUnitData ret = null;
+        for (int i = startOffset; (i < units.length) && (ret == null); i++)
+        {
+            IMXMLUnitData unit = units[i];
+
+            // unit is a match if it "contains" the offset.
+            // We are using a somewhat bizarre form of "contains" here, in that we are
+            // using getStart() and getConentEnd(). This asymmetric mismatch is for several reasons:
+            //      * it's the only way to match the existing (non-falcon) behavior
+            //      * If our cursor is before the <, we want to match the tag.
+            //              example:     |<foo   >  will find "foo" as the nearest tag.
+            //      So we need to use start here (not content start)
+            //      * If our cursor is between two tags, we want to match the NEXT one, not the previous one
+            //              example:   <bar >|<foo>  should match foo, not bar
+
+            if (MXMLData.contains(unit.getAbsoluteStart(), unit.getContentEnd(), offset))
+            {
+                ret = unit;
+            }
+            // if we find a unit that starts after the offset, then it must
+            // be the "first one after", so return it
+            else if (unit.getAbsoluteStart() >= offset)
+            {
+                ret = unit;
+            }
+        }
+
+        // If we found something, update the cursor for the next search
+        if (ret != null)
+            cursor.setCursor(offset, ret.getIndex());
+        return ret;
+    }
+
+    /**
+     * Get the unit that should be referenced when looking at what tags contain
+     * this offset (i.e. tags that are opened and not closed before this offset)
+     * 
+     * @param offset test offset
+     * @return reference unit for containment searches
+     */
+    public IMXMLUnitData findContainmentReferenceUnit(int offset)
+    {
+        return findNearestUnit(offset);
+    }
+
+    /**
+     * Get the unit that contains this offset
+     * 
+     * @param offset test offset
+     * @return the containing unit (or null if no unit contains this offset)
+     */
+    public IMXMLUnitData findUnitContainingOffset(int offset)
+    {
+        IMXMLUnitData unit = findNearestUnit(offset);
+        if (unit != null && unit.containsOffset(offset))
+            return unit;
+
+        return null;
+    }
+
+    /**
+     * Get the open, close, or empty tag that contains this offset. Note that if
+     * offset is inside a text node, this returns null. If you want the
+     * surrounding tag in that case, use
+     * findTagOrSurroundingTagContainingOffset.
+     * 
+     * @param offset test offset
+     * @return the containing tag (or null, if no tag contains this offset)
+     */
+    public IMXMLTagData findTagContainingOffset(int offset)
+    {
+        IMXMLUnitData unit = findUnitContainingOffset(offset);
+        if (unit != null && unit.isTag())
+            return (IMXMLTagData)unit;
+
+        return null;
+    }
+
+    @Override
+    public IMXMLTagData findTagOrSurroundingTagContainingOffset(int offset)
+    {
+        IMXMLUnitData unit = findUnitContainingOffset(offset);
+        if (unit != null)
+        {
+            if (unit.isTag())
+            {
+                return (IMXMLTagData)unit;
+            }
+            else if (unit.isText())
+            {
+                IMXMLTagData containingTag = unit.getContainingTag(unit.getAbsoluteStart());
+                return containingTag;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Get the open or empty tag whose attribute list contains this offset. A
+     * tag's attribute list extends from after the tag name + first whitespace
+     * until before the closing ">" or "/>".
+     * 
+     * @param offset test offset
+     * @return tag whose attribute list contains this offset (or null, if the
+     * offset isn't in any attribute lists
+     */
+    public IMXMLTagData findAttributeListContainingOffset(int offset)
+    {
+        IMXMLTagData tag = findTagContainingOffset(offset);
+        if (tag != null && tag.isOpenTag())
+            return tag.isOffsetInAttributeList(offset) ? tag : null;
+
+        return null;
+    }
+
+    /**
+     * Test whether the offset is contained within the range from start to end.
+     * This test excludes the start position and includes the end position,
+     * which is how you want things to work for code hints.
+     * 
+     * @param start start of the range (excluded)
+     * @param end end of the range (included)
+     * @param offset test offset
+     * @return true iff the offset is contained in the range
+     */
+    public static boolean contains(int start, int end, int offset)
+    {
+        return start < offset && end >= offset;
+    }
+
+    @Override
+    public IMXMLTagData getRootTag()
+    {
+        int n = units.length;
+        for (int i = 0; i < n; i++)
+        {
+            IMXMLUnitData unit = units[i];
+            if (unit instanceof IMXMLTagData)
+                return (IMXMLTagData)unit;
+        }
+        return null;
+    }
+
+    @Override
+    public int getEnd()
+    {
+        final int n = getNumUnits();
+        return n > 0 ? getUnit(n - 1).getAbsoluteEnd() : 0;
+    }
+
+    public Cursor getCursor()
+    {
+        return cursor;
+    }
+
+    /**
+     * Verifies that all units (plus all attributes on units that are tags) have
+     * their source location information set.
+     * <p>
+     * This is used only in asserts.
+     */
+    public boolean verify()
+    {
+        for (IMXMLUnitData unit : getUnits())
+        {
+            ((MXMLUnitData)unit).verify();
+        }
+
+        return true;
+    }
+
+    // For debugging only.
+    void dumpUnits()
+    {
+        for (IMXMLUnitData unit : getUnits())
+        {
+            System.out.println(((MXMLUnitData)unit).toDumpString());
+        }
+    }
+
+    /**
+     * For debugging only.
+     */
+    @Override
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer();
+
+        IMXMLUnitData[] units = getUnits();
+        int n = units.length;
+        for (int i = 0; i < n; i++)
+        {
+            // Display the unit's index as, for example, [3].
+            sb.append('[');
+            sb.append(i);
+            sb.append(']');
+
+            sb.append(' ');
+
+            // Display the unit's information.
+            sb.append(units[i].toString());
+
+            sb.append('\n');
+        }
+
+        return sb.toString();
+    }
+
+    public static void main(String[] args)
+    {
+        final FileSpecification fileSpec = new FileSpecification(args[0]);
+        final MXMLTokenizer tokenizer = new MXMLTokenizer(fileSpec);
+        List<MXMLToken> tokens = null;
+        try
+        {
+            tokens = tokenizer.parseTokens(fileSpec.createReader());
+
+            // Build tags and attributes from the tokens.
+            final MXMLData mxmlData = new MXMLData(tokens, tokenizer.getPrefixMap(), fileSpec);
+
+            mxmlData.dumpUnits();
+        }
+        catch (FileNotFoundException e)
+        {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        finally
+        {
+            IOUtils.closeQuietly(tokenizer);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLDataManager.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLDataManager.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLDataManager.java
index 3364a26..19cacfa 100644
--- a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLDataManager.java
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLDataManager.java
@@ -22,7 +22,6 @@ package org.apache.flex.compiler.internal.mxml;
 import org.apache.flex.compiler.filespecs.IFileSpecification;
 import org.apache.flex.compiler.internal.caches.MXMLDataCache;
 import org.apache.flex.compiler.mxml.IMXMLDataManager;
-import org.apache.flex.compiler.mxml.MXMLData;
 
 /**
  * The {@code MXMLDataManager} of the {@code IWorkspace}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLDatabindingData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLDatabindingData.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLDatabindingData.java
new file mode 100644
index 0000000..da7f720
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLDatabindingData.java
@@ -0,0 +1,58 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import java.util.ListIterator;
+
+import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
+import org.apache.flex.compiler.mxml.IMXMLDatabindingData;
+import org.apache.flex.compiler.mxml.IMXMLDatabindingValue;
+import org.apache.flex.compiler.parsing.IASToken;
+
+/**
+ * Represents a databinding expression found within content of MXML
+ */
+public class MXMLDatabindingData extends MXMLUnitData implements
+        IMXMLDatabindingData
+{
+    /**
+     * Constructor.
+     */
+    MXMLDatabindingData(MXMLToken start, ListIterator<MXMLToken> iterator)
+    {
+        bindingValue = new MXMLDatabindingValue(start, iterator);
+
+        setOffsets(bindingValue.getAbsoluteStart(), bindingValue.getAbsoluteEnd());
+        setLine(start.getLine());
+        setColumn(start.getColumn());
+    }
+
+    private IMXMLDatabindingValue bindingValue;
+
+    //
+    // IMXMLDatabindingData implementations
+    //
+
+    @Override
+    public IASToken[] getDatabindingContent()
+    {
+        return bindingValue.getDatabindingContent();
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLDatabindingValue.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLDatabindingValue.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLDatabindingValue.java
new file mode 100644
index 0000000..2eee4d1
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLDatabindingValue.java
@@ -0,0 +1,113 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import java.util.ArrayList;
+import java.util.ListIterator;
+
+import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
+import org.apache.flex.compiler.mxml.IMXMLDatabindingValue;
+import org.apache.flex.compiler.mxml.IMXMLTagAttributeData;
+import org.apache.flex.compiler.mxml.IMXMLTextData.TextType;
+import org.apache.flex.compiler.parsing.IASToken;
+
+/**
+ * Represents a databinding expression found within an attribute value
+ */
+public class MXMLDatabindingValue extends MXMLTagAttributeValue implements
+        IMXMLDatabindingValue
+{
+    /**
+     * Constructor.
+     */
+    MXMLDatabindingValue(MXMLToken start, ListIterator<MXMLToken> iterator, IMXMLTagAttributeData parent)
+    {
+        super(parent);
+
+        setStart(start.getStart());
+        setColumn(start.getColumn());
+        setLine(start.getLine());
+
+        while (iterator.hasNext())
+        {
+            MXMLToken token = iterator.next();
+
+            setEnd(token.getEnd());
+
+            if (token.isASToken())
+                tokens.add(token);
+            else
+                break;
+        }
+    }
+
+    /**
+     * Constructor.
+     */
+    MXMLDatabindingValue(MXMLToken start, ListIterator<MXMLToken> iterator)
+    {
+        this(start, iterator, null);
+    }
+
+    private ArrayList<IASToken> tokens = new ArrayList<IASToken>(5);
+
+    //
+    // IMXMLTextData implementations
+    //
+
+    @Override
+    public String getContent()
+    {
+        StringBuilder builder = new StringBuilder();
+
+        final int size = tokens.size();
+        IASToken lastToken = null;
+        for (int i = 0; i < size; i++)
+        {
+            IASToken currentToken = tokens.get(i);
+            if (lastToken != null)
+            {
+                int spaces = currentToken.getStart() - lastToken.getEnd();
+                for (int s = 0; s < spaces; s++)
+                    builder.append(" ");
+            }
+            builder.append(currentToken.getText());
+            lastToken = currentToken;
+        }
+
+        return builder.toString();
+    }
+
+    @Override
+    public TextType getTextType()
+    {
+        return TextType.DATABINDING;
+    }
+
+    //
+    // IMXMLDatabindingData implementations
+    //
+
+    @Override
+    public IASToken[] getDatabindingContent()
+    {
+        return tokens.toArray(new IASToken[0]);
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLEntityData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLEntityData.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLEntityData.java
new file mode 100644
index 0000000..96604cd
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLEntityData.java
@@ -0,0 +1,80 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
+import org.apache.flex.compiler.mxml.IMXMLEntityData;
+
+public class MXMLEntityData extends MXMLTextData implements IMXMLEntityData
+{
+    /**
+     * Constructor.
+     */
+    MXMLEntityData(MXMLToken textToken)
+    {
+        super(textToken);
+
+        type = textToken.getType();
+    }
+
+    private int type;
+
+    //
+    // Object overrides
+    //
+
+    // This method is only used for debugging.
+    @Override
+    public String toString()
+    {
+        String s = getCompilableText();
+
+        s = s.replaceAll("\n", "\\\\n");
+        s = s.replaceAll("\r", "\\\\r");
+        s = s.replaceAll("\t", "\\\\t");
+
+        StringBuilder sb = new StringBuilder();
+        sb.append(type);
+        sb.append(" \"");
+        sb.append(s);
+        sb.append("\"");
+        return sb.toString();
+    }
+
+    //
+    // MXMLTextData overrides
+    // 
+
+    @Override
+    public String getCompilableText()
+    {
+        return getDecodedContent();
+    }
+
+    //
+    // IMXMLEntityData implementations
+    //
+
+    @Override
+    public String getDecodedContent()
+    {
+        return MXMLEntityValue.getDecodedContent(getContents(), type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLEntityValue.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLEntityValue.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLEntityValue.java
new file mode 100644
index 0000000..29d7db7
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLEntityValue.java
@@ -0,0 +1,144 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.flex.compiler.mxml.IMXMLEntityValue;
+import org.apache.flex.compiler.mxml.IMXMLTagAttributeData;
+import org.apache.flex.compiler.mxml.IMXMLTextData.TextType;
+import org.apache.flex.compiler.parsing.IMXMLToken;
+import org.apache.flex.compiler.parsing.MXMLTokenTypes;
+
+public class MXMLEntityValue extends MXMLTagAttributeValue implements
+        IMXMLEntityValue
+{
+    private static final Map<String, String> NAMED_ENTITIES;
+
+    static
+    {
+        NAMED_ENTITIES = new HashMap<String, String>(5);
+
+        NAMED_ENTITIES.put("&amp;", "&");
+        NAMED_ENTITIES.put("&apos;", "'");
+        NAMED_ENTITIES.put("&gt;", ">");
+        NAMED_ENTITIES.put("&lt;", "<");
+        NAMED_ENTITIES.put("&quot;", "\"");
+
+        // TODO HTML 4 supports about 250 named characters
+        // HTML 5 supports about 2500. How many should MXML support
+        // beyond these required 5? What did Xerces/mxmlc support?
+    }
+
+    static final String getDecodedContent(String content, int type)
+    {
+        switch (type)
+        {
+            case MXMLTokenTypes.TOKEN_ENTITY:
+            {
+                return NAMED_ENTITIES.get(content);
+            }
+            case MXMLTokenTypes.TOKEN_HEX_ENTITY:
+            {
+                //thanks to the lexer, we are always: &#x00000;
+                //strip off the first 3 chars and the trailing semicolon
+                return String.valueOf(Integer.parseInt(content.substring(3, content.length() - 1), 16));
+            }
+            case MXMLTokenTypes.TOKEN_DECIMAL_ENTITY:
+            {
+                //thanks to the lexer, we are always: &#\21267;
+                //strip off the first 3 chars and the trailing semicolon
+                return String.valueOf(Integer.parseInt(content.substring(3, content.length() - 1)));
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Constructor.
+     */
+    MXMLEntityValue(IMXMLToken token, IMXMLTagAttributeData parent)
+    {
+        super(parent);
+
+        content = token.getText();
+        type = token.getType();
+
+        setStart(token.getStart());
+        setEnd(token.getEnd());
+        setColumn(token.getColumn());
+        setLine(token.getLine());
+    }
+
+    private final String content;
+
+    /**
+     * Token type which tells us what kind of entity we are dealing with
+     */
+    private final int type;
+
+    //
+    // Object overrides
+    //
+
+    // For debugging only. This format is nice in the Eclipse debugger.
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append("|");
+        sb.append(getContent());
+        sb.append("| ");
+        sb.append(getLine());
+        sb.append(" ");
+        sb.append(getColumn());
+
+        return sb.toString();
+    }
+
+    //
+    // IMXMLTagAttributeValue implementations
+    //
+
+    @Override
+    public String getContent()
+    {
+        return content;
+    }
+
+    @Override
+    public TextType getTextType()
+    {
+        return TextType.ENTITY;
+    }
+
+    //
+    // IMXMLEntityValue implementations
+    //
+
+    @Override
+    public String getDecodedContent()
+    {
+        return getDecodedContent(content, type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLInstructionData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLInstructionData.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLInstructionData.java
new file mode 100644
index 0000000..da2fec4
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLInstructionData.java
@@ -0,0 +1,97 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import org.apache.flex.compiler.mxml.IMXMLInstructionData;
+import org.apache.flex.compiler.parsing.IMXMLToken;
+
+public class MXMLInstructionData extends MXMLUnitData implements
+        IMXMLInstructionData
+{
+    /**
+     * Constructor.
+     */
+    MXMLInstructionData(IMXMLToken token)
+    {
+        instructionText = token.getText();
+
+        setOffsets(token.getStart(), token.getEnd());
+        setColumn(token.getColumn());
+        setLine(token.getLine());
+    }
+
+    private String instructionText;
+
+    //
+    // Object overrides
+    //
+
+    // For debugging only. This format is nice in the Eclipse debugger.
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append('|');
+        sb.append(getInstructionText());
+        sb.append('|');
+
+        sb.append(' ');
+
+        // Display line, column, start, and end as "17:5 160-188".
+        sb.append(super.toString());
+
+        return sb.toString();
+    }
+
+    //
+    // MXMLUnitData overrides
+    //
+
+    // For debugging only. This format is nice in a text file.
+    @Override
+    public String toDumpString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append(super.toDumpString());
+
+        sb.append('\t');
+
+        sb.append('"');
+        sb.append(getInstructionText());
+        sb.append('"');
+
+        return sb.toString();
+    }
+
+    //
+    // IMXMLInstructionData implementations
+    //
+
+    /**
+     * Returns the raw processing instruction. It is up to clients to parse
+     * this.
+     */
+    public String getInstructionText()
+    {
+        return instructionText;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLNamespaceAttributeData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLNamespaceAttributeData.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLNamespaceAttributeData.java
new file mode 100644
index 0000000..4c00837
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLNamespaceAttributeData.java
@@ -0,0 +1,64 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import java.util.Collection;
+import java.util.ListIterator;
+
+import org.apache.flex.compiler.filespecs.IFileSpecification;
+import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
+import org.apache.flex.compiler.mxml.IMXMLNamespaceAttributeData;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+
+/**
+ * Represents an xmlns style namespace import found within the MXML language
+ */
+public class MXMLNamespaceAttributeData extends MXMLTagAttributeData implements
+        IMXMLNamespaceAttributeData
+{
+    /**
+     * Constructor.
+     */
+    MXMLNamespaceAttributeData(MXMLToken nameToken, ListIterator<MXMLToken> tokenIterator, MXMLDialect mxmlDialect, IFileSpecification spec, Collection<ICompilerProblem> problems)
+    {
+        super(nameToken, tokenIterator, mxmlDialect, spec, problems);
+
+        if (attributeName.startsWith("xmlns:"))
+            prefix = attributeName.substring(6);
+    }
+
+    private String prefix = "";
+
+    //
+    // IMXMLNamepsaceAttributeData implementations
+    //
+
+    @Override
+    public String getNamespacePrefix()
+    {
+        return prefix;
+    }
+
+    @Override
+    public String getNamespace()
+    {
+        return getRawValue();
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLNamespaceMapping.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLNamespaceMapping.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLNamespaceMapping.java
new file mode 100644
index 0000000..272fcc7
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLNamespaceMapping.java
@@ -0,0 +1,76 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import org.apache.flex.compiler.mxml.IMXMLNamespaceMapping;
+
+/**
+ * This class stores a MXML-namespace-URI-to-manifest-file mapping.
+ */
+public class MXMLNamespaceMapping implements IMXMLNamespaceMapping
+{
+    public MXMLNamespaceMapping(String uri, String manifestFileName)
+    {
+        assert uri != null;
+        assert manifestFileName != null;
+        this.uri = uri;
+        this.manifestFileName = manifestFileName;
+    }
+
+    private String uri;
+    private String manifestFileName;
+
+    @Override
+    public String getURI()
+    {
+        return uri;
+    }
+
+    @Override
+    public String getManifestFileName()
+    {
+        return manifestFileName;
+    }
+
+    /**
+     * For debugging.
+     * 
+     * @return Debug string representation of this object.
+     */
+    @Override
+    public String toString()
+    {
+        return uri + "->" + manifestFileName;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (obj == this)
+            return true;
+        if (!(obj instanceof MXMLNamespaceMapping))
+            return false;
+        MXMLNamespaceMapping other = (MXMLNamespaceMapping)obj;
+        if (!(uri.equals(other.uri)))
+            return false;
+        return manifestFileName.equals(other.manifestFileName);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLStateSplitter.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLStateSplitter.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLStateSplitter.java
new file mode 100644
index 0000000..3c78c33
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLStateSplitter.java
@@ -0,0 +1,86 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import java.util.Collection;
+
+import org.apache.flex.compiler.filespecs.IFileSpecification;
+import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
+import org.apache.flex.compiler.parsing.IMXMLToken;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.problems.SyntaxProblem;
+
+/**
+ * Simple utility for parsing attribute.state phrases.
+ */
+public class MXMLStateSplitter
+{
+    /**
+     * Constructor.
+     */
+    public MXMLStateSplitter(IMXMLToken nameToken, MXMLDialect mxmlDialect, Collection<ICompilerProblem> problems, IFileSpecification fileSpec)
+    {
+        // Is there a dot in the name?
+        String name = nameToken.getText();
+        int i = name.indexOf('.');
+        if (i >= 0)
+        {
+            if (mxmlDialect != null && mxmlDialect.isEqualToOrAfter(MXMLDialect.MXML_2009))
+            {
+                baseName = name.substring(0, i);
+                stateName = name.substring(i + 1);
+                stateNameOffset = i + 1;
+            }
+            else
+            {
+                stateNameOffset = -1;
+                baseName = name;
+                stateName = null;
+
+                // TODO: I don't think is going to make the right kind of "problem"
+                // This is how the old code worked, but I think it will give a strange message
+                if (problems != null && fileSpec != null)
+                    problems.add(new SyntaxProblem((MXMLToken)nameToken, "Spark state overrides not supported by current language version"));
+            }
+        }
+        else
+        {
+            // no dot.
+            baseName = name;
+            stateNameOffset = -1;
+            stateName = null;
+        }
+    }
+
+    /**
+     * The part of the name before the dot, or the whole name if no dot.
+     */
+    public final String baseName;
+
+    /**
+     * What's after the first dot (state override), or null if no dot
+     */
+    public final String stateName;
+
+    /**
+     * offset of state name, where zero is the first character in the name
+     */
+    public final int stateNameOffset;
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bec3ba00/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagAttributeData.java
----------------------------------------------------------------------
diff --git a/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagAttributeData.java b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagAttributeData.java
new file mode 100644
index 0000000..b921919
--- /dev/null
+++ b/compiler/src/org/apache/flex/compiler/internal/mxml/MXMLTagAttributeData.java
@@ -0,0 +1,637 @@
+/*
+ *
+ *  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.flex.compiler.internal.mxml;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.ListIterator;
+
+import org.apache.flex.compiler.common.ISourceLocation;
+import org.apache.flex.compiler.common.PrefixMap;
+import org.apache.flex.compiler.common.SourceLocation;
+import org.apache.flex.compiler.common.XMLName;
+import org.apache.flex.compiler.filespecs.IFileSpecification;
+import org.apache.flex.compiler.internal.parsing.ISourceFragment;
+import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken;
+import org.apache.flex.compiler.mxml.IMXMLTagAttributeData;
+import org.apache.flex.compiler.mxml.IMXMLTagAttributeValue;
+import org.apache.flex.compiler.mxml.IMXMLTagData;
+import org.apache.flex.compiler.mxml.IMXMLTextValue;
+import org.apache.flex.compiler.parsing.IMXMLToken;
+import org.apache.flex.compiler.parsing.MXMLTokenTypes;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.problems.SyntaxProblem;
+
+/**
+ * Encapsulation of a tag attribute in MXML
+ */
+public class MXMLTagAttributeData extends SourceLocation implements
+        IMXMLTagAttributeData
+{
+    /**
+     * Constructor.
+     */
+    MXMLTagAttributeData(MXMLToken nameToken, ListIterator<MXMLToken> tokenIterator, MXMLDialect mxmlDialect, IFileSpecification spec, Collection<ICompilerProblem> problems)
+    {
+        setStart(nameToken.getStart());
+        setLine(nameToken.getLine());
+        setColumn(nameToken.getColumn());
+        setEnd(nameToken.getEnd());
+
+        // Deal with name if it is of the form name.state
+        MXMLStateSplitter splitState = new MXMLStateSplitter(nameToken, mxmlDialect, problems, spec);
+        attributeName = splitState.baseName;
+        if (splitState.stateName != null)
+        {
+            stateName = splitState.stateName;
+            stateStart = nameToken.getStart() + splitState.stateNameOffset;
+        }
+
+        MXMLToken token = null;
+
+        // Look for "=" token
+        if (tokenIterator.hasNext())
+        {
+            token = tokenIterator.next();
+
+            if (token.getType() != MXMLTokenTypes.TOKEN_EQUALS)
+            {
+                problems.add(new SyntaxProblem(token));
+                // need to restore the token position in the error
+                // case to handle error recovery otherwise the any
+                // trees after this won't be created
+                tokenIterator.previous();
+                return;
+            }
+
+            valueStart = token.getEnd() + 1; //set the attributes start to right after the equals until we have a value
+            valueLine = token.getLine();
+            valueColumn = token.getColumn();
+        }
+
+        // Look for value token
+        ArrayList<IMXMLTagAttributeValue> values = new ArrayList<IMXMLTagAttributeValue>(3);
+        while (tokenIterator.hasNext())
+        {
+            token = tokenIterator.next();
+            if (token.getType() == MXMLTokenTypes.TOKEN_DATABINDING_START)
+            {
+                values.add(new MXMLDatabindingValue(token, tokenIterator, this));
+            }
+            else if (token.getType() == MXMLTokenTypes.TOKEN_STRING)
+            {
+                values.add(new MXMLTextValue(token, this));
+            }
+            else if (token.isEntity())
+            {
+                values.add(new MXMLEntityValue(token, this));
+            }
+            else
+            {
+                if (!MXMLToken.isTagEnd(token.getType()) && token.getType() != MXMLTokenTypes.TOKEN_NAME)
+                {
+                    // if we error out early, push back token - it may be start of next tag
+                    // this is "pre-falcon" repair that was lost
+                    tokenIterator.previous();
+                    problems.add(new SyntaxProblem(token));
+                }
+                else
+                {
+                    tokenIterator.previous();
+                }
+                break;
+            }
+        }
+
+        this.values = values.toArray(new MXMLTagAttributeValue[0]);
+
+        if (this.values.length > 0)
+        {
+            //set the start value
+            IMXMLTagAttributeValue value = this.values[0];
+            valueStart = value.getAbsoluteStart();
+            valueLine = value.getLine();
+            valueColumn = value.getColumn();
+            final int valueEnd = getValueEnd();
+            setEnd(valueEnd + 1);
+        }
+    }
+
+    /**
+     * The MXML tag that contains this attribute
+     */
+    protected IMXMLTagData parent;
+
+    /**
+     * The name of this attribute.
+     */
+    protected String attributeName;
+
+    /**
+     * The offset at which the attribute value starts
+     */
+    protected int valueStart;
+
+    /**
+     * The line on which the attribute value starts
+     */
+    protected int valueLine;
+
+    /**
+     * The column at which the attribute value starts
+     */
+    protected int valueColumn;
+
+    /**
+     * Array of values inside this attribute data.
+     */
+    private IMXMLTagAttributeValue[] values = new IMXMLTagAttributeValue[0];
+
+    /**
+     * The name of this state, if it exists
+     */
+    protected String stateName;
+
+    /**
+     * The offset at which the optional state starts
+     */
+    protected int stateStart;
+
+    /**
+     * The URI specified by this attribute's prefix.
+     */
+    protected String uri;
+
+    //
+    // Object overrides.
+    //
+
+    // For debugging only. This format is nice in the Eclipse debugger.
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+        buildAttributeString(false);
+        return sb.toString();
+    }
+
+    /**
+     * For unit tests only.
+     * 
+     * @return name value and offsets in string form
+     */
+    public String buildAttributeString(boolean skipSrcPath)
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getName());
+        sb.append('=');
+        sb.append('"');
+        sb.append(getRawValue());
+        sb.append('"');
+
+        sb.append(' ');
+
+        // Display line, column, start, and end as "17:5 160-188".
+        if (skipSrcPath)
+            sb.append(getOffsetsString());
+        else
+            sb.append(super.toString());
+        return sb.toString();
+    }
+
+    //
+    // Other methods
+    //
+
+    @Override
+    public IMXMLTagData getParent()
+    {
+        return parent;
+    }
+
+    /**
+     * Sets this attribute's tag.
+     * 
+     * @param parent MXML tag containing this attribute
+     */
+    public void setParent(IMXMLTagData parent)
+    {
+        this.parent = parent;
+        setSourcePath(parent.getSourcePath());
+    }
+
+    /**
+     * Adjust all associated offsets by the adjustment amount
+     * 
+     * @param offsetAdjustment amount to add to offsets
+     */
+    public void adjustOffsets(int offsetAdjustment)
+    {
+        if (attributeName != null)
+        {
+            setStart(getAbsoluteStart() + offsetAdjustment);
+            setEnd(getAbsoluteEnd() + offsetAdjustment);
+        }
+
+        if (hasValue())
+        {
+            valueStart += offsetAdjustment;
+            for (int i = 0; i < values.length; i++)
+            {
+                ((MXMLTagAttributeValue)values[i]).setStart(values[i].getAbsoluteStart() + offsetAdjustment);
+                ((MXMLTagAttributeValue)values[i]).setEnd(values[i].getAbsoluteEnd() + offsetAdjustment);
+            }
+        }
+
+        if (stateName != null)
+            stateStart += offsetAdjustment;
+    }
+
+    @Override
+    public String getName()
+    {
+        return attributeName;
+    }
+
+    @Override
+    public String getStateName()
+    {
+        return stateName != null ? stateName : "";
+    }
+
+    /**
+     * Checks whether this attribute is associated with a state.
+     * 
+     * @return True if a state association exists.
+     */
+    public boolean hasState()
+    {
+        return stateName != null;
+    }
+
+    @Override
+    public boolean hasValue()
+    {
+        return values.length > 0;
+    }
+
+    @Override
+    public IMXMLTagAttributeValue[] getValues()
+    {
+        return values;
+    }
+
+    /**
+     * Get the attribute value as a String (with quotes)
+     * 
+     * @return attribute value (with quotes)
+     */
+    public String getValueWithQuotes()
+    {
+        StringBuilder value = new StringBuilder();
+
+        final int size = values.length;
+        IMXMLTagAttributeValue lastData = null;
+        for (int i = 0; i < size; i++)
+        {
+            IMXMLTagAttributeValue data = values[i];
+            if (lastData != null)
+            {
+                for (int s = 0; s < data.getAbsoluteStart() - lastData.getAbsoluteEnd(); i++)
+                {
+                    value.append(" ");
+                }
+            }
+            value.append(data.getContent());
+        }
+
+        return value.toString();
+    }
+
+    @Override
+    public String getRawValue()
+    {
+        String value = getValueWithQuotes();
+
+        if (value != null && value.length() > 0)
+        {
+            // length can be one in case of invalid data and then the substring() call fails
+            // so, handle it here
+            if (value.charAt(0) == value.charAt(value.length() - 1) && value.length() != 1)
+                value = value.substring(1, value.length() - 1);
+            else
+                value = value.substring(1);
+        }
+
+        return value;
+    }
+
+    @Override
+    public ISourceFragment[] getValueFragments(Collection<ICompilerProblem> problems)
+    {
+        String value = getRawValue();
+        ISourceLocation location = getValueLocation();
+        MXMLDialect mxmlDialect = getMXMLDialect();
+
+        return EntityProcessor.parse(value, location, mxmlDialect, problems);
+    }
+
+    /**
+     * Returns the value of the raw token (without quotes) only if only one
+     * value exists and it is a string value New clients should take into
+     * account that multiple values exist inside of an attribute value
+     * 
+     * @return a value token, or null
+     */
+    // TODO Rename to getValueToken()
+    public IMXMLToken getRawValueToken()
+    {
+        if (hasState() && values.length == 1 && values[0] instanceof IMXMLTextValue)
+        {
+            String value = getRawValue();
+            if (value != null)
+            {
+                return new MXMLToken(MXMLTokenTypes.TOKEN_STRING, getValueStart() + 1, getValueStart() + 1 + value.length(), -1, -1, value);
+            }
+        }
+        return null;
+    }
+
+    public IFileSpecification getSource()
+    {
+        return getParent().getSource();
+    }
+
+    /**
+     * Get this unit's line number.
+     * 
+     * @return end offset
+     */
+    public final int getNameLine()
+    {
+        return getLine();
+    }
+
+    /**
+     * Get this unit's column number.
+     * 
+     * @return end offset
+     */
+    public final int getNameColumn()
+    {
+        return getColumn();
+    }
+
+    public int getNameStart()
+    {
+        return getAbsoluteStart();
+    }
+
+    /**
+     * Get this attribute's name's end offset
+     * 
+     * @return name end offset
+     */
+    public int getNameEnd()
+    {
+        return getAbsoluteStart() + attributeName.length();
+    }
+
+    @Override
+    public int getValueStart()
+    {
+        return hasValue() ? valueStart + 1 : 0;
+    }
+
+    @Override
+    public int getValueEnd()
+    {
+        if (hasValue())
+        {
+            String lastContent = values[values.length - 1].getContent();
+
+            if (lastContent.charAt(0) == lastContent.charAt(lastContent.length() - 1))
+                return getValueStart() + lastContent.length() - 2;
+
+            return getValueStart() + lastContent.length();
+        }
+
+        // If there is no valid "end", then we must return -1. Callers depend on this.
+        // See MXMLTagData.findArttributeContainingOffset for an example
+        return -1;
+    }
+
+    @Override
+    public int getValueLine()
+    {
+        return hasValue() ? valueLine : 0;
+    }
+
+    @Override
+    public int getValueColumn()
+    {
+        return hasValue() ? valueColumn + 1 : 0;
+    }
+
+    @Override
+    public SourceLocation getValueLocation()
+    {
+        return new SourceLocation(getSourcePath(), getValueStart(), getValueEnd(), getValueLine(), getValueColumn());
+    }
+
+    /**
+     * Get this attribute's state start offset if a state token is present other
+     * wise zero.
+     * 
+     * @return state start offset or zero
+     */
+    public int getStateStart()
+    {
+        return stateName != null ? stateStart : 0;
+    }
+
+    /**
+     * Get this attribute's state tokens end offset if a state token is present
+     * other wise zero.
+     * 
+     * @return state start offset or zero
+     */
+    public int getStateEnd()
+    {
+        return stateName != null ? stateStart + stateName.length() : 0;
+    }
+
+    /**
+     * Does this value have a closing quote character?
+     * 
+     * @return true if this value has a closing quote character
+     */
+    protected boolean valueIsWellFormed()
+    {
+        // If there is a value, it came from a string token.  We know (from the
+        // RawTagTokenizer) that this means it starts with a quote character.  If
+        // it ends with the same quote character, it's well formed.
+        if (hasValue())
+        {
+            String lastContent = values[values.length - 1].getContent();
+            return (lastContent.charAt(0) == lastContent.charAt(lastContent.length() - 1));
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns the {@link PrefixMap} that represents all prefix->namespace
+     * mappings are in play on this tag. For example, if a parent tag defines
+     * <code>xmlns:m="falcon"</code> and this tag defines
+     * <code>xmlns:m="eagle"</code> then in this prefix map, m will equal
+     * "eagle"
+     * 
+     * @return a {@link PrefixMap} or null
+     */
+    public PrefixMap getCompositePrefixMap()
+    {
+        return parent.getCompositePrefixMap();
+    }
+
+    /**
+     * Does the offset fall inside the bounds of the attribute name?
+     * 
+     * @param offset test offset
+     * @return true if the offset falls within the attribute name
+     */
+    public boolean isInsideName(int offset)
+    {
+        if (attributeName != null)
+            return MXMLData.contains(getNameStart(), getNameEnd(), offset);
+
+        return false;
+    }
+
+    public boolean isInsideStateName(int offset)
+    {
+        if (stateName != null)
+            return MXMLData.contains(getStateStart(), getStateEnd(), offset);
+
+        return false;
+    }
+
+    /**
+     * Does the offset fall inside the bounds of the attribute value?
+     * 
+     * @param offset test offset
+     * @return true if the offset falls within the attribute value
+     */
+    public boolean isInsideValue(int offset)
+    {
+        if (hasValue())
+            return MXMLData.contains(getValueStart() - 1, getValueEnd(), offset);
+
+        return false;
+    }
+
+    @Override
+    public String getPrefix()
+    {
+        String name = getName();
+        int i = name.indexOf(':');
+        return i != -1 ? name.substring(0, i) : null;
+    }
+
+    @Override
+    public String getShortName()
+    {
+        String name = getName();
+        int i = name.indexOf(':');
+        return i != -1 ? name.substring(i + 1) : name;
+    }
+
+    @Override
+    public XMLName getXMLName()
+    {
+        return new XMLName(getURI(), getShortName());
+    }
+
+    @Override
+    public String getURI()
+    {
+        if (uri == null)
+        {
+            //walk up our chain to find the correct uri for our namespace.  first one wins
+            String prefix = getPrefix();
+            if (prefix == null)
+                return null;
+
+            IMXMLTagData lookingAt = parent;
+
+            // For attributes with prefix, parent's parent can be null if
+            // parent is the root tag 
+            while (lookingAt != null && lookingAt.getParent() != null)
+            {
+                PrefixMap depth = lookingAt.getParent().getPrefixMapForData(lookingAt);
+                if (depth != null && depth.containsPrefix(prefix))
+                {
+                    uri = depth.getNamespaceForPrefix(prefix);
+                    break;
+                }
+
+                lookingAt = lookingAt.getParentTag();
+            }
+        }
+
+        return uri;
+    }
+
+    void invalidateURI()
+    {
+        uri = null;
+    }
+
+    @Override
+    public MXMLDialect getMXMLDialect()
+    {
+        return getParent().getParent().getMXMLDialect();
+    }
+
+    @Override
+    public boolean isSpecialAttribute(String name)
+    {
+        String languageURI = getMXMLDialect().getLanguageNamespace();
+
+        return getName().equals(name) && (getPrefix() == null || getURI() == languageURI);
+    }
+
+    /**
+     * Verifies that this attrobite has its source location information set.
+     * <p>
+     * This is used only in asserts.
+     */
+    public boolean verify()
+    {
+        // Verify the source location.
+        assert getSourcePath() != null : "Attribute has null source path: " + toString();
+        assert getStart() != UNKNOWN : "Attribute has unknown start: " + toString();
+        assert getEnd() != UNKNOWN : "Attribute has unknown end: " + toString();
+        assert getLine() != UNKNOWN : "Attribute has unknown line: " + toString();
+        assert getColumn() != UNKNOWN : "Attribute has unknown column: " + toString();
+
+        return true;
+    }
+}