/** Called on each content unit that is not part of the default value. */ private void processNonDefaultPropertyContentUnit(MXMLTreeBuilder builder, MXMLNodeInfo info) { // If this gets called and we're processing the default property, // then childTag is the first child tag after the default property value tags. if (processingDefaultProperty) { processingDefaultProperty = false; processedDefaultProperty = true; assert defaultPropertyContentUnits.size() > 0; assert !builder.getFileScope().isScriptTag(defaultPropertyContentUnits.get(0)) : "First default property content unit must not be a script tag!"; // We've accumulated all the default property child tags // in defaultPropertyChildTags. Use them to initialize // the defaultPropertyNode. // But first find all the trailing script tags // and remove those from the list of default // property content units. // Script tags are put in the defaultPropertyContentUnits collection // to fix http://bugs.adobe.com/jira/browse/CMP-955. int lastNonScriptTagIndex; for (lastNonScriptTagIndex = (defaultPropertyContentUnits.size() - 1); lastNonScriptTagIndex > 0; --lastNonScriptTagIndex) { MXMLUnitData unitData = defaultPropertyContentUnits.get(lastNonScriptTagIndex); if (!builder.getFileScope().isScriptTag(unitData)) break; } assert lastNonScriptTagIndex >= 0; assert lastNonScriptTagIndex < defaultPropertyContentUnits.size(); List<MXMLUnitData> trailingScriptTags = defaultPropertyContentUnits.subList( lastNonScriptTagIndex + 1, defaultPropertyContentUnits.size()); List<MXMLUnitData> defaultPropertyContentUnitsWithoutTrailingScriptTags = defaultPropertyContentUnits.subList(0, lastNonScriptTagIndex + 1); // process the default property content units with the trailing // script tags removed. IVariableDefinition defaultPropertyDefinition = getDefaultPropertyDefinition(builder); defaultPropertyNode.initializeDefaultProperty( builder, defaultPropertyDefinition, defaultPropertyContentUnitsWithoutTrailingScriptTags); // Now create MXMLScriptNode's for all the trailing script tags. for (MXMLUnitData scriptTagData : trailingScriptTags) { assert builder.getFileScope().isScriptTag(scriptTagData); MXMLScriptNode scriptNode = new MXMLScriptNode(this); scriptNode.initializeFromTag(builder, (MXMLTagData) scriptTagData); info.addChildNode(scriptNode); } } }
/** * Attempt to parse a binding expression from the passed in attribute * * @param attr The Tag Attribute Data to parse * @return An IMXMLDataBindingNode that was parsed from attr, or null if no databinding expression * was found */ private IMXMLSingleDataBindingNode parseBindingExpression(MXMLTagAttributeData attr) { Object o = MXMLDataBindingParser.parse( parent, attr, attr.getValueFragments(builder.getProblems()), builder.getProblems(), builder.getWorkspace(), builder.getMXMLDialect()); if (o instanceof IMXMLSingleDataBindingNode) { return ((IMXMLSingleDataBindingNode) o); } return null; }
/** * Attempt to parse a binding expression from the passed in text data * * @param text The Text Data to parse * @return An IMXMLDataBindingNode that was parsed from text, or null if no databinding expression * was found */ private IMXMLSingleDataBindingNode parseBindingExpression(MXMLTextData text) { Object o = MXMLDataBindingParser.parse( parent, text, text.getFragments(builder.getProblems()), builder.getProblems(), builder.getWorkspace(), builder.getMXMLDialect()); if (o instanceof IMXMLSingleDataBindingNode) { return ((IMXMLSingleDataBindingNode) o); } return null; }
/** * Resolve the specifier name in the class definition to a member definition, and create a * specifier node based on the member type. * * @param builder MXML tree builder. * @param specifierName Specifier name. * @return A MXML specifier node. */ protected MXMLSpecifierNodeBase createSpecifierNode( MXMLTreeBuilder builder, String specifierName) { MXMLSpecifierNodeBase specifierNode = null; // Check if the attribute is a declared property, style, or event. FlexProject project = builder.getProject(); IDefinition specifierDefinition = project.resolveSpecifier(classReference, specifierName); if (specifierDefinition instanceof ISetterDefinition || specifierDefinition instanceof IVariableDefinition) { specifierNode = new MXMLPropertySpecifierNode(this); } else if (specifierDefinition instanceof IEventDefinition) { specifierNode = new MXMLEventSpecifierNode(this); } else if (specifierDefinition instanceof IStyleDefinition) { specifierNode = new MXMLStyleSpecifierNode(this); } else if (specifierDefinition instanceof IEffectDefinition) { specifierNode = new MXMLEffectSpecifierNode(this); } if (specifierNode != null) { specifierNode.setDefinition(specifierDefinition); // TODO Move this logic } // If not, dynamic classes allow new properties to be set via attributes. else if (classReference.isDynamic()) { specifierNode = new MXMLPropertySpecifierNode(this); ((MXMLPropertySpecifierNode) specifierNode) .setDynamicName(specifierName); // TODO Move this logic } return specifierNode; }
@Override protected void initializationComplete( MXMLTreeBuilder builder, MXMLTagData tag, MXMLNodeInfo info) { super.initializationComplete(builder, tag, info); // If the last child unit was part of the default property, // we don't know to process the default property units // until we get here. processNonDefaultPropertyContentUnit(builder, info); setChildren(info.getChildNodeList().toArray(new IMXMLNode[0])); // If the class references by this node implements mx.core.IContainer, // add an expression dependency on mx.core.UIComponentDescriptor // because we'll have to codegen descriptors. if (isContainer) { FlexProject project = builder.getProject(); builder.addExpressionDependency(project.getUIComponentDescriptorClass()); } }
/** Determines, and caches, the default property for the class to which this node refers. */ private IVariableDefinition getDefaultPropertyDefinition(MXMLTreeBuilder builder) { if (!defaultPropertyDefinitionInitialized) { FlexProject project = builder.getProject(); String defaultPropertyName = classReference.getDefaultPropertyName(project); if (defaultPropertyName != null) { defaultPropertyDefinition = (IVariableDefinition) project.resolveSpecifier(classReference, defaultPropertyName); } defaultPropertyDefinitionInitialized = true; } return defaultPropertyDefinition; }
@Override protected void processChildTag( MXMLTreeBuilder builder, MXMLTagData tag, MXMLTagData childTag, MXMLNodeInfo info) { if (info.hasSpecifierWithName(childTag.getShortName(), childTag.getStateName())) { ICompilerProblem problem = new MXMLDuplicateChildTagProblem(childTag); builder.addProblem(problem); return; } FlexProject project = builder.getProject(); // Handle child tags that are property/style/event specifiers. MXMLSpecifierNodeBase childNode = createSpecifierNode(builder, childTag.getShortName()); if (childNode != null) { // This tag is not part of the default property value. processNonDefaultPropertyContentUnit(builder, info); childNode.setSuffix(builder, childTag.getStateName()); childNode.initializeFromTag(builder, childTag); info.addChildNode(childNode); } else if (builder.getFileScope().isScriptTag(childTag) && (builder.getMXMLDialect().isEqualToOrBefore(MXMLDialect.MXML_2009))) { // In MXML 2006 and 2009, allow a <Script> tag // inside any class reference tag if (!processingDefaultProperty) { // Not processing the default property, just make a script // node and put it in the tree. MXMLScriptNode scriptNode = new MXMLScriptNode(this); scriptNode.initializeFromTag(builder, childTag); info.addChildNode(scriptNode); } else { // We are processing a default property. Script nodes need // to be a child of that default specifier nodes so that // finding a node by offset works properly. // See: http://bugs.adobe.com/jira/browse/CMP-955 processDefaultPropertyContentUnit(builder, childTag, info); } } else if (builder.getFileScope().isReparentTag(childTag)) { MXMLReparentNode reparentNode = new MXMLReparentNode(this); reparentNode.initializeFromTag(builder, childTag); info.addChildNode(reparentNode); } else { IDefinition definition = builder.getFileScope().resolveTagToDefinition(childTag); if (definition instanceof ClassDefinition) { // Handle child tags that are instance tags. IVariableDefinition defaultPropertyDefinition = getDefaultPropertyDefinition(builder); if (defaultPropertyDefinition != null && !processedDefaultProperty) { // Since there is a default property and we haven't already processed it, // assume this child instance tag is part of its value. processDefaultPropertyContentUnit(builder, childTag, info); } else { // This tag is not part of the default property value. processNonDefaultPropertyContentUnit(builder, info); MXMLInstanceNode instanceNode = MXMLInstanceNode.createInstanceNode(builder, definition.getQualifiedName(), this); instanceNode.setClassReference( project, (IClassDefinition) definition); // TODO Move this logic to initializeFromTag(). instanceNode.initializeFromTag(builder, childTag); info.addChildNode(instanceNode); } } else { // Handle child tags that are something other than property/style/event tags // or instance tags. // This tag is not part of the default property value. processNonDefaultPropertyContentUnit(builder, info); super.processChildTag(builder, tag, childTag, info); } } }