selector = new Less_Tree_Selector( $elements ); $this->arguments = $args; $this->index = $index; $this->currentFileInfo = $currentFileInfo; $this->important = $important; } // function accept($visitor){ // $this->selector = $visitor->visit($this->selector); // $this->arguments = $visitor->visit($this->arguments); //} public function compile( $env ) { $rules = array(); $match = false; $isOneFound = false; $candidates = array(); $defaultUsed = false; $conditionResult = array(); $args = array(); foreach ( $this->arguments as $a ) { $args[] = array( 'name' => $a['name'], 'value' => $a['value']->compile( $env ) ); } foreach ( $env->frames as $frame ) { $mixins = $frame->find( $this->selector ); if ( !$mixins ) { continue; } $isOneFound = true; $defNone = 0; $defTrue = 1; $defFalse = 2; // To make `default()` function independent of definition order we have two "subpasses" here. // At first we evaluate each guard *twice* (with `default() == true` and `default() == false`), // and build candidate list with corresponding flags. Then, when we know all possible matches, // we make a final decision. $mixins_len = count( $mixins ); for ( $m = 0; $m < $mixins_len; $m++ ) { $mixin = $mixins[$m]; if ( $this->IsRecursive( $env, $mixin ) ) { continue; } if ( $mixin->matchArgs( $args, $env ) ) { $candidate = array( 'mixin' => $mixin, 'group' => $defNone ); if ( $mixin instanceof Less_Tree_Ruleset ) { for ( $f = 0; $f < 2; $f++ ) { Less_Tree_DefaultFunc::value( $f ); $conditionResult[$f] = $mixin->matchCondition( $args, $env ); } if ( $conditionResult[0] || $conditionResult[1] ) { if ( $conditionResult[0] != $conditionResult[1] ) { $candidate['group'] = $conditionResult[1] ? $defTrue : $defFalse; } $candidates[] = $candidate; } } else { $candidates[] = $candidate; } $match = true; } } Less_Tree_DefaultFunc::reset(); $count = array( 0, 0, 0 ); for ( $m = 0; $m < count( $candidates ); $m++ ) { $count[ $candidates[$m]['group'] ]++; } if ( $count[$defNone] > 0 ) { $defaultResult = $defFalse; } else { $defaultResult = $defTrue; if ( ( $count[$defTrue] + $count[$defFalse] ) > 1 ) { throw new Exception( 'Ambiguous use of `default()` found when matching for `' . $this->format( $args ) . '`' ); } } $candidates_length = count( $candidates ); $length_1 = ( $candidates_length == 1 ); for ( $m = 0; $m < $candidates_length; $m++ ) { $candidate = $candidates[$m]['group']; if ( ( $candidate === $defNone ) || ( $candidate === $defaultResult ) ) { try{ $mixin = $candidates[$m]['mixin']; if ( !( $mixin instanceof Less_Tree_Mixin_Definition ) ) { $mixin = new Less_Tree_Mixin_Definition( '', array(), $mixin->rules, null, false ); $mixin->originalRuleset = $mixins[$m]->originalRuleset; } $rules = array_merge( $rules, $mixin->evalCall( $env, $args, $this->important )->rules ); } catch ( Exception $e ) { // throw new Less_Exception_Compiler($e->getMessage(), $e->index, null, $this->currentFileInfo['filename']); throw new Less_Exception_Compiler( $e->getMessage(), null, null, $this->currentFileInfo ); } } } if ( $match ) { if ( !$this->currentFileInfo || !isset( $this->currentFileInfo['reference'] ) || !$this->currentFileInfo['reference'] ) { Less_Tree::ReferencedArray( $rules ); } return $rules; } } if ( $isOneFound ) { throw new Less_Exception_Compiler( 'No matching definition was found for `'.$this->Format( $args ).'`', null, $this->index, $this->currentFileInfo ); } else { throw new Less_Exception_Compiler( trim( $this->selector->toCSS() ) . " is undefined in ".$this->currentFileInfo['filename'], null, $this->index ); } } /** * Format the args for use in exception messages * */ private function Format( $args ) { $message = array(); if ( $args ) { foreach ( $args as $a ) { $argValue = ''; if ( $a['name'] ) { $argValue .= $a['name'] . ':'; } if ( is_object( $a['value'] ) ) { $argValue .= $a['value']->toCSS(); } else { $argValue .= '???'; } $message[] = $argValue; } } return implode( ', ', $message ); } /** * Are we in a recursive mixin call? * * @return bool */ private function IsRecursive( $env, $mixin ) { foreach ( $env->frames as $recur_frame ) { if ( !( $mixin instanceof Less_Tree_Mixin_Definition ) ) { if ( $mixin === $recur_frame ) { return true; } if ( isset( $recur_frame->originalRuleset ) && $mixin->ruleset_id === $recur_frame->originalRuleset ) { return true; } } } return false; } }