flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cd...@apache.org
Subject [03/51] [partial] - Migrated the directory structure to a more Maven style structure. - Started migrating the Parser from Antlr2+3 and JFlex to Antlr4.
Date Tue, 22 Jul 2014 13:35:29 GMT
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/CSSReducer.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/CSSReducer.java b/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/CSSReducer.java
new file mode 100644
index 0000000..db63df3
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/CSSReducer.java
@@ -0,0 +1,691 @@
+/*
+ *
+ *  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.css.codegen;
+
+import static org.apache.flex.compiler.internal.as.codegen.ABCGeneratingReducer.pushNumericConstant;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.Vector;
+
+import org.apache.flex.abc.ABCConstants;
+import org.apache.flex.abc.instructionlist.InstructionList;
+import org.apache.flex.abc.semantics.MethodBodyInfo;
+import org.apache.flex.abc.semantics.MethodInfo;
+import org.apache.flex.abc.semantics.Name;
+import org.apache.flex.abc.visitors.IABCVisitor;
+import org.apache.flex.abc.visitors.IMethodBodyVisitor;
+import org.apache.flex.abc.visitors.IMethodVisitor;
+import org.apache.flex.abc.visitors.ITraitsVisitor;
+import org.apache.flex.compiler.constants.IASLanguageConstants;
+import org.apache.flex.compiler.css.ICSSDocument;
+import org.apache.flex.compiler.css.ICSSNode;
+import org.apache.flex.compiler.css.ICSSProperty;
+import org.apache.flex.compiler.css.ICSSPropertyValue;
+import org.apache.flex.compiler.css.ICSSRule;
+import org.apache.flex.compiler.css.ICSSSelector;
+import org.apache.flex.compiler.css.ICSSSelectorCondition;
+import org.apache.flex.compiler.definitions.references.IResolvedQualifiersReference;
+import org.apache.flex.compiler.definitions.references.ReferenceFactory;
+import org.apache.flex.compiler.internal.as.codegen.LexicalScope;
+import org.apache.flex.compiler.internal.css.CSSArrayPropertyValue;
+import org.apache.flex.compiler.internal.css.CSSColorPropertyValue;
+import org.apache.flex.compiler.internal.css.CSSFunctionCallPropertyValue;
+import org.apache.flex.compiler.internal.css.CSSKeywordPropertyValue;
+import org.apache.flex.compiler.internal.css.CSSNumberPropertyValue;
+import org.apache.flex.compiler.internal.css.CSSRgbColorPropertyValue;
+import org.apache.flex.compiler.internal.css.CSSRule;
+import org.apache.flex.compiler.internal.css.CSSSelector;
+import org.apache.flex.compiler.internal.css.CSSStringPropertyValue;
+import org.apache.flex.compiler.internal.css.codegen.Pair.InstructionListAndClosure;
+import org.apache.flex.compiler.internal.css.codegen.Pair.InstructionListAndString;
+import org.apache.flex.compiler.internal.css.codegen.Pair.PairOfInstructionLists;
+import org.apache.flex.compiler.internal.css.semantics.CSSSemanticAnalyzer;
+import org.apache.flex.compiler.internal.units.EmbedCompilationUnit;
+import org.apache.flex.compiler.problems.CSSCodeGenProblem;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.projects.IFlexProject;
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * This reducer generates a valid CSS file from a CSS model tree. The target
+ * code has two main parts - an array of selector data and an object literal
+ * with function closures to set the style properties.
+ */
+public class CSSReducer implements ICSSCodeGenResult
+{
+
+    /**
+     * The {@code global} CSS selector.
+     */
+    private static final String GLOBAL_SELECTOR = "global";
+
+    /**
+     * AET name for {@code var inheiritingStyles:String}.
+     */
+    private static final Name NAME_INHERITING_STYLES = new Name("inheritingStyles");
+
+    /**
+     * AET name for {@code var data:Array}.
+     */
+    public static final Name NAME_DATA_ARRAY = new Name("data");
+
+    /**
+     * ABC {@code Name} for<br>
+     * <code>public static var factoryFunctions:Object = generateFactoryFunctions();</code>
+     */
+    public static final Name NAME_FACTORY_FUNCTIONS = new Name("factoryFunctions");
+
+    /**
+     * Parameter types for a method without any parameters.
+     */
+    private static final Vector<Name> EMPTY_PARAM_TYPES = new Vector<Name>();
+
+    /**
+     * Create a CSS reducer.
+     * 
+     * @param project Owner project.
+     * @param cssDocument CSS DOM tree.
+     * @param abcVisitor {@link IABCVisitor} to which generated ABC constructs
+     * are added.
+     * @param session CSS compilation session data.
+     * @param isDefaultFactory If true, the generated code will register the
+     * styles with {@link ICSSRuntimeConstants#DEFAULT_FACTORY}.
+     */
+    public CSSReducer(final IFlexProject project,
+                      final ICSSDocument cssDocument,
+                      final IABCVisitor abcVisitor,
+                      final CSSCompilationSession session,
+                      final boolean isDefaultFactory)
+    {
+        assert project != null : "Expected a Flex project.";
+        assert cssDocument != null : "Expected a CSS model.";
+        assert abcVisitor != null : "Expected an ABC visitor.";
+        assert session != null : "Expected a CSSCompilationSession.";
+
+        this.problems = new HashSet<ICompilerProblem>();
+        this.session = session;
+        this.resolvedSelectors = ImmutableMap.copyOf(session.resolvedSelectors);
+        this.abcVisitor = abcVisitor;
+        this.project = project;
+        if (isDefaultFactory)
+            this.factory = ICSSRuntimeConstants.DEFAULT_FACTORY;
+        else
+            this.factory = ICSSRuntimeConstants.FACTORY;
+    }
+
+    /**
+     * Stores CSS semantic analysis results.
+     */
+    private final CSSCompilationSession session;
+
+    /**
+     * CSS code generation problems.
+     */
+    private final Set<ICompilerProblem> problems;
+
+    /**
+     * A dictionary for "selector" to "class definition".
+     */
+    private final ImmutableMap<ICSSSelector, String> resolvedSelectors;
+
+    /**
+     * Populate the target ABC instructions by using this visitor.
+     */
+    private final IABCVisitor abcVisitor;
+
+    /**
+     * Instructions for the class init method of a generated style's class.
+     */
+    private InstructionList cinitInstructionList;
+
+    /**
+     * Owner project.
+     */
+    private final IFlexProject project;
+
+    /**
+     * The "factory" with which the styles will be registered.
+     */
+    private final Integer factory;
+    
+    /**
+     * The media query string building up for the selector
+     */
+    private String mediaQueryString;
+
+    /**
+     * The map of media query to factory functions
+     */
+    private HashMap<String,ArrayList<String>> mediaQueryMap = new HashMap<String, ArrayList<String>>();
+    
+    /**
+     * Root reduction rule. It aggregates all the instructions and emit ABC code
+     * of {@code StyleDateClass}.
+     * 
+     * @param site {@link ICSSDocument} node.
+     * @param namespaceList Instructions to create array and closure for
+     * namespace declarations.
+     * @param ruleList Instructions to create array and closure for rules.
+     * @return Instructions to create array and closure for the CSS document.
+     */
+    public PairOfInstructionLists reduceDocument(ICSSNode site, PairOfInstructionLists namespaceList, PairOfInstructionLists ruleList)
+    {
+        // Instructions to push an array object on the stack.
+        final int elementSize = ruleList.arrayReduction.getInstructions().size();
+        final InstructionList arrayInstructions = new InstructionList();
+        arrayInstructions.addAll(ruleList.arrayReduction);
+        arrayInstructions.addInstruction(ABCConstants.OP_newarray, elementSize);
+
+        final PairOfInstructionLists pair = new PairOfInstructionLists(arrayInstructions, ruleList.closureReduction);
+        generateABC(pair);
+
+        return pair;
+    }
+
+    /**
+     * Generate ABC instructions for both array and closure.
+     * 
+     * @param pair Instructions to create array and closure for the
+     * {@code StyleDataClass}.
+     */
+    private void generateABC(final PairOfInstructionLists pair)
+    {
+        assert cinitInstructionList == null : "generateABC should only be called once per reducer because each document should only be reduced once.";
+        cinitInstructionList = new InstructionList();
+
+        // Generate instructions for "StyleDataClass$cinit()".
+        final InstructionList initializeFactoryFunctions = cinitInstructionList;
+
+        // Initialize "factoryFunctions".
+        initializeFactoryFunctions.addInstruction(ABCConstants.OP_getlocal0);
+        initializeFactoryFunctions.addAll(pair.closureReduction);
+        initializeFactoryFunctions.addInstruction(ABCConstants.OP_initproperty, NAME_FACTORY_FUNCTIONS);
+
+        // Initialize "data".
+        initializeFactoryFunctions.addInstruction(ABCConstants.OP_getlocal0);
+        initializeFactoryFunctions.addAll(pair.arrayReduction);
+        initializeFactoryFunctions.addInstruction(ABCConstants.OP_initproperty, NAME_DATA_ARRAY);
+
+        // Initialize "inheritingStyles".
+        @SuppressWarnings("unused")
+        final String inheritingStylesText =
+                Joiner.on(",").skipNulls().join(session.inheritingStyles);
+        initializeFactoryFunctions.addInstruction(ABCConstants.OP_getlocal0);
+        initializeFactoryFunctions.addInstruction(ABCConstants.OP_pushnull);
+        initializeFactoryFunctions.addInstruction(ABCConstants.OP_initproperty, NAME_INHERITING_STYLES);
+    }
+
+    @Override
+    public InstructionList getClassInitializationInstructions()
+    {
+        assert cinitInstructionList != null : "The initialize instructions may not be accessed until the document reduction has executed";
+        return cinitInstructionList;
+    }
+
+    @Override
+    public void visitClassTraits(ITraitsVisitor classTraitsVisitor)
+    {
+
+        // Resolve "Object" type.
+        final IResolvedQualifiersReference referenceObject = ReferenceFactory.packageQualifiedReference(project.getWorkspace(), "Object");
+
+        // Resolve "String" type.
+        @SuppressWarnings("unused")
+        final IResolvedQualifiersReference referenceString = ReferenceFactory.packageQualifiedReference(project.getWorkspace(), "String");
+
+        // Resolve "Array" type.
+        final IResolvedQualifiersReference referenceArray = ReferenceFactory.packageQualifiedReference(project.getWorkspace(), "Array");
+
+        // Generate "public static var factoryFunctions:Object;"
+        classTraitsVisitor.visitSlotTrait(
+                ABCConstants.TRAIT_Const,
+                NAME_FACTORY_FUNCTIONS,
+                ITraitsVisitor.RUNTIME_SLOT,
+                referenceObject.getMName(),
+                LexicalScope.noInitializer);
+
+        // Generate "public static var data:Array;"
+        classTraitsVisitor.visitSlotTrait(
+                ABCConstants.TRAIT_Const,
+                NAME_DATA_ARRAY,
+                ITraitsVisitor.RUNTIME_SLOT,
+                referenceArray.getMName(),
+                LexicalScope.noInitializer);
+
+        // Generate "public static var inheritingStyles:Array"
+        classTraitsVisitor.visitSlotTrait(
+                ABCConstants.TRAIT_Var,
+                NAME_INHERITING_STYLES,
+                ITraitsVisitor.RUNTIME_SLOT,
+                referenceArray.getMName(),
+                LexicalScope.noInitializer);
+    }
+
+    /**
+     * Namespace node does not generate code.
+     */
+    public PairOfInstructionLists reduceNamespaceDefinition(ICSSNode site)
+    {
+        return null;
+    }
+
+    /**
+     * Namespace list node does not generate code.
+     */
+    public PairOfInstructionLists reduceNamespaceList(ICSSNode site, List<PairOfInstructionLists> namespaces)
+    {
+        return null;
+    }
+
+    /**
+     * Reduce a CSS property.
+     * <p>
+     * For example: {@code fontSize : 12; } will be translated into
+     * ActionScript:<br>
+     * <code>this.fontSize = 12;</code><br>
+     * The ABC instructions for this statement are:<br>
+     * 
+     * <pre>
+     * getlocal0
+     * pushint 12
+     * setproperty fontSize
+     * </pre>
+     * 
+     * {@code getlocal0} will put "this" on the stack, then the property value
+     * is put on the stack. Finally, {@code setproperty} will assign "12" to
+     * "fontSize".
+     * <p>
+     * The code generation is based on the assumption that the CSS DOM tree has
+     * been semantically checked, so that the validity of the property name and
+     * type is not re-checked in the BURM.
+     */
+    public PairOfInstructionLists reduceProperty(ICSSNode site)
+    {
+        assert site instanceof ICSSProperty : "Expected ICSSProperty node but got " + site.getClass().getName();
+        final ICSSProperty propertyNode = (ICSSProperty)site;
+        final String name = propertyNode.getName();
+        final ICSSPropertyValue value = propertyNode.getValue();
+        final InstructionList inst = new InstructionList();
+
+        final InstructionList valueInstructions = getInstructionListForPropertyValue(value);
+        if (!valueInstructions.isEmpty())
+        {
+            // push "this" on the stack
+            inst.addInstruction(ABCConstants.OP_getlocal0);
+            // push value on the stack
+            inst.addAll(valueInstructions);
+            // set the property value
+            inst.addInstruction(ABCConstants.OP_setproperty, new Name(name));
+        }
+
+        return new PairOfInstructionLists(new InstructionList(), inst);
+    }
+
+    /**
+     * Get the AET instructions that can push values for the property on the AVM
+     * stack.
+     * 
+     * @param value CSS property value.
+     * @return AET instructions.
+     */
+    private InstructionList getInstructionListForPropertyValue(final ICSSPropertyValue value)
+    {
+        final InstructionList valueInstructions = new InstructionList();
+        // push property value on the stack
+        if (value instanceof CSSStringPropertyValue)
+        {
+            valueInstructions.addInstruction(ABCConstants.OP_pushstring, ((CSSStringPropertyValue)value).getValue());
+        }
+        else if (value instanceof CSSColorPropertyValue)
+        {
+            valueInstructions.addInstruction(ABCConstants.OP_pushint, new Integer(((CSSColorPropertyValue)value).getColorAsInt()));
+        }
+        else if (value instanceof CSSRgbColorPropertyValue)
+        {
+            valueInstructions.addInstruction(ABCConstants.OP_pushint, new Integer(((CSSRgbColorPropertyValue)value).getColorAsInt()));
+        }
+        else if (value instanceof CSSKeywordPropertyValue)
+        {
+            CSSKeywordPropertyValue keywordValue = (CSSKeywordPropertyValue)value;
+            String keywordString = keywordValue.getKeyword();
+            if (IASLanguageConstants.TRUE.equals(keywordString))
+                valueInstructions.addInstruction(ABCConstants.OP_pushtrue);
+            else if (IASLanguageConstants.FALSE.equals(keywordString))
+                valueInstructions.addInstruction(ABCConstants.OP_pushfalse);
+            else
+                valueInstructions.addInstruction(ABCConstants.OP_pushstring, ((CSSKeywordPropertyValue)value).getKeyword());
+        }
+        else if (value instanceof CSSNumberPropertyValue)
+        {
+            valueInstructions.addInstruction(ABCConstants.OP_pushdouble, new Double(((CSSNumberPropertyValue)value).getNumber().doubleValue()));
+        }
+        else if (value instanceof CSSFunctionCallPropertyValue)
+        {
+            final CSSFunctionCallPropertyValue functionCall = (CSSFunctionCallPropertyValue)value;
+            if ("ClassReference".equals(functionCall.name))
+            {
+                final String className = CSSFunctionCallPropertyValue.getSingleArgumentFromRaw(functionCall.rawArguments);
+                if ("null".equals(className))
+                {
+                    // ClassReference(null) resets the property's class reference.
+                    valueInstructions.addInstruction(ABCConstants.OP_pushnull);
+                }
+                else
+                {
+                    final IResolvedQualifiersReference reference = ReferenceFactory.packageQualifiedReference(project.getWorkspace(), className);
+                    valueInstructions.addInstruction(ABCConstants.OP_getlex, reference.getMName());
+                }
+            }
+            else if ("url".equals(functionCall.name))
+            {
+                final String urlString = CSSFunctionCallPropertyValue.getSingleArgumentFromRaw(functionCall.rawArguments);
+                valueInstructions.addInstruction(ABCConstants.OP_pushstring, urlString);
+            }
+            else if ("PropertyReference".equals(functionCall.name))
+            {
+                // TODO: implement me
+            }
+            else if ("Embed".equals(functionCall.name))
+            {
+                final EmbedCompilationUnit embedCompilationUnit = session.resolvedEmbedProperties.get(functionCall);
+                if (embedCompilationUnit == null)
+                {
+                    final ICompilerProblem e = new CSSCodeGenProblem(
+                            new IllegalStateException("Unable to find compilation unit for " + functionCall));
+                    problems.add(e);
+                }
+                else
+                {
+                    final String qName = embedCompilationUnit.getName();
+                    final IResolvedQualifiersReference reference = ReferenceFactory.packageQualifiedReference(project.getWorkspace(), qName);
+                    valueInstructions.addInstruction(ABCConstants.OP_getlex, reference.getMName());
+                }
+            }
+            else
+            {
+                assert false : "CSS parser bug: unexpected function call property value: " + functionCall;
+                throw new IllegalStateException("Unexpected function call property value: " + functionCall);
+            }
+        }
+        else if (value instanceof CSSArrayPropertyValue)
+        {
+            final CSSArrayPropertyValue arrayValue = (CSSArrayPropertyValue)value;
+            for (final ICSSPropertyValue elementValue : arrayValue.getElements())
+            {
+                valueInstructions.addAll(getInstructionListForPropertyValue(elementValue));
+            }
+            valueInstructions.addInstruction(ABCConstants.OP_newarray, arrayValue.getElements().size());
+        }
+        else
+        {
+            assert false : "Unsupported property value: " + value;
+        }
+        return valueInstructions;
+    }
+
+    /**
+     * Reduce a property list node. This method aggregates all the instructions
+     * to set property values. It also add instructions to setup the stack frame
+     * for this function closure.
+     */
+    public PairOfInstructionLists reducePropertyList(ICSSNode site, List<PairOfInstructionLists> properties)
+    {
+        final InstructionList closureInstructions = new InstructionList();
+        for (final PairOfInstructionLists inst : properties)
+            closureInstructions.addAll(inst.closureReduction);
+
+        closureInstructions.addInstruction(ABCConstants.OP_returnvoid);
+        return new PairOfInstructionLists(null, closureInstructions);
+    }
+
+    /**
+     * Reduce CSS rule node. The ABC method for the closures are generated here
+     * by merging the instructions from {@code propertyList} into the
+     * {@code selector}'s closure map.
+     * 
+     * @param site {@link ICSSRule} node.
+     * @param selector Instructions to construct the array data, and a map of
+     * named closures.
+     * @param propertyList Instructions to create array and closure that set the
+     * properties.
+     * @return Instructions for array data and a map of closures.
+     */
+    public InstructionListAndClosure reduceRule(ICSSNode site, InstructionListAndClosure selector, PairOfInstructionLists propertyList)
+    {
+        // Generate anonymous function.
+        final MethodInfo methodInfo = new MethodInfo();
+        String miName = ((CSSRule)site).getSelectorGroup().get(0).getElementName();
+        if (mediaQueryString != null)
+        {
+            pushNumericConstant(ICSSRuntimeConstants.MEDIA_QUERY, selector.arrayReduction);
+            selector.arrayReduction.addInstruction(ABCConstants.OP_pushstring, mediaQueryString);
+
+            miName = mediaQueryString + "_" + miName;
+            if (mediaQueryMap.containsKey(mediaQueryString))
+            {
+                ArrayList<String> factoryList = mediaQueryMap.get(mediaQueryString);
+                factoryList.add(miName);
+            }
+            else
+            {
+                ArrayList<String> factoryList = new ArrayList<String>();
+                factoryList.add(miName);
+                mediaQueryMap.put(mediaQueryString, factoryList);
+            }
+        }
+        methodInfo.setMethodName(miName);
+        methodInfo.setParamTypes(EMPTY_PARAM_TYPES);
+        final IMethodVisitor methodVisitor = abcVisitor.visitMethod(methodInfo);
+        methodVisitor.visit();
+
+        // Generate method body.
+        final MethodBodyInfo methodBodyInfo = new MethodBodyInfo();
+        methodBodyInfo.setMethodInfo(methodInfo);
+        final IMethodBodyVisitor methodBodyVisitor = methodVisitor.visitBody(methodBodyInfo);
+        methodBodyVisitor.visit();
+        methodBodyVisitor.visitInstructionList(propertyList.closureReduction);
+        methodBodyVisitor.visitEnd();
+
+        // Finish anonymous function.
+        methodVisitor.visitEnd();
+
+        // Populate the closure name-body map with method info objects.
+        for (final String name : selector.closureReduction.keySet())
+        {
+            if (mediaQueryString != null)
+            {
+                selector.closureReduction.remove(name);
+                selector.closureReduction.put(mediaQueryString + "_" + name, 
+                        methodInfo);
+            }
+            else
+                selector.closureReduction.put(name, methodInfo);
+        }
+        
+        mediaQueryString = null;
+
+        return selector;
+    }
+
+    /**
+     * Reduce a "selector" node. The node can have zero or more ascendant
+     * selectors.
+     */
+    public InstructionListAndString reduceSelector(ICSSNode site)
+    {
+        assert site instanceof ICSSSelector : "Expected a 'selector' node, but got '" + site.getClass().getName() + "'.";
+
+        final InstructionList arrayInstructions = new InstructionList();
+        final List<String> resolvedSimpleSelectorNames = new ArrayList<String>();
+        final ICSSSelector selectorNode = (ICSSSelector)site;
+        final ImmutableList<ICSSSelector> selectors = CSSSelector.getCombinedSelectorList(selectorNode);
+        for (final ICSSSelector selector : selectors)
+        {
+            final String selectorLiteral = getSelecterLiteralForABC(selector);
+
+            // Generate array data for conditional selector.
+            for (final ICSSSelectorCondition condition : selector.getConditions())
+            {
+                pushNumericConstant(ICSSRuntimeConstants.CONDITION, arrayInstructions);
+                arrayInstructions.addInstruction(ABCConstants.OP_pushstring, condition.getConditionType().name().toLowerCase());
+                arrayInstructions.addInstruction(ABCConstants.OP_pushstring, condition.getValue());
+            }
+
+            // Generate array data for type selector.
+            pushNumericConstant(ICSSRuntimeConstants.SELECTOR, arrayInstructions);
+            arrayInstructions.addInstruction(ABCConstants.OP_pushstring, selectorLiteral);
+
+            // Collect resolved name for the simple selector in the combined selectors.
+            // For example: "spark.components.Button#loginButton", ".highlight#main:up"
+            final String resolvedSelectorName = selectorLiteral.concat(Joiner.on("").join(selector.getConditions()));
+            resolvedSimpleSelectorNames.add(resolvedSelectorName);
+        }
+
+        final String combinedSelectors = Joiner.on(" ").join(resolvedSimpleSelectorNames);
+        return new InstructionListAndString(arrayInstructions, combinedSelectors);
+    }
+
+    /**
+     * Convert from CSS type names to ActionScript QNames.
+     * 
+     * @param selector CSS selector.
+     * @return String value of the selector name that works with Flex CSS
+     * runtime.
+     */
+    private String getSelecterLiteralForABC(final ICSSSelector selector)
+    {
+        final String selectorQname;
+        if (project.getCSSManager().isFlex3CSS())
+        {
+            assert !selector.isAdvanced() : "Advanced selector is not supported in Flex 3 mode. " + selector;
+            // Flex 3 style CSS are emitted "as-is".
+            final String elementName = selector.getElementName();
+            selectorQname = elementName == null ? "" : elementName;
+        }
+        else if (CSSSemanticAnalyzer.isWildcardSelector(selector))
+        {
+            // Selectors without specified types are normalized to have wildcard type "*".
+            // From SDK 4.5.2 and up, the CSS runtime queries such selectors by Qname "*".
+            if (GLOBAL_SELECTOR.equals(selector.getElementName()))
+                selectorQname = GLOBAL_SELECTOR;
+            else
+                selectorQname = "";
+        }
+        else
+        {
+            final String qname = resolvedSelectors.get(selector);
+            assert qname != null : "Unable to resolve type selector: " + selector;
+            selectorQname = qname;
+        }
+        return selectorQname;
+    }
+
+    /**
+     * Reduce rule list node.
+     */
+    public PairOfInstructionLists reduceRuleList(ICSSNode site, List<InstructionListAndClosure> rules)
+    {
+        final InstructionList arrayInstructions = new InstructionList();
+        final InstructionList closureInstructions = new InstructionList();
+        int closureCount = 0;
+        for (final InstructionListAndClosure ruleReduction : rules)
+        {
+            arrayInstructions.addAll(ruleReduction.arrayReduction);
+
+            for (final Entry<String, MethodInfo> entry : ruleReduction.closureReduction.entrySet())
+            {
+                closureInstructions.addInstruction(ABCConstants.OP_pushstring, entry.getKey());
+                closureInstructions.addInstruction(ABCConstants.OP_newfunction, entry.getValue());
+                closureCount++;
+            }
+        }
+        closureInstructions.addInstruction(ABCConstants.OP_newobject, closureCount);
+
+        return new PairOfInstructionLists(arrayInstructions, closureInstructions);
+    }
+
+    /**
+     * Reduce instructions for selector group.
+     * <p>
+     * The array reduction is instruction list. The closure reduction is a map.
+     * The keys in the map are the resolved selector names that will be used as
+     * names for the generated closures. The values in the map are all null.
+     * They will be populated in the parent tree, because the {@link MethodInfo}
+     * for the closure bodies come from a sibling "properties" tree.
+     */
+    public InstructionListAndClosure reduceSelectorGroup(ICSSNode site, List<InstructionListAndString> selectors)
+    {
+        final InstructionList arrayInstructions = new InstructionList();
+        final Map<String, MethodInfo> closureNames = new HashMap<String, MethodInfo>();
+        for (final InstructionListAndString selectorReduction : selectors)
+        {
+            arrayInstructions.addAll(selectorReduction.arrayReduction);
+            closureNames.put(selectorReduction.closureReduction, null);
+        }
+        pushNumericConstant(ICSSRuntimeConstants.STYLE_DECLARATION, arrayInstructions);
+        pushNumericConstant(factory, arrayInstructions);
+
+        return new InstructionListAndClosure(arrayInstructions, closureNames);
+    }
+
+    public PairOfInstructionLists reduceFontFaceList(ICSSNode site, List<PairOfInstructionLists> fontFaces)
+    {
+        // TODO Implement @font-face code generation
+        return null;
+    }
+
+    public PairOfInstructionLists reduceFontFace(ICSSNode site)
+    {
+        // TODO Implement @font-face code generation
+        return null;
+    }
+
+    public PairOfInstructionLists reduceMediaQuery(ICSSNode site, List<PairOfInstructionLists> conditions)
+    {
+        // TODO Implement @media code generation
+        return null;
+    }
+
+    public PairOfInstructionLists reduceMediaQueryCondition(ICSSNode site)
+    {
+        // TODO Implement @media code generation
+        if (mediaQueryString == null)
+            mediaQueryString = site.toString();
+        else
+            mediaQueryString += "and " + site.toString();
+        return null;
+    }
+
+    /**
+     * @return CSS reduction problems.
+     */
+    public Set<ICompilerProblem> getProblems()
+    {
+        return problems;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/ICSSCodeGenResult.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/ICSSCodeGenResult.java b/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/ICSSCodeGenResult.java
new file mode 100644
index 0000000..7bddedf
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/ICSSCodeGenResult.java
@@ -0,0 +1,45 @@
+/*
+ *
+ *  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.css.codegen;
+
+import org.apache.flex.abc.instructionlist.InstructionList;
+import org.apache.flex.abc.visitors.ITraitsVisitor;
+
+/**
+ * Interface to results of the CSS code generator.
+ */
+public interface ICSSCodeGenResult
+{
+    /**
+     * @return The {@link InstructionList} containing instructions for
+     * initializing the CSS data structures. This method does not append
+     * {@code returnvoid} instructions to the end of the instruction list.
+     */
+    InstructionList getClassInitializationInstructions();
+    
+    /**
+     * Add generated data slots for generated data structures to the specified
+     * {@link ITraitsVisitor}.
+     * 
+     * @param classTraitsVisitor {@link ITraitsVisitor} to which traits for the
+     * css data structures are added.
+     */
+    void visitClassTraits(ITraitsVisitor classTraitsVisitor);
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/ICSSRuntimeConstants.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/ICSSRuntimeConstants.java b/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/ICSSRuntimeConstants.java
new file mode 100644
index 0000000..ef6bc8d
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/ICSSRuntimeConstants.java
@@ -0,0 +1,44 @@
+/*
+ *
+ *  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.css.codegen;
+
+import org.apache.flex.abc.instructionlist.InstructionList;
+
+/**
+ * Defines all the runtime constants in the CSS framework. The constants are of
+ * type {@code Integer} so that they can be directly used in
+ * {@link InstructionList#addInstruction(int, Object)}.
+ */
+public interface ICSSRuntimeConstants
+{
+    // From CSSClass
+    static final Integer SELECTOR = 0;
+    static final Integer CONDITION = 1;
+    static final Integer STYLE_DECLARATION = 2;
+    static final Integer MEDIA_QUERY = 3;
+    
+    // From CSSFactory
+    static final Integer DEFAULT_FACTORY = 0;
+    static final Integer FACTORY = 1;
+
+    // From CSSDataType
+    static final Integer NATIVE = 0;
+    static final Integer DEFINITION = 1;
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/Pair.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/Pair.java b/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/Pair.java
new file mode 100644
index 0000000..18cace7
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/css/codegen/Pair.java
@@ -0,0 +1,101 @@
+/*
+ *
+ *  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.css.codegen;
+
+import java.util.Map;
+
+import org.apache.flex.abc.instructionlist.InstructionList;
+import org.apache.flex.abc.semantics.MethodInfo;
+
+/**
+ * The CSS code generation produces two sets of ABC instructions - one for the
+ * array data, the other for the closure functions. This is a two-tuple used by
+ * {@link CSSReducer}. At different tree nodes, the reduction result types for
+ * array and closure can be different. This generic class allows variant types
+ * to be used when reducing different tree nodes.
+ * 
+ * @param <L> Type of the array reduction result.
+ * @param <R> Type of the closure reduction result.
+ */
+abstract class Pair<L, R>
+{
+    /**
+     * Create a two-tuple object.
+     * 
+     * @param arrayReduction The array reduction result.
+     * @param closureReduction The closure reduction result.
+     */
+    protected Pair(L arrayReduction, R closureReduction)
+    {
+        this.arrayReduction = arrayReduction;
+        this.closureReduction = closureReduction;
+    }
+
+    /** Array reduction result. */
+    public final L arrayReduction;
+
+    /** Closure reduction result. */
+    public final R closureReduction;
+
+    /**
+     * Print debugging message for this {@code Pair} object.
+     */
+    @Override
+    public String toString()
+    {
+        return String.format("[array]\n%s\n\n[closure]\n%s\n", arrayReduction, closureReduction);
+    }
+
+    /**
+     * Both the array reduction and the closure reduction results are
+     * {@link InstructionList}.
+     */
+    public static final class PairOfInstructionLists extends Pair<InstructionList, InstructionList>
+    {
+        public PairOfInstructionLists(InstructionList arrayReduction, InstructionList closureReduction)
+        {
+            super(arrayReduction, closureReduction);
+        }
+    }
+
+    /**
+     * The array reduction result is {@link InstructionList}. The closure result
+     * is {@code String}.
+     */
+    public static final class InstructionListAndString extends Pair<InstructionList, String>
+    {
+        public InstructionListAndString(InstructionList arrayReduction, String closureReduction)
+        {
+            super(arrayReduction, closureReduction);
+        }
+    }
+
+    /**
+     * The array reduction result is {@link InstructionList}. The closure result
+     * is a map of closure names to closure method bodies.
+     */
+    public static final class InstructionListAndClosure extends Pair<InstructionList, Map<String, MethodInfo>>
+    {
+        public InstructionListAndClosure(InstructionList arrayReduction, Map<String, MethodInfo> closureReduction)
+        {
+            super(arrayReduction, closureReduction);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/css/package.hmtl
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/css/package.hmtl b/compiler/src/main/java/org/apache/flex/compiler/internal/css/package.hmtl
new file mode 100644
index 0000000..a5119d5
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/css/package.hmtl
@@ -0,0 +1,37 @@
+<!--
+
+  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 is the internal extension of the external
+<code>org.apache.flex.compiler.css</code> package.
+
+<p>
+It contains classes that implement the CSS model interfaces.
+</p>
+
+<p>
+See the <a href="../../package-summary.html#package_description">description</a>
+of the <code>org.apache.flex.compiler</code> package for an explanation
+of how the compiler code is organized into external and internal packages.
+</p>
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/css/semantics/ActivatedStyleSheets.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/css/semantics/ActivatedStyleSheets.java b/compiler/src/main/java/org/apache/flex/compiler/internal/css/semantics/ActivatedStyleSheets.java
new file mode 100644
index 0000000..2bb2436
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/css/semantics/ActivatedStyleSheets.java
@@ -0,0 +1,150 @@
+/*
+ *
+ *  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.css.semantics;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.flex.compiler.css.ICSSDocument;
+import org.apache.flex.compiler.internal.projects.LibraryPathManager;
+import org.apache.flex.utils.FilenameNormalization;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * A container for all activated CSS models. It can sort the CSS models by
+ * priority.
+ * <ol>
+ * <li>CSS files from {@code defaults-css-files} configuration option.</li>
+ * <li>"defaults.css" in SWC libraries on the library paths.</li>
+ * <li>Theme CSS and SWC.</li>
+ * </ol>
+ */
+public class ActivatedStyleSheets
+{
+    public ActivatedStyleSheets()
+    {
+        defaults = new ArrayList<ICSSDocument>();
+        themes = new ArrayList<ICSSDocument>();
+        libraries = new HashMap<ICSSDocument, String>();
+        comparator = new Comparator<ICSSDocument>()
+        {
+            /**
+             * Sort CSS model in their SWC filenames' alphabetic order. If we
+             * need to sort in the define order of library path,
+             * {@link LibraryPathManager} need to provide the comparator.
+             */
+            @Override
+            public int compare(ICSSDocument o1, ICSSDocument o2)
+            {
+                final String swcFile1 = libraries.get(o1);
+                final String swcFile2 = libraries.get(o2);
+                return swcFile1.compareTo(swcFile2);
+            }
+        };
+    }
+
+    /**
+     * CSS models from {@code defaults-css-files} option.
+     */
+    private final List<ICSSDocument> defaults;
+
+    /**
+     * CSS models from theme files.
+     */
+    private final List<ICSSDocument> themes;
+
+    /**
+     * CSS models from "defaults.css" files in SWC libraries.
+     */
+    private final Map<ICSSDocument, String> libraries;
+
+    /**
+     * Sort {@link #libraries} on their paths by alphabetical order.
+     */
+    private final Comparator<ICSSDocument> comparator;
+
+    /**
+     * Activate a default CSS model.
+     * 
+     * @param css CSS model.
+     */
+    public void addDefaultCSS(final ICSSDocument css)
+    {
+        assert css != null : "defaults css can't be null";
+        defaults.add(css);
+    }
+
+    /**
+     * Activate a theme CSS model.
+     * 
+     * @param css CSS model.
+     */
+    public void addThemeCSS(final ICSSDocument css)
+    {
+        assert css != null : "theme css can't be null";
+        themes.add(css);
+    }
+
+    /**
+     * Activate a library CSS model.
+     * 
+     * @param css CSS model.
+     * @param path Filename of SWC library that contains the CSS.
+     */
+    public void addLibraryCSS(final ICSSDocument css, final String path)
+    {
+        assert css != null : "librarycss can't be null";
+        libraries.put(css, FilenameNormalization.normalize(path));
+    }
+
+    /**
+     * @return A list of all activated CSS model sorted by precedence.
+     */
+    public List<ICSSDocument> sort()
+    {
+        // Sort CSS models from SWC libraries by library path order.
+        final List<ICSSDocument> librariesSorted = new ArrayList<ICSSDocument>(libraries.keySet());
+        Collections.sort(librariesSorted, comparator);
+
+        final ImmutableList.Builder<ICSSDocument> builder = new ImmutableList.Builder<ICSSDocument>();
+        builder.addAll(defaults);
+        builder.addAll(librariesSorted);
+        builder.addAll(themes);
+        return builder.build();
+    }
+
+    /**
+     * @return All activated CSS models.
+     */
+    public Set<ICSSDocument> all()
+    {
+        final ImmutableSet.Builder<ICSSDocument> builder = new ImmutableSet.Builder<ICSSDocument>();
+        builder.addAll(defaults);
+        builder.addAll(libraries.keySet());
+        builder.addAll(themes);
+        return builder.build();
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/css/semantics/CSSSemanticAnalyzer.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/css/semantics/CSSSemanticAnalyzer.java b/compiler/src/main/java/org/apache/flex/compiler/internal/css/semantics/CSSSemanticAnalyzer.java
new file mode 100644
index 0000000..a4748f4
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/css/semantics/CSSSemanticAnalyzer.java
@@ -0,0 +1,759 @@
+/*
+ *
+ *  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.css.semantics;
+
+import static org.apache.flex.compiler.internal.css.CSSStringPropertyValue.stripQuotes;
+import static com.google.common.collect.Collections2.filter;
+import static com.google.common.collect.Collections2.transform;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.flex.compiler.common.XMLName;
+import org.apache.flex.compiler.constants.IASLanguageConstants;
+import org.apache.flex.compiler.css.ICSSDocument;
+import org.apache.flex.compiler.css.ICSSNamespaceDefinition;
+import org.apache.flex.compiler.css.ICSSProperty;
+import org.apache.flex.compiler.css.ICSSPropertyValue;
+import org.apache.flex.compiler.css.ICSSRule;
+import org.apache.flex.compiler.css.ICSSSelector;
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.metadata.IMetaTag;
+import org.apache.flex.compiler.internal.css.CSSFunctionCallPropertyValue;
+import org.apache.flex.compiler.internal.css.CSSManager;
+import org.apache.flex.compiler.internal.css.CSSSelector;
+import org.apache.flex.compiler.internal.css.CSSStringPropertyValue;
+import org.apache.flex.compiler.internal.css.codegen.CSSCompilationSession;
+import org.apache.flex.compiler.internal.mxml.MXMLDialect;
+import org.apache.flex.compiler.internal.parsing.as.ASParser;
+import org.apache.flex.compiler.internal.projects.ASProject;
+import org.apache.flex.compiler.internal.targets.Target;
+import org.apache.flex.compiler.internal.tree.as.metadata.MetaTagsNode;
+import org.apache.flex.compiler.internal.units.EmbedCompilationUnit;
+import org.apache.flex.compiler.internal.units.EmbedCompilationUnitFactory;
+import org.apache.flex.compiler.mxml.IXMLNameResolver;
+import org.apache.flex.compiler.problems.CSSEmbedAssetProblem;
+import org.apache.flex.compiler.problems.CSSExcludedStylePropertyProblem;
+import org.apache.flex.compiler.problems.CSSUndefinedNamespacePrefixProblem;
+import org.apache.flex.compiler.problems.CSSUndefinedTypeProblem;
+import org.apache.flex.compiler.problems.CSSUnknownDefaultNamespaceProblem;
+import org.apache.flex.compiler.problems.CSSUnresolvedClassReferenceProblem;
+import org.apache.flex.compiler.problems.CSSUnusedTypeSelectorProblem;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.projects.IFlexProject;
+import org.apache.flex.compiler.tree.metadata.IMetaTagNode;
+import org.apache.flex.compiler.units.ICompilationUnit;
+import org.apache.flex.utils.FilenameNormalization;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+
+/**
+ * Semantic analyzer for CSS. This is a static class. It's used by
+ * {@link CSSManager}.
+ */
+public class CSSSemanticAnalyzer
+{
+
+    /** Global selector. */
+    private static final String GLOBAL_SELECTOR = "global";
+    /** Universal selector. */
+    private static final String UNIVERSAL_SELECTOR = "*";
+
+    /**
+     * Try to resolve all the dependencies introduced by
+     * {@code ClassReference()} and {@code Embed()} property values in a CSS
+     * rule.
+     * 
+     * @param resolvedEmbedProperties A map from {@code Embed()} property values
+     * to their resolved {@link EmbedCompilationUnit}'s.
+     * @param cssRule CSS rule.
+     * @param project Current project.
+     * @param classReferences Definitions of the {@code ClassReference("...")}
+     * properties will be stored in this collection after the function returns.
+     * @param embedCompilationUnits {@link EmbedCompilationUnit}'s used in the
+     * rules will be stored in this collection after the function returns.
+     * @param problems Compiler problems. This method reports
+     * {@link CSSUnresolvedClassReferenceProblem} issues.
+     */
+    public static void resolveDependencies(
+            final Map<CSSFunctionCallPropertyValue, EmbedCompilationUnit> resolvedEmbedProperties,
+            final ICSSRule cssRule,
+            final ICompilerProject project,
+            final Set<IClassDefinition> classReferences,
+            final Set<EmbedCompilationUnit> embedCompilationUnits,
+            final Collection<ICompilerProblem> problems)
+    {
+        assert cssRule != null : "CSS rule can't be null";
+        assert project != null : "Project can't be null";
+        assert problems != null : "Problems can't be null";
+        assert classReferences != null : "Expected an output collection for ClassReferences.";
+        assert embedCompilationUnits != null : "Expected an output collection for Embed.";
+
+        for (final ICSSProperty property : cssRule.getProperties())
+        {
+            final ICSSPropertyValue propertyValue = property.getValue();
+            if (propertyValue instanceof CSSFunctionCallPropertyValue)
+            {
+                final CSSFunctionCallPropertyValue functionCall = (CSSFunctionCallPropertyValue)propertyValue;
+                if (CSSFunctionCallPropertyValue.CLASS_REFERENCE.equals(functionCall.name))
+                {
+                    // Found a ClassReference() property.
+                    if ("null".equals(functionCall.rawArguments))
+                    {
+                        // Do nothing. ClassReference(null) resets the skin class.
+                    }
+                    else
+                    {
+                        final String qName;
+                        if (CSSStringPropertyValue.isQuoted(functionCall.rawArguments))
+                            qName = stripQuotes(functionCall.rawArguments);
+                        else
+                            qName = functionCall.rawArguments;
+
+                        final IDefinition definition = project.resolveQNameToDefinition(qName);
+                        // The definition is expected to be a class definition.
+                        if (definition != null && definition instanceof IClassDefinition)
+                        {
+                            classReferences.add((IClassDefinition)definition);
+                        }
+                        else
+                        {
+                            final CSSUnresolvedClassReferenceProblem problem = new CSSUnresolvedClassReferenceProblem(functionCall);
+                            problems.add(problem);
+                        }
+                    }
+                }
+                else if (CSSFunctionCallPropertyValue.EMBED.equals(functionCall.name))
+                {
+                    final String embedMetadata = String.format("[%s(%s)]", functionCall.name, functionCall.rawArguments);
+                    // TODO Calling normalize here prevents an assert later
+                    // in the getFileSpecification() of Workspace. The problem is that an embed
+                    // in default.css inside a SWC has a source path which doesn't look normalized.
+                    final String sourcePath = FilenameNormalization.normalize(functionCall.getSourcePath());
+                    final MetaTagsNode metadata = ASParser.parseMetadata(project.getWorkspace(), embedMetadata,
+                                                                         sourcePath, functionCall.getStart(),
+                                                                         functionCall.getLine(), functionCall.getColumn(),
+                                                                         problems);
+                    final IMetaTagNode embedTag = metadata.getTagByName("Embed");
+                    if (embedTag == null)
+                    {
+                        problems.add(new CSSEmbedAssetProblem(functionCall));
+                    }
+                    else
+                    {
+                        try
+                        {
+                            final EmbedCompilationUnit embedCompilationUnit =
+                                    EmbedCompilationUnitFactory.getCompilationUnit(
+                                            (ASProject)project,
+                                            embedTag.getSourcePath(),
+                                            functionCall,
+                                            embedTag.getAllAttributes(),
+                                            problems);
+                            if (embedCompilationUnit == null)
+                            {
+                                problems.add(new CSSEmbedAssetProblem(functionCall));
+                            }
+                            else
+                            {
+                                resolvedEmbedProperties.put(functionCall, embedCompilationUnit);
+                                embedCompilationUnits.add(embedCompilationUnit);
+                            }
+                        }
+                        catch (InterruptedException e)
+                        {
+                            // Incremental build interrupts the current build. We can
+                            // throw away the results.
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Resolve type selectors to class definitions within a file scope context
+     * <p>
+     * If a namespace short name is mapped to a undefined namespace URI, just
+     * ignore.
+     * 
+     * @param xmlNameResolver XML name resolver
+     * @param css CSS DOM.
+     * @param problems Collect problems.
+     * @param isCompatibilityVersion3 If true, do not create
+     * {@link CSSUnknownDefaultNamespaceProblem}'s.
+     * @return A map of CSS selectors to QNames of their resolved types.
+     */
+    public static ImmutableMap<ICSSSelector, String> resolveSelectors(
+            final IXMLNameResolver xmlNameResolver,
+            final ICSSDocument css,
+            final Collection<ICompilerProblem> problems,
+            final boolean isCompatibilityVersion3)
+    {
+        assert xmlNameResolver != null : "Expected xmlNameResolver";
+        assert css != null : "Expected CSS";
+
+        final ImmutableSet<ICSSSelector> allSelectors = getAllSelectors(css);
+
+        if (isCompatibilityVersion3)
+            return resolveSelectorsAsFlex3Style(allSelectors);
+
+        final ICSSNamespaceDefinition defaultNamespace = css.getDefaultNamespaceDefinition();
+        final Builder<ICSSSelector, String> builder = new Builder<ICSSSelector, String>();
+        for (final ICSSSelector selector : allSelectors)
+        {
+            // Expand selector to QName and conditions.
+            if (isWildcardSelector(selector))
+                continue;
+
+            final String prefix = selector.getNamespacePrefix();
+            final ICSSNamespaceDefinition namespace;
+
+            if (prefix == null)
+            {
+                // Check if the selector is a type selector without explicit namespace.
+                if (defaultNamespace == null)
+                {
+                    problems.add(new CSSUnknownDefaultNamespaceProblem((CSSSelector)selector));
+                    continue;
+                }
+                else
+                {
+                    namespace = defaultNamespace;
+                }
+            }
+            else
+            {
+                // Resolve namespace.
+                namespace = css.getNamespaceDefinition(prefix);
+            }
+
+            if (namespace == null)
+            {
+                problems.add(new CSSUndefinedNamespacePrefixProblem((CSSSelector)selector));
+                continue;
+            }
+
+            assert (selector.getElementName() != null) : "Null element name should be skipped as a wildcard selector.";
+            final XMLName xmlName = new XMLName(namespace.getURI(), selector.getElementName());
+
+            // Resolve type name.
+            final String qname = xmlNameResolver.resolveXMLNameToQualifiedName(xmlName, MXMLDialect.MXML_2009);
+            if (qname == null)
+            {
+                problems.add(new CSSUndefinedTypeProblem((CSSSelector)selector));
+            }
+            else
+            {
+                builder.put(selector, qname);
+            }
+        }
+        return builder.build();
+    }
+
+    /**
+     * Resolve selectors as Flex 3 CSS. In Flex 3 CSS, selectors don't have
+     * namespaces. As a result, they don't have to be resolved to a type
+     * definition. For example, selector "Button" will be emitted as a selector
+     * literal "Button". Whereas, in Flex 4 mode, "Button" would be resolved to
+     * a default namespace and then emitted as a Spark Button QName or MX Button
+     * QName.
+     * 
+     * @param selectors All the selectors to resolve.
+     * @return A map from selectors to its resolved runtime style selector name.
+     */
+    private static ImmutableMap<ICSSSelector, String> resolveSelectorsAsFlex3Style(
+            final Iterable<ICSSSelector> selectors)
+    {
+        final ImmutableMap.Builder<ICSSSelector, String> builder = new ImmutableMap.Builder<ICSSSelector, String>();
+        for (final ICSSSelector selector : selectors)
+        {
+            builder.put(selector, selector.getCSSSyntax());
+        }
+        return builder.build();
+    }
+
+    /**
+     * Collect all the selectors in the CSS document including the subjects and
+     * the combination selectors.
+     * 
+     * @param document CSS document
+     * @return All the selectors in the CSS.
+     */
+    public static ImmutableSet<ICSSSelector> getAllSelectors(final ICSSDocument document)
+    {
+        assert document != null : "Expected CSS document";
+
+        final ImmutableSet.Builder<ICSSSelector> builder = new ImmutableSet.Builder<ICSSSelector>();
+        for (final ICSSRule rule : document.getRules())
+        {
+            for (final ICSSSelector subject : rule.getSelectorGroup())
+            {
+                ICSSSelector selector = subject;
+                while (selector != null)
+                {
+                    builder.add(selector);
+                    if (selector.getCombinator() != null)
+                        selector = selector.getCombinator().getSelector();
+                    else
+                        selector = null;
+                }
+            }
+        }
+        return builder.build();
+    }
+
+    /**
+     * A {@link Predicate} that filters {@link ICSSSelector}'s matched by a
+     * given set of class definitions. This is created for
+     * {@link Collections2#filter(Collection, Predicate)}.
+     */
+    private static class MatchedCSSRulePredicate implements Predicate<ICSSRule>
+    {
+        /**
+         * QNames of the definitions to be matched by the CSS rules.
+         */
+        private final ImmutableSet<String> qnames;
+
+        /**
+         * A map of selectors resolved to class definitions.
+         */
+        private final ImmutableMap<ICSSSelector, String> resolvedSelectors;
+
+        /**
+         * Create a predicate for filtering matched CSS rules.
+         * 
+         * @param qnames A set of class definitions to be matched by the
+         * CSS rules.
+         * @param resolvedSelectors A map of selectors resolved to class
+         * definitions.
+         */
+        public MatchedCSSRulePredicate(final ImmutableSet<String> qnames,
+                                       final ImmutableMap<ICSSSelector, String> resolvedSelectors)
+        {
+            assert qnames != null : "Expected a set of definition for the CSS rules to match.";
+            assert resolvedSelectors != null : "Expected a map of selectors resolved to class definitions.";
+            this.qnames = qnames;
+            this.resolvedSelectors = resolvedSelectors;
+        }
+
+        /**
+         * Return true if any of the <b>subject</b> selectors in the
+         * {@code rule}'s selector group match any definitions in
+         * {@link #qnames}. Combinator selectors are ignored.
+         */
+        @Override
+        public boolean apply(final ICSSRule rule)
+        {
+            for (final ICSSSelector selector : rule.getSelectorGroup())
+            {
+                if (isWildcardSelector(selector))
+                    return true;
+                final String qname = resolvedSelectors.get(selector);
+                if (qnames.contains(qname))
+                    return true;
+            }
+            return false;
+        }
+    }
+
+    /**
+     * This predicate is created for {@code -compatibility-version=3} mode. In
+     * Flex 3, the selectors don't have namespace specifiers. Under the
+     * "compatible" mode, {@code Button} means {@code *|Button} in CSS3 syntax.
+     * <p>
+     * All selectors with Flex 4 advanced syntax will be dropped.
+     * <p>
+     * This class only compares the selector element names and the definition
+     * short names.
+     */
+    private static class Flex3CSSRulePredicate implements Predicate<ICSSRule>
+    {
+        private final ImmutableSet<String> definitionSimpleNames;
+
+        private Flex3CSSRulePredicate(final ImmutableSet<String> definitionSimpleNames)
+        {
+            this.definitionSimpleNames = definitionSimpleNames;
+        }
+
+        @Override
+        public boolean apply(ICSSRule rule)
+        {
+            for (final ICSSSelector selector : rule.getSelectorGroup())
+            {
+                // drop advanced selectors for flex 3
+                if (selector.isAdvanced())
+                    return false;
+
+                // drop unused css rules
+                final String elementName = selector.getElementName();
+                if (GLOBAL_SELECTOR.equals(elementName))
+                    continue;
+                if (elementName == null)
+                    continue;
+                if (!definitionSimpleNames.contains(elementName))
+                    return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Convert a dot-separated QName string to the simple name. For example:
+     * <ul>
+     * <li>{@code f("a.b.foo") = "foo";}</li>
+     * <li>{@code f("bar") = "bar";}</li>
+     * </ul>
+     */
+    private static final Function<String, String> QNAME_TO_SIMPLE_NAME = new Function<String, String>()
+    {
+        @Override
+        public String apply(String qname)
+        {
+            return Iterables.getLast(Splitter.on(".").omitEmptyStrings().split(qname));
+        }
+    };
+
+    /**
+     * Get a set of {@link ICSSRule}'s that match any of the class definitions
+     * passed in.
+     * 
+     * @param session CSS compilation session data.
+     * @param flexProject Flex project.
+     * @param cssDocument CSS document.
+     * @param qnames A set of QNames of the definitions to be matched the CSS
+     * rules.
+     * @param problems Problems collection.
+     * @return A set of CSS rules matched by one of the given class definitions.
+     */
+    public static ImmutableSet<ICSSRule> getMatchedRules(
+            final CSSCompilationSession session,
+            final IFlexProject flexProject,
+            final ICSSDocument cssDocument,
+            final ImmutableSet<String> qnames,
+            final Collection<ICompilerProblem> problems)
+    {
+        final boolean isFlex3CSS = flexProject.getCSSManager().isFlex3CSS();
+        final ImmutableMap<ICSSSelector, String> resolvedSelectors =
+                resolveSelectors(flexProject, cssDocument, problems, isFlex3CSS);
+        final Predicate<ICSSRule> predicate;
+        if (isFlex3CSS)
+        {
+            final ImmutableSet<String> simpleNames =
+                    ImmutableSet.copyOf(transform(qnames, QNAME_TO_SIMPLE_NAME));
+            predicate = new Flex3CSSRulePredicate(simpleNames);
+        }
+        else
+        {
+            predicate = new MatchedCSSRulePredicate(qnames, resolvedSelectors);
+        }
+
+        // Cache the result of selector resolution on the session. 
+        // The CSS code generation will use this map later.
+        session.resolvedSelectors.putAll(resolvedSelectors);
+
+        // Find rules with selectors that match types in a given definition set.
+        return ImmutableSet.copyOf(filter(cssDocument.getRules(), predicate));
+    }
+
+    /**
+     * Check if the selector is a wildcard selector. For example:
+     * <ul>
+     * <li>global</li>
+     * <li>*</li>
+     * <li>.highlight</li>
+     * <li>:up</li>
+     * </ul>
+     * 
+     * @param selector CSS selector
+     * @return True if the selector is a "wildcard" selector.
+     */
+    public static boolean isWildcardSelector(ICSSSelector selector)
+    {
+        final String elementName = selector.getElementName();
+        return elementName == null ||
+               UNIVERSAL_SELECTOR.equals(elementName) ||
+               GLOBAL_SELECTOR.equals(elementName);
+    }
+
+    /**
+     * Build a map from QNames to class definitions.
+     * 
+     * @param classDefinitions Class definitions.
+     * @return Lookup map.
+     */
+    public static final ImmutableMap<String, IClassDefinition> buildQNameToDefinitionMap(final Collection<IClassDefinition> classDefinitions)
+    {
+        final Map<String, IClassDefinition> builder = new HashMap<String, IClassDefinition>();
+        for (final IClassDefinition classDefinition : classDefinitions)
+        {
+            builder.put(classDefinition.getQualifiedName(), classDefinition);
+        }
+        return ImmutableMap.copyOf(builder);
+    }
+
+    /**
+     * Find all the class definitions in the given collection.
+     * 
+     * @param definitions A collection of definitions.
+     * @return A set of class definitions.
+     */
+    public static ImmutableSet<IClassDefinition> getClassDefinitionSet(final Collection<IDefinition> definitions)
+    {
+        final ImmutableSet.Builder<IClassDefinition> builder = new ImmutableSet.Builder<IClassDefinition>();
+        for (final IDefinition def : definitions)
+        {
+            if (def instanceof IClassDefinition)
+                builder.add((IClassDefinition)def);
+        }
+        final ImmutableSet<IClassDefinition> classDefinitions = builder.build();
+        return classDefinitions;
+    }
+
+    /**
+     * <p>
+     * Validate a CSS model. The validation only works for Flex 4+.
+     * </p>
+     * <h1>Find CSS rules with unused type selectors.</h1>
+     * <p>
+     * The result is added to the problem collection.
+     * <p>
+     * For example, if an MXML document only uses {@code <s:Button>} tags, and
+     * its {@code <fx:Style>} block contains:
+     * 
+     * <pre>
+     * ...
+     * s|Button { fontSize : 12; }
+     * local|MyComponent {  color : red; }
+     * ...
+     * </pre>
+     * 
+     * Since {@code <local:MyComponent>} isn't used in the current MXML
+     * document, the {@code local|MyComponent} is a rule with an <i>unused type
+     * selector</i>.
+     * <p>
+     * The validation process only finds all the unused type selectors, but it
+     * doesn't take them out of the code generation.
+     * <p>
+     * <h1>Find usages of excludes styles.</h1> If a component declares one of
+     * its styles to be "excluded", usages of such styles will be reported as
+     * {@link CSSExcludedStylePropertyProblem}.
+     * 
+     * <pre>
+     * [Exclude(kind="style", name="foo")]
+     * public class MyButton
+     * {
+     * }
+     * </pre>
+     * 
+     * The following CSS will cause the problem:
+     * 
+     * <pre>
+     * local|MyButton { foo : something; }
+     * </pre>
+     * 
+     * @param linkingCompilationUnits All type selectors that doesn't map to any
+     * definition in this collection are "unused".
+     * @param session {@link CSSCompilationSession#cssDocuments} has all the CSS
+     * models an MXML document has.
+     * @throws InterruptedException Abort compilation.
+     */
+    public static void validate(
+            final Set<ICompilationUnit> linkingCompilationUnits,
+            final CSSCompilationSession session,
+            final Collection<ICompilerProblem> problems)
+            throws InterruptedException
+    {
+        final CSSValidator validator = new CSSValidator(session, linkingCompilationUnits, problems);
+        for (final ICSSDocument cssDocument : session.cssDocuments)
+        {
+            visit(cssDocument, validator);
+        }
+    }
+
+    /**
+     * CSS model visitor.
+     */
+    private static interface ICSSVisitor
+    {
+
+        /**
+         * Visit a CSS document.
+         */
+        void beginDocument(final ICSSDocument document);
+
+        /**
+         * Visit a CSS rule.
+         */
+        void beginRule(final ICSSRule rule);
+
+        /**
+         * Visit a CSS subject selector.
+         */
+        void beginSubject(final ICSSSelector selector, final ICSSRule rule);
+
+        /**
+         * Visit a CSS property.
+         */
+        void beginProperty(final ICSSProperty property, final ICSSRule rule);
+    }
+
+    /**
+     * Validate the following CSS semantic constraints:
+     * <ol>
+     * <li>unused type selectors</li>
+     * <li>usage of excluded styles</li>
+     * </ol>
+     */
+    private static class CSSValidator implements ICSSVisitor
+    {
+        private final CSSCompilationSession session;
+        private final ImmutableMap<String, IClassDefinition> qnameToDefinition;
+        private final Collection<ICompilerProblem> problems;
+        private final Multimap<ICSSSelector, String> excludedStyles;
+
+        /**
+         * Create a CSS validating visitor.
+         * 
+         * @param session CSS compilation session.
+         * @param linkingCompilationUnits All the compilation units to be
+         * linked. This is used to find <i>unused type selectors</i>.
+         * @param problems Problem collection.
+         * @throws InterruptedException Compilation aborted.
+         */
+        private CSSValidator(final CSSCompilationSession session,
+                             final Set<ICompilationUnit> linkingCompilationUnits,
+                             final Collection<ICompilerProblem> problems) throws InterruptedException
+        {
+            this.session = session;
+            final ImmutableList<IDefinition> linkingDefinitions =
+                    Target.getAllExternallyVisibleDefinitions(linkingCompilationUnits);
+            final ImmutableSet<IClassDefinition> classDefinitions =
+                    getClassDefinitionSet(linkingDefinitions);
+            this.qnameToDefinition = buildQNameToDefinitionMap(classDefinitions);
+            this.problems = problems;
+            this.excludedStyles = HashMultimap.create();
+        }
+
+        /**
+         * <ol>
+         * <li>Find all excluded styles for the current subject.</li>
+         * <li>Find unused type selectors.</li>
+         * </ol>
+         */
+        @Override
+        public void beginSubject(final ICSSSelector selector, final ICSSRule rule)
+        {
+            if (!isWildcardSelector(selector))
+            {
+                final String qname = session.resolvedSelectors.get(selector);
+                if (qnameToDefinition.containsKey(qname))
+                {
+                    // The subject's resolved QName is in the linking set.
+                    // Collect all "excluded" styles for this subject selector.
+                    // Only check "Exclude" styles on used styles.
+                    final IClassDefinition classDefinition = qnameToDefinition.get(qname);
+                    final IMetaTag[] excludeMetaTags = classDefinition.getMetaTagsByName(IASLanguageConstants.EXCLUDE_META_TAG);
+                    for (final IMetaTag exclude : excludeMetaTags)
+                    {
+                        final String kind = exclude.getAttributeValue(IASLanguageConstants.EXCLUDE_META_TAG_KIND);
+                        if (IASLanguageConstants.EXCLUDE_META_TAG_STYLE.equals(kind))
+                        {
+                            final String excludedStyleName = exclude.getAttributeValue(IASLanguageConstants.EXCLUDE_META_TAG_NAME);
+                            if (excludedStyleName != null && !excludedStyleName.isEmpty())
+                            {
+                                this.excludedStyles.put(selector, excludedStyleName);
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    // Selector's resolved QName is not in the linking set.
+                    problems.add(new CSSUnusedTypeSelectorProblem(selector));
+                }
+            }
+        }
+
+        @Override
+        public void beginRule(final ICSSRule rule)
+        {
+        }
+
+        @Override
+        public void beginDocument(final ICSSDocument document)
+        {
+        }
+
+        /**
+         * Check usages of excluded styles.
+         */
+        @Override
+        public void beginProperty(final ICSSProperty property, final ICSSRule rule)
+        {
+            for (final ICSSSelector subject : rule.getSelectorGroup())
+            {
+                final Collection<String> excludedStylesForSubject = excludedStyles.get(subject);
+                if (excludedStylesForSubject != null && excludedStylesForSubject.contains(property.getName()))
+                {
+                    final String qname = session.resolvedSelectors.get(subject);
+                    problems.add(new CSSExcludedStylePropertyProblem(property, qname));
+                }
+
+            }
+        }
+
+    }
+
+    /**
+     * Visit a CSS document model.
+     * 
+     * @param document CSS model.
+     * @param visitor Handler for various visit methods.
+     */
+    private static void visit(final ICSSDocument document, final ICSSVisitor visitor)
+    {
+        visitor.beginDocument(document);
+        for (final ICSSRule rule : document.getRules())
+        {
+            visitor.beginRule(rule);
+            for (final ICSSSelector selector : rule.getSelectorGroup())
+                visitor.beginSubject(selector, rule);
+
+            for (final ICSSProperty property : rule.getProperties())
+                visitor.beginProperty(property, rule);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/AccessorDefinition.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/AccessorDefinition.java b/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/AccessorDefinition.java
new file mode 100644
index 0000000..aadd143
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/AccessorDefinition.java
@@ -0,0 +1,237 @@
+/*
+ *
+ *  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.definitions;
+
+import java.util.Iterator;
+
+
+import org.apache.flex.compiler.definitions.IAccessorDefinition;
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.IFunctionDefinition;
+import org.apache.flex.compiler.definitions.IGetterDefinition;
+import org.apache.flex.compiler.definitions.IInterfaceDefinition;
+import org.apache.flex.compiler.definitions.INamespaceDefinition;
+import org.apache.flex.compiler.definitions.IPackageDefinition;
+import org.apache.flex.compiler.definitions.ISetterDefinition;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.scopes.IDefinitionSet;
+import org.apache.flex.compiler.tree.as.IVariableNode;
+import org.apache.flex.compiler.definitions.IScopedDefinition;
+import org.apache.flex.compiler.definitions.references.INamespaceReference;
+import org.apache.flex.compiler.internal.as.codegen.BindableHelper;
+import org.apache.flex.compiler.internal.scopes.ASScope;
+
+/**
+ * {@code AccessorDefinition} is the abstract base class for definitions that
+ * represent getters and setters.
+ */
+public abstract class AccessorDefinition extends FunctionDefinition implements IAccessorDefinition
+{
+    public AccessorDefinition(String name)
+    {
+        super(name);
+    }
+
+    @Override
+    public AccessorDefinition resolveCorrespondingAccessor(ICompilerProject project)
+    {
+        IDefinition parent = getParent();
+
+        if (parent instanceof IClassDefinition)
+        {
+            // This accessor is in a class, so look for a corresponding one
+            // in this class and then in all superclasses.
+            Iterator<IClassDefinition> iter = ((IClassDefinition)parent).classIterator(project, true);
+            while (iter.hasNext())
+            {
+                IClassDefinition cls = iter.next();
+
+                AccessorDefinition correspondingAccessor =
+                        findCorrespondingAccessor(cls, project);
+
+                if (correspondingAccessor != null)
+                    return correspondingAccessor;
+            }
+        }
+        else if (parent instanceof IInterfaceDefinition)
+        {
+            // This accessor is in an interface, so look for a corresponding one
+            // in this interface and then in all superinterfaces.
+            Iterator<IInterfaceDefinition> iter = ((IInterfaceDefinition)parent).interfaceIterator(project, true);
+            while (iter.hasNext())
+            {
+                IInterfaceDefinition intf = iter.next();
+
+                AccessorDefinition correspondingAccessor =
+                        findCorrespondingAccessor(intf, project);
+
+                if (correspondingAccessor != null)
+                    return correspondingAccessor;
+            }
+        }
+        else if (parent instanceof IPackageDefinition)
+        {
+            IPackageDefinition pd = (IPackageDefinition)parent;
+            return findCorrespondingAccessor(pd, project);
+        }
+        else if (parent == null)
+        {
+            // if the parent definition is null, we must be at file scope, so must search the scope 
+            // directly
+            ASScope scope = this.getContainingASScope();
+            return findCorrespondingAccessor(scope, project);
+        }
+        else
+            assert false; // we should have code for all cases...
+
+        return null;
+    }
+
+    /**
+     * Looks in a specified class or interface for an accessor that corresponds
+     * to "this". i.e. if "this" is a getter, find the matching setter.
+     * 
+     * @param type is the definition to search for corresponding def
+     * @return an accessor definition that matches, or null if none found
+     */
+
+    private AccessorDefinition findCorrespondingAccessor(IScopedDefinition type, ICompilerProject project)
+    {
+        final ASScope scope = (ASScope)type.getContainedScope();
+        return findCorrespondingAccessor(scope, project);
+    }
+
+    /**
+     * Looks in a specified scope for an accessor that corresponds to "this".
+     * i.e. if "this" is a getter, find the matching setter.
+     * 
+     * @param scope is the scope to search for corresponding def
+     * @return an accessor definition that matches, or null if none found
+     */
+
+    private AccessorDefinition findCorrespondingAccessor(ASScope scope, ICompilerProject project)
+    {
+        final String name = getBaseName();
+        final INamespaceReference namespaceReference = getNamespaceReference();
+        final boolean isStatic = isStatic();
+        
+        // If the namespace is bad and dosn't resolve, then we can't find corresponding accessor.
+        final INamespaceDefinition thisNamespaceDef = namespaceReference.resolveNamespaceReference(project);
+        if (thisNamespaceDef == null)
+            return null; 
+        final boolean isBindable = ((NamespaceDefinition)thisNamespaceDef).getAETNamespace().getName().equals(
+                                    BindableHelper.bindableNamespaceDefinition.getAETNamespace().getName());
+
+        final IDefinitionSet definitionSet = scope.getLocalDefinitionSetByName(name);
+
+        if (definitionSet == null)
+            return null;
+
+        final int n = definitionSet.getSize();
+        for (int i = 0; i < n; i++)
+        {
+            IDefinition d = definitionSet.getDefinition(i);
+            if (d instanceof IAccessorDefinition)
+            {
+                final IAccessorDefinition definition = (IAccessorDefinition)d;
+                
+                // If this is a static accessor, we want another static accessor.
+                // If this is an instance accessor, we want another instance accessor. 
+                if (definition.isStatic() == isStatic)
+                {
+                    // If this is a getter, we want a setter, and vice versa.
+                    if (this instanceof IGetterDefinition && definition instanceof ISetterDefinition ||
+                        this instanceof ISetterDefinition && definition instanceof IGetterDefinition)
+                    {
+                        INamespaceReference testDefRef = definition.getNamespaceReference();
+                        INamespaceDefinition testNamespaceDef = testDefRef.resolveNamespaceReference(project);
+                        final boolean testBindable = ((NamespaceDefinition)testNamespaceDef).getAETNamespace().getName().equals(
+                                BindableHelper.bindableNamespaceDefinition.getAETNamespace().getName());
+                        /* aharui: namespaces shouldn't have to match.  A subclass may only override
+                         * one of the protected methods, and it was legal to have a public getter with
+                         * a protected setter and other combinations like that.  Either both
+                         * have to be in the bindable namespace, or both are not. */
+                        if ((isBindable && testBindable) ||
+                                (!isBindable && !testBindable))
+                            return (AccessorDefinition)definition;
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Get the classification for this variable (local, argument, class member,
+     * etc)
+     * 
+     * @return variable classification
+     */
+    @Override
+    public VariableClassification getVariableClassification()
+    {
+        IDefinition parent = getParent();
+
+        if (parent instanceof IFunctionDefinition)
+            return VariableClassification.LOCAL;
+        if (parent instanceof IClassDefinition)
+            return VariableClassification.CLASS_MEMBER;
+        if (parent instanceof IInterfaceDefinition)
+            return VariableClassification.INTERFACE_MEMBER;
+        if (parent instanceof IPackageDefinition)
+            return VariableClassification.PACKAGE_MEMBER;
+        if (parent == null)
+        {
+            if (inPackageNamespace())
+                return VariableClassification.PACKAGE_MEMBER;
+
+            return VariableClassification.FILE_MEMBER;
+        }
+
+        assert false;
+        return null;
+    }
+
+    @Override
+    public IVariableNode getVariableNode()
+    {
+        return (IVariableNode)super.getNode();
+    }
+
+    @Override
+    public Object resolveInitialValue(ICompilerProject project)
+    {
+        return null;
+    }
+
+    @Override
+    public boolean inlineFunction()
+    {
+        // if inlining has been enabled, don't need to check
+        // for inline keyword, as inline all getters/setters
+        // as long as they meet the correct criteria.
+        if (canFunctionBeInlined())
+            return true;
+
+        return false;
+    }
+}


Mime
View raw message