You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2014/07/22 15:35:56 UTC
[30/51] [partial] - Migrated the directory structure to a more Maven
style structure. - Started migrating the Parser from Antlr2+3 and JFlex to
Antlr4.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/common/ModifiersSet.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/common/ModifiersSet.java b/compiler/src/main/java/org/apache/flex/compiler/common/ModifiersSet.java
new file mode 100644
index 0000000..679b46e
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/common/ModifiersSet.java
@@ -0,0 +1,126 @@
+/*
+ *
+ * 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.common;
+
+import java.util.ArrayList;
+
+import org.apache.flex.compiler.internal.tree.as.ModifierNode;
+
+/**
+ * Map for holding a set of modifiers
+ */
+public class ModifiersSet
+{
+ public ModifiersSet()
+ {
+ }
+
+ private short bits = 0;
+
+ private int start = -1;
+
+ /**
+ * Add another modifier keyword to the collection (and adjust the span
+ * accordingly)
+ *
+ * @param modifier token holding modifier keyword
+ */
+ public void addModifier(ASModifier modifier)
+ {
+ bits |= modifier.getMaskValue();
+ }
+
+ /**
+ * Add another modifier keyword to the collection (and adjust the span
+ * accordingly)
+ *
+ * @param modifier token holding modifier keyword
+ */
+ public void addModifier(ModifierNode modifier)
+ {
+ if (modifier.getModifier() != null)
+ {
+ bits |= modifier.getModifier().getMaskValue();
+ if ((start == -1 || modifier.getAbsoluteStart() < start) && modifier.getAbsoluteStart() > 0)
+ start = modifier.getAbsoluteStart();
+ }
+
+ }
+
+ public int getStart()
+ {
+ return start;
+ }
+
+ public boolean hasModifiers()
+ {
+ return Integer.bitCount(bits) > 0;
+ }
+
+ public ASModifier[] getAllModifiers()
+ {
+ ArrayList<ASModifier> retVal = new ArrayList<ASModifier>(ASModifier.MODIFIERS.length);
+ if (hasModifiers())
+ {
+ for (int i = 0; i < ASModifier.MODIFIERS.length; i++)
+ {
+ if ((bits & ASModifier.MODIFIERS[i].getMaskValue()) == ASModifier.MODIFIERS[i].getMaskValue())
+ {
+ retVal.add(ASModifier.MODIFIERS[i]);
+ }
+ }
+ }
+ return retVal.toArray(new ASModifier[0]);
+ }
+
+ /**
+ * Is the given modifier in the set?
+ *
+ * @return true if the modifier is included in the set
+ */
+ public boolean hasModifier(ASModifier modifier)
+ {
+ return (bits & modifier.getMaskValue()) == modifier.getMaskValue();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ModifiersSet))
+ return false;
+
+ return bits == ((ModifiersSet)obj).bits && start == ((ModifiersSet)obj).start;
+ }
+
+ /**
+ * For debugging only.
+ */
+ @Override
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ for (ASModifier modifier : getAllModifiers())
+ {
+ sb.append(modifier.toString());
+ sb.append(' ');
+ }
+ return sb.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/common/Multiname.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/common/Multiname.java b/compiler/src/main/java/org/apache/flex/compiler/common/Multiname.java
new file mode 100644
index 0000000..2f296f4
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/common/Multiname.java
@@ -0,0 +1,192 @@
+/*
+ *
+ * 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.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.flex.abc.semantics.Name;
+import org.apache.flex.abc.semantics.Namespace;
+import org.apache.flex.abc.semantics.Nsset;
+import org.apache.flex.compiler.definitions.INamespaceDefinition;
+import org.apache.flex.compiler.internal.definitions.NamespaceDefinition;
+import org.apache.flex.compiler.internal.workspaces.Workspace;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.workspaces.IWorkspace;
+
+public final class Multiname
+{
+ /**
+ * Constructs a {@link Multiname} by parsing the specified name string.
+ *
+ * @param project {@link ICompilerProject} whose {@link IWorkspace} is used
+ * to create package namespace definitions.
+ * @param name Either a simple definition name or a dotted qname.
+ * @return A new {@link Multiname} created from information in the specified
+ * name
+ */
+ public static Multiname crackDottedQName(ICompilerProject project, String name)
+ {
+ return crackDottedQName(project, name, false);
+ }
+
+ /**
+ * Constructs a {@link Multiname} by parsing the specified name string.
+ *
+ * @param project {@link ICompilerProject} whose {@link IWorkspace} is used
+ * to create package namespace definitions.
+ * @param name Either a simple definition name or a dotted qname.
+ * @param includeInternal true if package internal namespaces should be in
+ * the namespace set in the multiname.
+ * @return A new {@link Multiname} created from information in the specified
+ * name
+ */
+ public static Multiname crackDottedQName(ICompilerProject project, String name, boolean includeInternal)
+ {
+ Workspace workspace = (Workspace)project.getWorkspace();
+ final Set<INamespaceDefinition> namespaceSet = new HashSet<INamespaceDefinition>(includeInternal ? 2 : 1);
+ if (name != null)
+ {
+ int lastIndexOfDot = name != null ? name.lastIndexOf('.') : -1;
+ if (lastIndexOfDot != -1)
+ {
+ final String definitionName = name.substring(lastIndexOfDot + 1);
+ final String packageName = name.substring(0, lastIndexOfDot);
+ INamespaceDefinition publicPackageNS =
+ workspace.getPackageNamespaceDefinitionCache().get(packageName, false);
+ namespaceSet.add(publicPackageNS);
+ if (includeInternal)
+ {
+ INamespaceDefinition internalPackageNS =
+ workspace.getPackageNamespaceDefinitionCache().get(packageName, true);
+ namespaceSet.add(internalPackageNS);
+ }
+ return new Multiname(namespaceSet, definitionName);
+ }
+ }
+
+ final INamespaceDefinition publicPackageNS = NamespaceDefinition.getPublicNamespaceDefinition();
+ namespaceSet.add(publicPackageNS);
+ if (includeInternal)
+ {
+ INamespaceDefinition internalPackageNS =
+ workspace.getPackageNamespaceDefinitionCache().get("", true);
+ namespaceSet.add(internalPackageNS);
+ }
+ return new Multiname(namespaceSet, name);
+ }
+
+ /**
+ * Returns the package name part of a dotted fully qualified AS3 name. One
+ * thing this method is used for is to compute package names of mxml
+ * classes.
+ *
+ * @param name A dotted fully qualified AS3 name
+ * @return The package name in the specified name.
+ */
+ public static String getPackageNameForQName(String name)
+ {
+ if (name == null)
+ return "";
+ int lastIndexOfDot = name.lastIndexOf('.');
+ if (lastIndexOfDot != -1)
+ return name.substring(0, lastIndexOfDot);
+ return "";
+ }
+
+ /**
+ * Returns the base name part of a dotted fully qualified AS3 name.
+ *
+ * @param name A dotted fully qualified AS3 name
+ * @return The base name in the specified name.
+ */
+ public static String getBaseNameForQName(String name)
+ {
+ int lastIndexOfDot = name.lastIndexOf('.');
+ if (lastIndexOfDot != -1)
+ return name.substring(lastIndexOfDot + 1);
+ return name;
+ }
+
+ public static Multiname create(Set<INamespaceDefinition> nsset, String baseName)
+ {
+ return new Multiname(nsset, baseName);
+ }
+
+ public Multiname(Set<INamespaceDefinition> namespaceSet, String baseName)
+ {
+ this.namespaceSet = namespaceSet;
+ this.baseName = baseName;
+ }
+
+ private final Set<INamespaceDefinition> namespaceSet;
+ private final String baseName;
+
+ /**
+ * Gets the namespace set for this {@link Multiname}.
+ * @return The namespace set for this {@link Multiname}.
+ */
+ public Set<INamespaceDefinition> getNamespaceSet()
+ {
+ return namespaceSet;
+ }
+
+ /**
+ * Gets the base name for this {@link Multiname}.
+ * @return The base name set for this {@link Multiname}.
+ */
+ public String getBaseName()
+ {
+ return baseName;
+ }
+
+ /**
+ * Gets the AET name for this {@link Multiname}.
+ * @return A {@link Name} object.
+ */
+ public Name getMName()
+ {
+ Set<Namespace> namespaces = new HashSet<Namespace>(namespaceSet.size());
+ for ( INamespaceDefinition ns: namespaceSet )
+ namespaces.add( ((NamespaceDefinition)ns).getAETNamespace() );
+
+ return new Name(new Nsset(namespaces), getBaseName());
+ }
+
+ /**
+ * For debugging only.
+ * <p>
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append('[');
+ for (INamespaceDefinition namespace : namespaceSet)
+ {
+ builder.append(namespace.toString());
+ builder.append(", ");
+ }
+ builder.append("]::");
+ builder.append(baseName);
+ return builder.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/common/MutablePrefixMap.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/common/MutablePrefixMap.java b/compiler/src/main/java/org/apache/flex/compiler/common/MutablePrefixMap.java
new file mode 100644
index 0000000..53c224b
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/common/MutablePrefixMap.java
@@ -0,0 +1,162 @@
+/*
+ *
+ * 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.common;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * This is a mutable version of a {@link PrefixMap} that allows additions and
+ * removals of namespaces
+ */
+public class MutablePrefixMap extends PrefixMap
+{
+ public MutablePrefixMap()
+ {
+ super();
+ }
+
+ public MutablePrefixMap(PrefixMap map)
+ {
+ PrefixMap clone = map.clone();
+ namespaceToPrefixMap = new HashMap<String, Set<String>>(clone.namespaceToPrefixMap);
+ prefixes = new HashSet<String>(clone.prefixes);
+ }
+
+ public MutablePrefixMap(String ns, String prefix)
+ {
+ add(ns, prefix);
+ }
+
+ /**
+ * Creates an immutable version of this prefix map
+ *
+ * @return an immutable prefix map
+ */
+ public PrefixMap toImmutable()
+ {
+ PrefixMap map = new PrefixMap();
+ map.namespaceToPrefixMap = new HashMap<String, Set<String>>(namespaceToPrefixMap);
+ map.prefixes = new HashSet<String>(prefixes);
+ return map;
+ }
+
+ /**
+ * Add a prefix and its uri to the map.
+ *
+ * @param prefix A namespace prefix string, such as <code>"fx"</code>.
+ * @param uri The corresponding namespace URI, such as <code>http://ns.adobe.com/mxml/2009</code>.
+ */
+ public void add(String prefix, String uri)
+ {
+ add(prefix, uri, false);
+ }
+
+ /**
+ * Adds a prefix and uri to this namespace map.
+ *
+ * @param prefix the prefix to add
+ * @param uri the namespace to add for the given prefix
+ * @param onlyIfUnique If the mapping is not unique, it will be added only
+ * if this flag is set to false. A mapping is considering unique if a prefix
+ * has not already been defined
+ */
+ public void add(String prefix, String uri, boolean onlyIfUnique)
+ {
+ Set<String> list = namespaceToPrefixMap.get(uri);
+ if (list == null)
+ {
+ list = new LinkedHashSet<String>(1);
+ namespaceToPrefixMap.put(uri, list);
+ }
+ if (onlyIfUnique)
+ {
+ if (!list.contains(prefix))
+ {
+ list.add(prefix);
+ prefixes.add(prefix);
+ }
+ }
+ else
+ {
+ list.add(prefix);
+ prefixes.add(prefix);
+ }
+ }
+
+ /**
+ * Adds all information from one {@link PrefixMap} to another
+ *
+ * @param map the {@link PrefixMap} where our data is coming from
+ * @param onlyIfUnique If the mapping is not unique, it will be added only
+ * if this flag is set to false. A mapping is considering unique if a prefix
+ * has not already been defined
+ */
+ public void addAll(PrefixMap map, boolean onlyIfUnique)
+ {
+ Iterator<String> it = map.namespaceToPrefixMap.keySet().iterator();
+ while (it.hasNext())
+ {
+ String ns = it.next();
+ Iterator<String> sItr = map.namespaceToPrefixMap.get(ns).iterator();
+ while (sItr.hasNext())
+ {
+ add(sItr.next(), ns, onlyIfUnique);
+ }
+ }
+ }
+
+ /**
+ * Adds all information from one {@link PrefixMap} to another
+ *
+ * @param map the {@link PrefixMap} where our data is coming from
+ */
+ public void addAll(PrefixMap map)
+ {
+ Iterator<String> it = map.namespaceToPrefixMap.keySet().iterator();
+ while (it.hasNext())
+ {
+ String ns = it.next();
+ Iterator<String> sItr = map.namespaceToPrefixMap.get(ns).iterator();
+ while (sItr.hasNext())
+ {
+ add(sItr.next(), ns);
+ }
+ }
+ }
+
+ public void remove(String prefix)
+ {
+ Iterator<String> it = namespaceToPrefixMap.keySet().iterator();
+ while (it.hasNext())
+ {
+ String next = it.next();
+ Set<String> set = namespaceToPrefixMap.get(next);
+ if (set != null)
+ {
+ set.remove(prefix);
+ }
+ }
+ prefixes.remove(prefix);
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/common/NodeReference.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/common/NodeReference.java b/compiler/src/main/java/org/apache/flex/compiler/common/NodeReference.java
new file mode 100644
index 0000000..b1c7da9
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/common/NodeReference.java
@@ -0,0 +1,242 @@
+/*
+ *
+ * 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.common;
+
+import org.apache.flex.compiler.filespecs.IFileSpecification;
+import org.apache.flex.compiler.internal.scopes.ASFileScope;
+import org.apache.flex.compiler.internal.scopes.ASScope;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.workspaces.IWorkspace;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Helper class to abstract the details of how we get back to Nodes from Definitions and NamespaceReferences.
+ *
+ * This class holds a WeakRef to the IASNode, and is able to regenerate the IASNode if needed after it has been collected.
+ */
+public class NodeReference
+{
+ /**
+ * Construct a NodeReference to the given node
+ * @param node the node to references
+ */
+ public NodeReference(IASNode node)
+ {
+ absoluteStart = node.getAbsoluteStart();
+ nodeRef = new WeakReference<IASNode>(node);
+ fileSpec = node.getFileSpecification();
+ }
+
+ /**
+ * Construct a NodeReference to a node in the specified file at the
+ * specified offset. This constructor is used from the MXMLScopeBuilder,
+ * where we only have temporary tree nodes.
+ *
+ * @param containingFileSpec File that contains the node this reference
+ * refers to.
+ * @param absoluteStart The offset at which the node this reference refers to
+ * starts.
+ */
+ public NodeReference(IFileSpecification containingFileSpec, int absoluteStart)
+ {
+ this.absoluteStart = absoluteStart;
+ nodeRef = new WeakReference<IASNode>(null);
+ fileSpec = containingFileSpec;
+ }
+
+ // The node that produced this definition, if this definition came from source.
+ // This is stored as a weak reference so that symbol tables don't prevent ASTs
+ // from being garbage-collected.
+ // If the reference is lost, getNode() restores it by using
+ // 'fileSpec' to reparse the AST and 'start' to find the correct node in that AST.
+ private WeakReference<IASNode> nodeRef;
+
+ // The {@link IFileSpecification} from which this definition came.
+ private IFileSpecification fileSpec;
+
+ // The absolute starting offset of this definition.
+ private int absoluteStart = ISourceLocation.UNKNOWN;
+
+ /**
+ * Get the file spec for this Node
+ */
+ public IFileSpecification getFileSpecification()
+ {
+ return fileSpec;
+ }
+
+ /**
+ * Get the start offset for the node
+ */
+ public int getAbsoluteStart()
+ {
+ return absoluteStart;
+ }
+
+ /**
+ * Finds the node closest to the root whose start offset is exactly the
+ * specified offset.
+ * <p>
+ * This method differs from
+ * {@link IASNode#getContainingNode(int)}
+ * in that it considers the start of a node to be contained by the node.
+ *
+ * @param root Node to start the search at.
+ * @param absoluteOffset Start offset of the node to find.
+ * @return The node closest to the specified root node whose start offset is
+ * the specified offset, or null if no such node exists.
+ */
+ private static IASNode findNode(IASNode root, int absoluteOffset)
+ {
+ IASNode current = root;
+ assert root.getAbsoluteEnd() >= absoluteOffset;
+
+ // These two nested while loops rely on the fact that
+ // the start and end offset of a node enclose the start
+ // offset of the nodes first child and the end offset of the
+ // nodes last child.
+ while ((current != null) && (current.getAbsoluteStart() != absoluteOffset))
+ {
+ assert current.getAbsoluteStart() < absoluteOffset;
+ assert current.getAbsoluteEnd() >= absoluteOffset;
+ int childCount = current.getChildCount();
+ int i = 0;
+ IASNode next = null;
+ // This inner loop computes which child node to descend to.
+ // We want to descend to the child contains the
+ // start offset. The child nodes are always in file order,
+ // and their source ranges do not overlap.
+ while ((i < childCount) && (next == null))
+ {
+ IASNode currChild = current.getChild(i);
+ // Once we find a child that ends after the offset
+ // we are looking for, descend to that child.
+ if (currChild != null && currChild.getAbsoluteEnd() >= absoluteOffset)
+ next = currChild;
+ ++i;
+ }
+ current = next;
+ }
+ return current;
+ }
+
+ /**
+ * Get a strong reference to the Node. If necessary this will reparse the file to find the correct Node.
+ * This method may return null, such as when document is so malformed
+ * that we can't produce a file node for it.
+ * (Note that MXMLScopeBuilder can produce definitions with NodeReferences into a malformed document.)
+ * @param workspace the Workspace to use to parse the file
+ * @param scope the containing scope of the definition we want the node for - this is used
+ * to find the ASFileScope it's contained in to reconnect the definitions and Nodes
+ * if the file needs to be reparsed
+ */
+ public IASNode getNode(IWorkspace workspace, ASScope scope)
+ {
+ // If this definition didn't come from source, return null.
+ if (fileSpec == null || absoluteStart == ISourceLocation.UNKNOWN)
+ return null;
+
+ // If the definition node is still weakly attached, return it.
+ IASNode node = nodeRef.get();
+ if (node != null)
+ return node;
+
+
+ // Reparse the file from which this definition came
+ // to create a new AST.
+ // TODO Detect whether the file has changed since the definition was created.
+ if( workspace != null )
+ {
+ ASScope s = scope;
+ ASFileScope fileScope = null;
+ // Get the file scope, and reconnect the AST to the definitions/scopes that
+ // already exist
+ while( s != null )
+ {
+ if( s instanceof ASFileScope )
+ {
+ fileScope = (ASFileScope)s;
+ }
+ s = s.getContainingScope();
+ }
+ if( fileScope != null) {
+
+ // Grab the lock
+ synchronized (this)
+ {
+ // Check again in case another thread already updated the node reference
+ node = nodeRef.get();
+ if(node != null )
+ return node;
+
+ // Get the file node from the file scope
+ IASNode fileNode = fileScope.getNode();
+
+ if (fileNode != null)
+ {
+ // Find the node that produced this definition,
+ // using the starting offset stored in this definition.
+ node = findNode(fileNode, absoluteStart);
+
+ // Reattach a weak reference to the node.
+ nodeRef = new WeakReference<IASNode>(node);
+ }
+ }
+ }
+ }
+ return node;
+ }
+
+ /**
+ * Get the node from the underlying weak reference. This will not do any parsing
+ * or any other work to recover the Node if it has been collected
+ * @return the IASNode this reference refers to, or null if the Node no longer exists
+ */
+ public IASNode getNodeIfExists()
+ {
+ return nodeRef != null ? nodeRef.get() : null;
+ }
+
+ /**
+ * Explicitly re-connect this node reference to the specified node.
+ * @param node The {@link IASNode} to re-connect this node reference to.
+ */
+ public void reconnectNode(IASNode node)
+ {
+ assert node.contains(absoluteStart);
+ nodeRef = new WeakReference<IASNode>(node);
+ }
+
+ /**
+ * static that represents no NodeReference (e.g. for defs that came from an ABC)
+ */
+ public static NodeReference noReference = new NodeReference();
+
+ /**
+ * Private ctor only used by the noReference instance.
+ */
+ private NodeReference()
+ {
+ this.nodeRef = null;
+ this.fileSpec = null;
+ this.absoluteStart = ISourceLocation.UNKNOWN;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/common/PrefixMap.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/common/PrefixMap.java b/compiler/src/main/java/org/apache/flex/compiler/common/PrefixMap.java
new file mode 100644
index 0000000..85c70a4
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/common/PrefixMap.java
@@ -0,0 +1,212 @@
+/*
+ *
+ * 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.common;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * A PrefixMap contains a collection of prefix to namespace mappings found in
+ * MXML documents. This object is <b>immutable</b>. For a mutable version, look
+ * at {@link MutablePrefixMap}
+ */
+public class PrefixMap implements Cloneable
+{
+ public PrefixMap()
+ {
+ super();
+ }
+
+ public PrefixMap(PrefixMap map)
+ {
+ namespaceToPrefixMap = new HashMap<String, Set<String>>(map.namespaceToPrefixMap);
+ prefixes = new HashSet<String>(map.prefixes);
+ }
+
+ protected HashMap<String, Set<String>> namespaceToPrefixMap = new HashMap<String, Set<String>>();
+
+ protected HashSet<String> prefixes = new HashSet<String>();
+
+ @Override
+ public PrefixMap clone()
+ {
+ PrefixMap result = new PrefixMap();
+
+ result.namespaceToPrefixMap = new HashMap<String, Set<String>>();
+
+ // copy values here as there is an internal set involved here
+ Iterator<String> it = namespaceToPrefixMap.keySet().iterator();
+ while (it.hasNext())
+ {
+ String next = it.next();
+ Set<String> set = namespaceToPrefixMap.get(next);
+ if (set != null)
+ {
+ Set<String> prefixSet = new LinkedHashSet<String>();
+ Iterator<String> setIt = set.iterator();
+ while (setIt.hasNext())
+ {
+ String prefix = setIt.next();
+ prefixSet.add(prefix);
+ }
+ result.namespaceToPrefixMap.put(next, prefixSet);
+ }
+ }
+
+ result.prefixes = new HashSet<String>(prefixes);
+ return result;
+ }
+
+ /**
+ * Creates a mutable copy of this PrefixMap, based on its values
+ *
+ * @return a mutable version of this prefix map
+ */
+ public MutablePrefixMap toMutable()
+ {
+ return new MutablePrefixMap(this.clone());
+ }
+
+ /**
+ * Returns the namespace for the given prefix. The first prefix found in the
+ * map will win
+ *
+ * @param prefix the prefix to find out namespace for
+ * @return a namespace URI or null
+ */
+ public String getNamespaceForPrefix(String prefix)
+ {
+ Iterator<String> it = namespaceToPrefixMap.keySet().iterator();
+ while (it.hasNext())
+ {
+ String next = it.next();
+ Set<String> set = namespaceToPrefixMap.get(next);
+ if (set != null)
+ {
+ if (set.contains(prefix))
+ {
+ return next;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns true if the given prefix exists somewhere in this map
+ *
+ * @param prefix A namespace prefix string such as <code>"fx"</code>.
+ */
+ public boolean containsPrefix(String prefix)
+ {
+ return prefixes.contains(prefix);
+ }
+
+ /**
+ * Checks whether the map contains a reference to the given namespace.
+ *
+ * @param namespace URI of a namespace.
+ */
+ public boolean containsNamespace(String namespace)
+ {
+ return namespaceToPrefixMap.containsKey(namespace);
+ }
+
+ /**
+ * Returns all the prefixes known to this map.
+ */
+ public String[] getAllPrefixes()
+ {
+ return prefixes.toArray(new String[0]);
+ }
+
+ /**
+ * Returns all the namespace URIs known to this map
+ */
+ public String[] getAllNamespaces()
+ {
+ return namespaceToPrefixMap.keySet().toArray(new String[0]);
+ }
+
+ /**
+ * Returns the prefix that is used to reference the given namespace URI.
+ *
+ * @param uri A namespace URI such as <code>"http://ns.adobe.com/mxml/2009"</code>.
+ */
+ public String[] getPrefixesForNamespace(String uri)
+ {
+ Set<String> set = namespaceToPrefixMap.get(uri);
+ if (set != null)
+ return set.toArray(new String[0]);
+ return new String[0];
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof PrefixMap)
+ {
+ PrefixMap right = (PrefixMap)obj;
+ if (right.namespaceToPrefixMap.size() != namespaceToPrefixMap.size())
+ {
+ return false;
+ }
+ if (right.prefixes.size() != prefixes.size())
+ {
+ return false;
+ }
+
+ Iterator<String> prefixItr = right.prefixes.iterator();
+ while (prefixItr.hasNext())
+ {
+ if (!prefixes.contains(prefixItr.next()))
+ {
+ return false;
+ }
+ }
+
+ Iterator<String> nsItr = right.namespaceToPrefixMap.keySet().iterator();
+ while (nsItr.hasNext())
+ {
+ String next = nsItr.next();
+ Set<String> set = namespaceToPrefixMap.get(next);
+ Set<String> rSet = right.namespaceToPrefixMap.get(next);
+ if (set == null)
+ {
+ return false;
+ }
+ Iterator<String> pItr = rSet.iterator();
+ while (pItr.hasNext())
+ {
+ if (!set.contains(pItr.next()))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ return super.equals(obj);
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/common/PrefixedXMLName.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/common/PrefixedXMLName.java b/compiler/src/main/java/org/apache/flex/compiler/common/PrefixedXMLName.java
new file mode 100644
index 0000000..afcd6f9
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/common/PrefixedXMLName.java
@@ -0,0 +1,185 @@
+/*
+ *
+ * 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.common;
+
+import org.apache.flex.compiler.constants.IMXMLCoreConstants;
+import org.apache.flex.compiler.internal.mxml.MXMLData;
+
+/**
+ * A subclass of XMLName used by clients that need to manipulate the actual
+ * syntactic form of the element name (including its prefix). Most clients of
+ * codemodel/mxmlmodel should use XMLName instead, and rely on the full
+ * namespace URI; the specific namespace prefix that's on a given element in a
+ * given document has no meaning outside that document. In particular, no one
+ * should ever assume that "mx:" is the prefix being used for the Flex
+ * namespace.
+ */
+public class PrefixedXMLName extends XMLName
+{
+ /**
+ * Constructor This version will parse the containingDocument on the fly (or
+ * use an existing parse, if there is already one in the MXMLDataProvider).
+ *
+ * @param rawName full element name (e.g. mx:Button)
+ * @param mxmlData MXMLData containing the element
+ */
+ public PrefixedXMLName(String rawName, MXMLData mxmlData)
+ {
+ name = splitName(rawName);
+ assert name != null;
+ xmlNamespace = resolvePrefix(prefix, mxmlData);
+ if (xmlNamespace == null)
+ xmlNamespace = IMXMLCoreConstants.emptyString;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param rawName full element name (e.g. mx:Button)
+ * @param prefixMap map of element prefixes to XML namespaces
+ */
+ public PrefixedXMLName(String rawName, PrefixMap prefixMap)
+ {
+ name = splitName(rawName);
+ assert name != null;
+ xmlNamespace = prefixMap.getNamespaceForPrefix(prefix);
+ if (xmlNamespace == null)
+ xmlNamespace = IMXMLCoreConstants.emptyString;
+ }
+
+ public PrefixedXMLName(String rawName, String uri)
+ {
+ name = splitName(rawName);
+ xmlNamespace = uri;
+ }
+
+ /**
+ * Constructor used when we already know the specific namespace and prefix
+ * being used by a particular instance of an XML element.
+ *
+ * @param xmlNamespace the namespace URI
+ * @param name the unprefixed element name
+ * @param rawName the prefixed element name (e.g. mx:Button)
+ */
+ public PrefixedXMLName(String xmlNamespace, String name, String rawName)
+ {
+ splitName(rawName);
+ this.name = name;
+ assert name != null;
+ this.xmlNamespace = (xmlNamespace == null) ? IMXMLCoreConstants.emptyString : xmlNamespace;
+ }
+
+ /**
+ * Prefix from the intial lookup. Only accurate when in the context of a
+ * document.
+ */
+ private String prefix;
+
+ /**
+ * Cached value of the full name. It's ok to cache this because we can't
+ * ever change the name, namespace, or prefix after this object is
+ * constructed.
+ */
+ private String prefixedName;
+
+ /**
+ * Split a raw tag name (e.g. mx:Button) into a prefix (mx) and short name
+ * (Button). The prefix is stored in fPrefix, and the short name is
+ * returned. For use in constructors.
+ *
+ * @param rawName full element name (e.g. mx:Button)
+ * @return short name (e.g. Button)
+ */
+ private String splitName(String rawName)
+ {
+ String name;
+
+ if (rawName == null)
+ {
+ prefix = IMXMLCoreConstants.emptyString;
+ return IMXMLCoreConstants.emptyString;
+ }
+
+ int colonIndex = rawName.indexOf(IMXMLCoreConstants.colon);
+ if (colonIndex > -1)
+ {
+ prefix = rawName.substring(0, colonIndex);
+ name = rawName.substring(colonIndex + 1);
+ }
+ else
+ {
+ prefix = IMXMLCoreConstants.emptyString;
+ name = rawName;
+ }
+
+ return name;
+ }
+
+ /**
+ * Determine which XML namespace is appropriate for the given prefix in the
+ * given document
+ *
+ * @param prefix element prefix
+ * @param mxmlData containing MXMLData
+ * @return XML namespaces
+ */
+ protected String resolvePrefix(String prefix, MXMLData mxmlData)
+ {
+ return resolvePrefix(prefix, mxmlData.getRootTagPrefixMap());
+ }
+
+ /**
+ * Determine which XML namespace is appropriate for the given prefix in the
+ * given prefix map
+ */
+ protected String resolvePrefix(String prefix, PrefixMap prefixMap)
+ {
+ if (prefixMap.containsPrefix(prefix))
+ return prefixMap.getNamespaceForPrefix(prefix);
+
+ return IMXMLCoreConstants.emptyString;
+ }
+
+ /**
+ * Get the prefix for the element
+ *
+ * @return the prefix
+ */
+ public String getPrefix()
+ {
+ return prefix;
+ }
+
+ /**
+ * Return the prefixed version of the name.
+ */
+ public String getPrefixedName()
+ {
+ if (prefixedName != null)
+ return prefixedName;
+
+ if (prefix != null && !prefix.equals(IMXMLCoreConstants.emptyString))
+ prefixedName = (prefix + IMXMLCoreConstants.colon + getName()).intern();
+ else
+ prefixedName = getName();
+
+ return prefixedName;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/common/RecursionGuard.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/common/RecursionGuard.java b/compiler/src/main/java/org/apache/flex/compiler/common/RecursionGuard.java
new file mode 100644
index 0000000..dc82334
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/common/RecursionGuard.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.common;
+
+import java.util.HashSet;
+
+import org.apache.flex.compiler.definitions.IDefinition;
+
+/**
+ * Recursion guard that can be used throughout code model to make sure we don't infinitely recurse when
+ * performing type lookups, etc. Since user code is not guaranteed to follow language rules, these are very important to avoid loops.
+ */
+public class RecursionGuard {
+
+ public HashSet<IDefinition> visitedDefinitions;
+ public boolean foundLoop = false;
+
+ public RecursionGuard()
+ {
+ visitedDefinitions = null;
+ }
+
+ public RecursionGuard( RecursionGuard other)
+ {
+ this.foundLoop = other.foundLoop;
+ if (other.visitedDefinitions != null)
+ this.visitedDefinitions = new HashSet<IDefinition>(other.visitedDefinitions);
+ }
+
+ /**
+ * Create a guard that is pre-populated with the passed in definition. the definition will be considered visited
+ * @param initialDefinition the {@link IDefinition} to mark as visited
+ */
+ public RecursionGuard(IDefinition initialDefinition)
+ {
+ visitedDefinitions = new HashSet<IDefinition>();
+ visitedDefinitions.add(initialDefinition);
+ }
+
+ public boolean isLoop(IDefinition target) {
+ if(visitedDefinitions == null)
+ visitedDefinitions = new HashSet<IDefinition>();
+ if (visitedDefinitions.add(target))
+ return false;
+
+ foundLoop = true;
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/common/SourceLocation.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/common/SourceLocation.java b/compiler/src/main/java/org/apache/flex/compiler/common/SourceLocation.java
new file mode 100644
index 0000000..88998b7
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/common/SourceLocation.java
@@ -0,0 +1,361 @@
+/*
+ *
+ * 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.common;
+
+import org.apache.flex.utils.FilenameNormalization;
+
+/**
+ * Common class to store file/location information across all source types
+ * such as AS, CSS etc
+ */
+public class SourceLocation implements ISourceLocation
+{
+ /**
+ * Constructor for a known source location.
+ */
+ public SourceLocation(String sourcePath, int start, int end, int line, int column)
+ {
+ this.sourcePath = sourcePath;
+ this.start = start;
+ this.end = end;
+ this.line = line;
+ this.column = column;
+ }
+
+ /**
+ * Copy Constructor for a known source location.
+ */
+ public SourceLocation(ISourceLocation location)
+ {
+ this(location.getSourcePath(),
+ location.getStart(),
+ location.getEnd(),
+ location.getLine(),
+ location.getColumn());
+ }
+
+ /**
+ * Constructor for an unknown source location.
+ */
+ public SourceLocation()
+ {
+ this(null, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN);
+ }
+
+ /**
+ * Source path.
+ */
+ private String sourcePath;
+
+ /**
+ * Zero-based starting offset.
+ * <p>
+ * This class does not distinguish between local and absolute offsets,
+ * but subclasses may. If so, they should store the absolute starting
+ * offset in this field and use it to compute the local starting offset.
+ */
+ private int start;
+
+ /**
+ * Zero-based ending offset.
+ * <p>
+ * This class does not distinguish between local and absolute offsets,
+ * but subclasses may. If so, they should store the absolute ending
+ * offset in this field and use it to compute the local ending offset.
+ */
+ private int end;
+
+ /**
+ * Zero-based line number.
+ * Corresponds to start, not end.
+ */
+ private int line;
+
+ /**
+ * Zero-based column number.
+ * Corresponds to start, not end.
+ */
+ private int column;
+
+ /**
+ * Copies source location information from another instance
+ * into this instance.
+ */
+ public final void setSourceLocation(ISourceLocation src)
+ {
+ assert src != null : "source location can't be null";
+
+ this.start = src.getStart();
+ this.end = src.getEnd();
+ this.line = src.getLine();
+ this.column = src.getColumn();
+ this.sourcePath = src.getSourcePath();
+ }
+
+ /**
+ * @return The local start offset
+ */
+ @Override
+ public int getStart()
+ {
+ assert start >= 0 || start == UNKNOWN : "Invalid value for start: " + start;
+ return start;
+ }
+
+ /**
+ * @return The absolute start offset.
+ */
+ @Override
+ public int getAbsoluteStart()
+ {
+ assert start >= 0 || start == UNKNOWN : "Invalid value for start: " + start;
+ return start;
+ }
+
+ /**
+ * @return The absolute end offset.
+ */
+ @Override
+ public int getAbsoluteEnd()
+ {
+ assert end >= 0 || end == UNKNOWN : "Invalid value for end: " + end;
+ return end;
+ }
+
+ /**
+ * Set the absolute offset where this node starts.
+ */
+ public void setStart(int start)
+ {
+ if (start != UNKNOWN)
+ this.start = start;
+ }
+
+ /**
+ * @return The local end offset.
+ */
+ @Override
+ public int getEnd()
+ {
+ assert end >= 0 || end == UNKNOWN : "Invalid value for end: " + end;
+ return end;
+ }
+
+ /**
+ * Set the absolute offset where this node ends.
+ */
+ public void setEnd(int end)
+ {
+ if (end != UNKNOWN)
+ this.end = end;
+ }
+
+ /**
+ * Get the line number where this node starts.
+ * Line numbers start at 0, not 1.
+ * @return The line number
+ */
+ @Override
+ public int getLine()
+ {
+ assert line >= 0 || line == UNKNOWN : "Invalid value for line: " + line;
+ return line;
+ }
+
+ /**
+ * Set the line number where this node starts.
+ * Column numbers start at 0, not 1.
+ * @param line The line number
+ */
+ public void setLine(int line)
+ {
+ if (line != UNKNOWN)
+ this.line = line;
+ }
+
+ /**
+ * Get the column number where this node starts.
+ * @return The column number
+ */
+ @Override
+ public int getColumn()
+ {
+ assert column >= 0 || column == UNKNOWN : "Invalid value for column: " + column;
+ return column;
+ }
+
+ /**
+ * Set the column number where this node starts.
+ * @param column The column number
+ */
+ public void setColumn(int column)
+ {
+ if (column != UNKNOWN)
+ this.column = column;
+ }
+
+ /**
+ * Get the source path for this node.
+ * @return The source path for this node
+ */
+ @Override
+ public final String getSourcePath()
+ {
+ // null means the source is unknown.
+ // "" means the source is a buffer that hasn't yet been saved to a file.
+ // Something like "framework.swc:defaults.css" means the source is a file inside a SWC.
+ // TODO Shouldn't the part before the colon be normalized?
+ // Anything else should be a normalized path to a source file.
+ assert sourcePath == null ||
+ sourcePath.isEmpty() ||
+ sourcePath.contains(".swc:") ||
+ FilenameNormalization.isNormalized(sourcePath) :
+ "Invalid value for sourcePath: " + sourcePath;
+ return sourcePath;
+ }
+
+ /**
+ * Set the source path of the node.
+ * @param sourcePath The source path
+ */
+ public final void setSourcePath(String sourcePath)
+ {
+ this.sourcePath = sourcePath;
+ }
+
+ /**
+ * Displays line, column, start, end, and sourcepath in a format such as
+ * <pre>
+ * "17:5 160-188 C:\test.as"
+ * </pre>
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getLineColumnString());
+ sb.append(getOffsetsString());
+ sb.append(getSourcePathString());
+ return sb.toString();
+ }
+
+ /**
+ * Displays Line and Column numbers
+ */
+ protected String getLineColumnString()
+ {
+ StringBuilder sb = new StringBuilder();
+ int line = getLine();
+ if (line != UNKNOWN)
+ sb.append(line);
+ else
+ sb.append('?');
+ sb.append(':');
+ int column = getColumn();
+ if (column != UNKNOWN)
+ sb.append(column);
+ else
+ sb.append('?');
+
+ sb.append(' ');
+ return sb.toString();
+ }
+
+ /**
+ * Displays sourcepath
+ *
+ */
+ protected String getSourcePathString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(' ');
+
+ String sourcePath = getSourcePath();
+ if (sourcePath != null)
+ sb.append(sourcePath);
+ else
+ sb.append('?');
+ return sb.toString();
+ }
+
+ /**
+ * Displays line, column, start, end
+ *
+ */
+ protected String getOffsetsString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("loc: ");
+ int start = getStart();
+ if (start != UNKNOWN)
+ sb.append(start);
+ else
+ sb.append('?');
+ sb.append('-');
+ int end = getEnd();
+ if (end != UNKNOWN)
+ sb.append(end);
+ else
+ sb.append('?');
+
+ sb.append(' ');
+
+ sb.append("abs: ");
+ int absoluteStart = getAbsoluteStart();
+ if (absoluteStart != UNKNOWN)
+ sb.append(absoluteStart);
+ else
+ sb.append('?');
+ sb.append('-');
+ int absoluteEnd = getAbsoluteEnd();
+ if (absoluteEnd != UNKNOWN)
+ sb.append(absoluteEnd);
+ else
+ sb.append('?');
+ return sb.toString();
+ }
+
+
+ /**
+ * Span the location range from {@code start} to {@code end}.
+ *
+ * @param start Start location.
+ * @param end End location.
+ */
+ public final void span(ISourceLocation start, ISourceLocation end)
+ {
+ setSourcePath(start.getSourcePath());
+ setStart(start.getStart());
+ setEnd(end.getEnd());
+ setLine(start.getLine());
+ setColumn(start.getColumn());
+ }
+
+ /**
+ * Span the location range from {@code start} to {@code end}.
+ *
+ * @param location The location
+ */
+ public final void span(ISourceLocation location)
+ {
+ if (location != null)
+ setSourceLocation(location);
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/common/VersionInfo.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/common/VersionInfo.java b/compiler/src/main/java/org/apache/flex/compiler/common/VersionInfo.java
new file mode 100644
index 0000000..3c1c2af
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/common/VersionInfo.java
@@ -0,0 +1,379 @@
+/*
+ *
+ * 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.common;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.apache.flex.utils.Trace;
+
+/**
+ * A helper class for querying build number, Flex version, and library
+ * version information.
+ */
+public class VersionInfo
+{
+ public static final String FLEX_MAJOR_VERSION = "4";
+ public static final String FLEX_MINOR_VERSION = "7";
+ public static final String FLEX_NANO_VERSION = "0";
+
+ /**
+ * Lib version is the "version" of the SWC format. Major number changes represent big (although not
+ * by definition incompatble) changes, such as bytecode format revs. Minor number changes are intended
+ * to represent easy-to-support modifications. The only universal rule is that the compiler will warn
+ * when a "future" major version is found in a SWC that's being read in.
+ *
+ * It's expected that incompatible changes will arise. Ad-hoc guard code will be added to implement those
+ * dividing lines. The way the code is currently laid out, these would probably be implemented in SWC.read(),
+ * but in any case they should be finable by looking at the callers of VersionInfo.getLibVersion().
+ *
+ * <li>
+ * Version 1.2: Add <keep-as3-metadata> container to catalog.xml to perserve metadata
+ * </li>
+ * <li>
+ * Version 1.1: Add <digest> container to catalog xml for cross-domain rsls support.
+ * Add "signatureChecksum" attribute to "script" element.
+ *
+ * </li>
+ * <li>
+ * Version 1.0: Initial version.
+ * </li>
+ *
+ */
+ public static final String LIB_VERSION_1_0 = "1.0";
+ public static final String LIB_VERSION_1_1 = "1.1";
+ public static final String LIB_VERSION_1_2 = "1.2";
+
+ public static final String LIB_MAJOR_VERSION = "1";
+ public static final String LIB_MINOR_VERSION = "2";
+
+ //
+ // Strings used for the rdf/xml tag written into a SWF via the Metadata
+ // tag.
+ //
+ /**
+ * Element containing version information.
+ */
+ public static final String COMPILER_ELEMENT = "compiler";
+
+ /**
+ * Product name of the compiler that compiled the SWF.
+ */
+ public static final String COMPILER_NAME_ATTRIBUTE = "name";
+
+ /**
+ * Version of the compiler that compiled the SWF.
+ */
+ public static final String COMPILER_VERSION_ATTRIBUTE = "version";
+
+ /**
+ * Build number of the compiler that compiled the SWF.
+ */
+ public static final String COMPILER_BUILD_ATTRIBUTE = "build";
+
+ /**
+ * Namespace of the "compiler" element.
+ */
+ public static final String COMPILER_NAMESPACE_URI = "http://ns.adobe.com/asc/2012";
+
+ /**
+ * Prefix of the the compiler's namespace URI.
+ */
+ public static final String COMPILER_NAMESPACE_PREFIX = "asc";
+
+ //Cache this info as it should not change during the time class is loaded
+ static String BUILD_MESSAGE;
+ static String BUILD_NUMBER_STRING;
+ static String FLEX_VERSION_NUMBER;
+ static String LIB_VERSION_NUMBER;
+ static boolean useFlexMessageFormat;
+
+ public static String buildMessage()
+ {
+ if (BUILD_MESSAGE == null)
+ {
+ try
+ {
+ //Ensure we've parsed build info
+ getBuild();
+
+ // If there is a version.properties file then build the message
+ // the way flex used to. Otherwise use the information from
+ // the compiler's jar file.
+ if (useFlexMessageFormat)
+ {
+ String buildNum = BUILD_NUMBER_STRING;
+ BUILD_MESSAGE = "Version " + FLEX_MAJOR_VERSION + "." + FLEX_MINOR_VERSION +
+ "." + FLEX_NANO_VERSION + " build " + buildNum;
+ }
+ else
+ {
+ BUILD_MESSAGE = "Version " + getCompilerVersion() + " build " +
+ getCompilerBuild();
+ }
+
+ }
+ catch (Throwable t)
+ {
+ if (Trace.error)
+ {
+ t.printStackTrace();
+ }
+ BUILD_MESSAGE = "build information unavailable";
+ }
+ }
+
+ return BUILD_MESSAGE;
+ }
+
+ public static String getBuild()
+ {
+ if (BUILD_NUMBER_STRING == null)
+ {
+ BUILD_NUMBER_STRING = "";
+
+ InputStream in = null;
+ try
+ {
+ Properties p = new Properties();
+ in = VersionInfo.class.getResourceAsStream("version.properties");
+
+ String build = "";
+ if (in != null)
+ {
+ p.load(in);
+ build = p.getProperty("build");
+ useFlexMessageFormat = true;
+ }
+ else
+ {
+ build = VersionInfo.class.getPackage().getImplementationVersion();
+ }
+
+ if ((build != null) && (! build.equals("")))
+ {
+ // In open source builds the build number has changed from an
+ // integer to a string of dot separated integers.
+ // for example: 191195 -> 3.0.0.97
+ int dot_index = build.lastIndexOf(".");
+ if (dot_index != -1)
+ {
+ build = build.substring(dot_index + 1);
+ }
+ BUILD_NUMBER_STRING = build;
+ }
+ }
+ catch (Throwable t)
+ {
+ if (Trace.error)
+ {
+ t.printStackTrace();
+ }
+ }
+ finally
+ {
+ if (in != null)
+ {
+ try
+ {
+ in.close();
+ }
+ catch (IOException ex)
+ {
+ }
+ }
+ }
+ }
+
+ return BUILD_NUMBER_STRING;
+ }
+
+ /**
+ * Get the build number as a long.
+ *
+ * @return build number as a long, 0 if the build number was not available.
+ */
+ public static long getBuildLong()
+ {
+ long buildNum = 0;
+ try
+ {
+ buildNum = Long.parseLong(getBuild());
+ }
+ catch (NumberFormatException e)
+ {
+ // ignore, return value will be 0.
+ }
+
+ return buildNum;
+ }
+
+ public static String getFlexVersion()
+ {
+ if (FLEX_VERSION_NUMBER == null)
+ {
+ FLEX_VERSION_NUMBER = FLEX_MAJOR_VERSION + "." + FLEX_MINOR_VERSION +
+ "." + FLEX_NANO_VERSION;
+ }
+ return FLEX_VERSION_NUMBER;
+ }
+
+ public static String getLibVersion()
+ {
+ if (LIB_VERSION_NUMBER == null)
+ {
+ LIB_VERSION_NUMBER = LIB_MAJOR_VERSION + "." + LIB_MINOR_VERSION;
+ }
+ return LIB_VERSION_NUMBER;
+ }
+
+ /**
+ * The name of the compiler.
+ *
+ * @return name of the compiler.
+ */
+ public static String getCompilerName()
+ {
+ String title = VersionInfo.class.getPackage().getImplementationTitle();
+ return title != null ? title : "";
+ }
+
+ /**
+ * The version of the compiler. Includes the major, minor, and nano versions
+ * separates by dots. For example, 4.7.0. The compiler version number comes
+ * from information from the manifest.mf file where as the Flex version
+ * number is hard-coded in this file.
+ *
+ * @return version of the compiler.
+ */
+ public static String getCompilerVersion()
+ {
+ String version = VersionInfo.class.getPackage().getImplementationVersion();
+
+ if ((version != null) && (!version.equals("")))
+ {
+ // remove the build number from the version.
+ // major.minor.nano.build -> major.minor.nano
+ int dot_index = version.lastIndexOf(".");
+ if (dot_index != -1)
+ version = version.substring(0, dot_index);
+ }
+
+ return version != null ? version : "";
+ }
+
+ /**
+ * The build number of the compiler. Can be converted to a long. The
+ * compiler build number comes from information from the manifest.mf file
+ * where as the Flex build number comes from a properties file.
+ *
+ * @return the build number of the compiler.
+ */
+ public static String getCompilerBuild()
+ {
+ String build = VersionInfo.class.getPackage().getImplementationVersion();
+
+ if ((build != null) && (! build.equals("")))
+ {
+ // Change major.minor.nano.build -> build
+ int dot_index = build.lastIndexOf(".");
+ if (dot_index != -1)
+ build = build.substring(dot_index + 1);
+ }
+
+ return build != null ? build : "";
+ }
+
+ /**
+ *
+ * @param swcLibVersion - library version to compare with the current library version.
+ * @param compareMajorVersion - if true, compare only the major versions. Otherwise compare
+ * both major and minor versions.
+ * @return true if the given library version is greater than the compiled in library version.
+ */
+ public static boolean IsNewerLibVersion(String swcLibVersion, boolean compareMajorVersion)
+ {
+ return compareVersions(swcLibVersion, getLibVersion(), compareMajorVersion) > 0;
+ }
+
+
+ /**
+ * Compare two version strings that are in at "Major.minor" format.
+ *
+ * Examples) "1.0", "1.1"
+ *
+ * @param version1 first version
+ * @param version2 second version
+ * @param compareMajorVersion compare only the major versions, disregarding the minor version.
+ *
+ * @return zero if the versions are equal
+ * less than zero if version1 is less than version2
+ * greater than zero if version1 is greater than version2
+ */
+ public static int compareVersions(String version1, String version2, boolean compareMajorVersion)
+ {
+ // C: change this implementation if the lib version changes from the a.b format to the a.b.c. format.
+ // Obviously, a.b.c is not a number!
+
+ double v1 = 0, v2 = 0;
+
+ try
+ {
+ v1 = Double.parseDouble(version1);
+ }
+ catch (NumberFormatException ex)
+ {
+ if (Trace.error)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ try
+ {
+ v2 = Double.parseDouble(version2);
+ }
+ catch (NumberFormatException ex)
+ {
+ if (Trace.error)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ if (compareMajorVersion)
+ {
+ v1 = Math.floor(v1);
+ v2 = Math.floor(v2);
+ }
+
+ if (v1 == v2)
+ {
+ return 0;
+ }
+ else if (v1 < v2)
+ {
+ return -1;
+ }
+
+ return 1;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/common/XMLName.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/common/XMLName.java b/compiler/src/main/java/org/apache/flex/compiler/common/XMLName.java
new file mode 100644
index 0000000..5ab2eb5
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/common/XMLName.java
@@ -0,0 +1,147 @@
+/*
+ *
+ * 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.common;
+
+/**
+ * Qualified element name (XML namespace and local name). This does not contain
+ * information about the namespace prefix that may be used on the element in a
+ * given document-- that's a transient syntactic detail; clients should rely on
+ * the namespace URI to disambiguate elements.
+ */
+public class XMLName implements Comparable<XMLName>
+{
+ public static final XMLName NULL_NAME = new XMLName("");
+
+ /**
+ * Constructor
+ *
+ * @param xmlNamespace XML namespace for element (e.g.
+ * http://foo.adobe.com/2006/mxml or shared.*)
+ * @param name element name without prefix (e.g. Button)
+ */
+ public XMLName(String xmlNamespace, String name)
+ {
+ this.name = (name == null) ? "" : name;
+ this.xmlNamespace = (xmlNamespace == null) ? "" : xmlNamespace;
+ }
+
+ /**
+ * Constructor that assumes an empty namespace.
+ *
+ * @param name element name without prefix (e.g. Button)
+ */
+ public XMLName(String name)
+ {
+ this.name = (name == null) ? "" : name;
+ this.xmlNamespace = "";
+ }
+
+ /**
+ * Constructor for use by our subclasses
+ */
+ protected XMLName()
+ {
+ // This stub function is the default constructor, only used by our subclasses.
+ }
+
+ /**
+ * XML namespace
+ */
+ protected String xmlNamespace;
+
+ /**
+ * Local element name (unqualified)
+ */
+ protected String name;
+
+ /**
+ * Get the element's unqualified local name
+ *
+ * @return local name
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Get the XML namespace for the element (e.g.
+ * http://foo.adobe.com/2006/mxml or shared.*)
+ *
+ * @return XML namespace
+ */
+ public String getXMLNamespace()
+ {
+ return xmlNamespace;
+ }
+
+ /**
+ * Dump the XMLName as a string (for debugging)
+ *
+ * @return string representation of the name
+ */
+ @Override
+ public String toString()
+ {
+ String retVal = null;
+ if (!xmlNamespace.equals(""))
+ retVal = xmlNamespace + ":" + name;
+ else
+ retVal = name;
+
+ return retVal;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ // use better hashcode impl to avoid all the unneeded recomputation and storage of additional field
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((xmlNamespace == null) ? 0 : xmlNamespace.hashCode());
+ return result;
+ }
+
+ /**
+ * Does this element name equal the one that's passed in?
+ *
+ * @return true if the element names are equal
+ */
+ @Override
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof XMLName))
+ return false;
+ XMLName xmlOther = (XMLName)other;
+
+ // All the code in XMLName and PrefixedXMLName makes sure that fName and fXMLNamespace
+ // are both non-null, so we don't have to check for null here.
+ if (!name.equals(xmlOther.name))
+ return false;
+ return xmlNamespace.equals(xmlOther.xmlNamespace);
+ }
+
+ @Override
+ public int compareTo(XMLName o)
+ {
+ return toString().compareTo(o.toString());
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/common/package.html
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/common/package.html b/compiler/src/main/java/org/apache/flex/compiler/common/package.html
new file mode 100644
index 0000000..fefcf66
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/common/package.html
@@ -0,0 +1,27 @@
+<!--
+
+ 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.
+
+-->
+
+<html>
+<body>
+
+This package contains miscellaneous classes and interfaces
+used by other compiler packages.
+
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/config/ApplicationDomainTarget.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/config/ApplicationDomainTarget.java b/compiler/src/main/java/org/apache/flex/compiler/config/ApplicationDomainTarget.java
new file mode 100644
index 0000000..de0555d
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/config/ApplicationDomainTarget.java
@@ -0,0 +1,79 @@
+/*
+ *
+ * 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.config;
+
+/**
+ * The ApplicationDomainTarget enum defines the possible values of the
+ * application domain an RSL can be loaded into at runtime.
+ * The application domain target specifies a relative application
+ * domain that is resolved at runtime.
+ */
+public enum ApplicationDomainTarget
+{
+ /**
+ * The default behavior for RSL loading is to load an RSL as high in
+ * the parent module factory chain as possible. In order to load an RSL
+ * into a parent module factory, that module factory must have been
+ * compiled with that RSL specified in the compiler options. If no parent module
+ * factories were compiled with that RSL , then the RSL will be loaded in
+ * the application domain of the module factory loading the RSL.
+ */
+ DEFAULT("default"),
+
+ /**
+ * The application domain of the current module factory.
+ */
+ CURRENT("current"),
+
+ /**
+ * The application domain of the parent module factory.
+ */
+ PARENT("parent"),
+
+ /**
+ * The application domain of the top-level module factory.
+ */
+ TOP_LEVEL("top-level");
+
+
+ private String applicationDomainValue;
+
+ /**
+ * Not for public consumption.
+ *
+ * @param applicationDomainValue
+ */
+ private ApplicationDomainTarget( String applicationDomainValue )
+ {
+ this.applicationDomainValue = applicationDomainValue;
+ }
+
+ /**
+ * The value the Flex runtime understands.
+ *
+ * @return The {@link String} value of the enum.
+ */
+ public String getApplicationDomainValue()
+ {
+ return applicationDomainValue;
+ }
+
+
+}