private void setAdditionVisitor ( ) { setAdditionVisitor ( new InclusiveNodeVisitor ( ) { /** * Add parameter set as a child for printing input, but also add each defined value to the variable map. */ @ Override public boolean add ( ParametersNode node ) { for ( VariableDefinitionNode variable : NodeTreeUtils . getChildren ( node , VariableDefinitionNode . class ) ) { _parameterDefinitions . add ( variable ) ; add ( variable ) ; } return super . add ( node ) ; } /** * Store the rule set's scope by selector group */ @ Override public boolean add ( RuleSetNode node ) { SelectorGroupNode selectorGroup = NodeTreeUtils . getFirstChild ( node , SelectorGroupNode . class ) ; for ( SelectorNode selectorNode : NodeTreeUtils . getChildren ( selectorGroup , SelectorNode . class ) ) { StringBuilder sb = new StringBuilder ( ) ; for ( Node selectorChild : selectorNode . getChildren ( ) ) { sb . append ( selectorChild . toString ( ) ) ; } String selector = sb . toString ( ) ; // Mixins lock on first definition if ( ! _selectorToRuleSetMap . containsKey ( selector ) ) { _selectorToRuleSetMap . put ( selector , node ) ; } } return super . add ( node ) ; } /** * Absorb all children of the given scope. This assumes that cloning is not necessary. */ @ Override public boolean add ( ScopeNode node ) { NodeTreeUtils . moveChildren ( node , ScopeNode . this ) ; return false ; // Don't add the original scope itself } /** * Store variable definitions in a map by name */ @ Override public boolean add ( VariableDefinitionNode node ) { String name = node . getName ( ) ; // "Variables" lock on first definition if ( ! _variableNameToValueMap . containsKey ( name ) ) { _variableNameToValueMap . put ( name , NodeTreeUtils . getFirstChild ( node , ExpressionGroupNode . class ) ) ; } return super . add ( node ) ; } /** * Store property nodes by name. If there are multiple properties for a given name, only retain the last one. */ @ Override public boolean add ( PropertyNode node ) { String name = node . getName ( ) ; // If this is the IE-specific "filter" property, always add it if ( name . equals ( FILTER_PROPERTY ) ) { return super . add ( node ) ; } // If the value of this property node is a vendor-specific keyword, always add it if ( node . getChildren ( ) . get ( 0 ) . toString ( ) . startsWith ( "-" ) ) { return super . add ( node ) ; } // Check if this property has been seen before if ( _propertyNameToNodeMap . containsKey ( name ) ) { PropertyNode oldPropertyNode = _propertyNameToNodeMap . get ( name ) ; int oldPropertyIndex = getChildren ( ) . indexOf ( oldPropertyNode ) ; if ( oldPropertyNode . isVisible ( ) ) { // Hide the unneeded property oldPropertyNode . setVisible ( false ) ; // Attempt to hide one surrounding white space node if ( ! hideWhiteSpaceNode ( oldPropertyIndex - 1 ) ) { hideWhiteSpaceNode ( oldPropertyIndex + 1 ) ; } } } // Store the property as the latest for this name _propertyNameToNodeMap . put ( name , node ) ; return super . add ( node ) ; } } ) ; }
Some nodes are captured in additional structures to aid later resolution .