JavaScriptMinifier: Enable phpcs and fix violations

Found 90 violations. 88 fixed by phpxbf. 2 remaining violations
were Generic.Files.LineLength.TooLong (fixed manually).

Change-Id: I760acc5b249fe6f4863652de7b563eaa5f13f05f
This commit is contained in:
Timo Tijhof 2018-01-11 22:21:53 +00:00
parent f2ef535e39
commit d43cbc7ca9

View file

@ -1,5 +1,4 @@
<?php
// phpcs:ignoreFile -- File external to MediaWiki. Ignore coding conventions checks.
/**
* JavaScript Minifier
*
@ -78,7 +77,7 @@ class JavaScriptMinifier {
// First we declare a few tables that contain our parsing rules
// $opChars : characters, which can be combined without whitespace in between them
$opChars = array(
$opChars = [
'!' => true,
'"' => true,
'%' => true,
@ -105,10 +104,10 @@ class JavaScriptMinifier {
'|' => true,
'}' => true,
'~' => true
);
];
// $tokenTypes : maps keywords and operators to their corresponding token type
$tokenTypes = array(
$tokenTypes = [
'!' => self::TYPE_UN_OP,
'~' => self::TYPE_UN_OP,
'delete' => self::TYPE_UN_OP,
@ -180,13 +179,13 @@ class JavaScriptMinifier {
'try' => self::TYPE_DO,
'var' => self::TYPE_DO,
'function' => self::TYPE_FUNC
);
];
// $goto : This is the main table for our state machine. For every state/token pair
// the following state is defined. When no rule exists for a given pair,
// the state is left unchanged.
$goto = array(
self::STATEMENT => array(
$goto = [
self::STATEMENT => [
self::TYPE_UN_OP => self::EXPRESSION,
self::TYPE_INCR_OP => self::EXPRESSION,
self::TYPE_ADD_OP => self::EXPRESSION,
@ -195,29 +194,29 @@ class JavaScriptMinifier {
self::TYPE_IF => self::CONDITION,
self::TYPE_FUNC => self::CONDITION,
self::TYPE_LITERAL => self::EXPRESSION_OP
),
self::CONDITION => array(
],
self::CONDITION => [
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
),
self::PROPERTY_ASSIGNMENT => array(
],
self::PROPERTY_ASSIGNMENT => [
self::TYPE_COLON => self::PROPERTY_EXPRESSION,
self::TYPE_BRACE_OPEN => self::STATEMENT
),
self::EXPRESSION => array(
],
self::EXPRESSION => [
self::TYPE_SEMICOLON => self::STATEMENT,
self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
self::TYPE_FUNC => self::EXPRESSION_FUNC,
self::TYPE_LITERAL => self::EXPRESSION_OP
),
self::EXPRESSION_NO_NL => array(
],
self::EXPRESSION_NO_NL => [
self::TYPE_SEMICOLON => self::STATEMENT,
self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
self::TYPE_FUNC => self::EXPRESSION_FUNC,
self::TYPE_LITERAL => self::EXPRESSION_OP
),
self::EXPRESSION_OP => array(
],
self::EXPRESSION_OP => [
self::TYPE_BIN_OP => self::EXPRESSION,
self::TYPE_ADD_OP => self::EXPRESSION,
self::TYPE_HOOK => self::EXPRESSION_TERNARY,
@ -225,33 +224,33 @@ class JavaScriptMinifier {
self::TYPE_COMMA => self::EXPRESSION,
self::TYPE_SEMICOLON => self::STATEMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
),
self::EXPRESSION_FUNC => array(
],
self::EXPRESSION_FUNC => [
self::TYPE_BRACE_OPEN => self::STATEMENT
),
self::EXPRESSION_TERNARY => array(
],
self::EXPRESSION_TERNARY => [
self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
self::TYPE_FUNC => self::EXPRESSION_TERNARY_FUNC,
self::TYPE_LITERAL => self::EXPRESSION_TERNARY_OP
),
self::EXPRESSION_TERNARY_OP => array(
],
self::EXPRESSION_TERNARY_OP => [
self::TYPE_BIN_OP => self::EXPRESSION_TERNARY,
self::TYPE_ADD_OP => self::EXPRESSION_TERNARY,
self::TYPE_HOOK => self::EXPRESSION_TERNARY,
self::TYPE_COMMA => self::EXPRESSION_TERNARY,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
),
self::EXPRESSION_TERNARY_FUNC => array(
],
self::EXPRESSION_TERNARY_FUNC => [
self::TYPE_BRACE_OPEN => self::STATEMENT
),
self::PAREN_EXPRESSION => array(
],
self::PAREN_EXPRESSION => [
self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
self::TYPE_FUNC => self::PAREN_EXPRESSION_FUNC,
self::TYPE_LITERAL => self::PAREN_EXPRESSION_OP
),
self::PAREN_EXPRESSION_OP => array(
],
self::PAREN_EXPRESSION_OP => [
self::TYPE_BIN_OP => self::PAREN_EXPRESSION,
self::TYPE_ADD_OP => self::PAREN_EXPRESSION,
self::TYPE_HOOK => self::PAREN_EXPRESSION,
@ -259,107 +258,107 @@ class JavaScriptMinifier {
self::TYPE_COMMA => self::PAREN_EXPRESSION,
self::TYPE_SEMICOLON => self::PAREN_EXPRESSION,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
),
self::PAREN_EXPRESSION_FUNC => array(
],
self::PAREN_EXPRESSION_FUNC => [
self::TYPE_BRACE_OPEN => self::STATEMENT
),
self::PROPERTY_EXPRESSION => array(
],
self::PROPERTY_EXPRESSION => [
self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
self::TYPE_FUNC => self::PROPERTY_EXPRESSION_FUNC,
self::TYPE_LITERAL => self::PROPERTY_EXPRESSION_OP
),
self::PROPERTY_EXPRESSION_OP => array(
],
self::PROPERTY_EXPRESSION_OP => [
self::TYPE_BIN_OP => self::PROPERTY_EXPRESSION,
self::TYPE_ADD_OP => self::PROPERTY_EXPRESSION,
self::TYPE_HOOK => self::PROPERTY_EXPRESSION,
self::TYPE_COMMA => self::PROPERTY_ASSIGNMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
),
self::PROPERTY_EXPRESSION_FUNC => array(
],
self::PROPERTY_EXPRESSION_FUNC => [
self::TYPE_BRACE_OPEN => self::STATEMENT
)
);
]
];
// $push : This table contains the rules for when to push a state onto the stack.
// The pushed state is the state to return to when the corresponding
// closing token is found
$push = array(
self::STATEMENT => array(
$push = [
self::STATEMENT => [
self::TYPE_BRACE_OPEN => self::STATEMENT,
self::TYPE_PAREN_OPEN => self::EXPRESSION_OP
),
self::CONDITION => array(
],
self::CONDITION => [
self::TYPE_PAREN_OPEN => self::STATEMENT
),
self::PROPERTY_ASSIGNMENT => array(
],
self::PROPERTY_ASSIGNMENT => [
self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT
),
self::EXPRESSION => array(
],
self::EXPRESSION => [
self::TYPE_BRACE_OPEN => self::EXPRESSION_OP,
self::TYPE_PAREN_OPEN => self::EXPRESSION_OP
),
self::EXPRESSION_NO_NL => array(
],
self::EXPRESSION_NO_NL => [
self::TYPE_BRACE_OPEN => self::EXPRESSION_OP,
self::TYPE_PAREN_OPEN => self::EXPRESSION_OP
),
self::EXPRESSION_OP => array(
],
self::EXPRESSION_OP => [
self::TYPE_HOOK => self::EXPRESSION,
self::TYPE_PAREN_OPEN => self::EXPRESSION_OP
),
self::EXPRESSION_FUNC => array(
],
self::EXPRESSION_FUNC => [
self::TYPE_BRACE_OPEN => self::EXPRESSION_OP
),
self::EXPRESSION_TERNARY => array(
],
self::EXPRESSION_TERNARY => [
self::TYPE_BRACE_OPEN => self::EXPRESSION_TERNARY_OP,
self::TYPE_PAREN_OPEN => self::EXPRESSION_TERNARY_OP
),
self::EXPRESSION_TERNARY_OP => array(
],
self::EXPRESSION_TERNARY_OP => [
self::TYPE_HOOK => self::EXPRESSION_TERNARY,
self::TYPE_PAREN_OPEN => self::EXPRESSION_TERNARY_OP
),
self::EXPRESSION_TERNARY_FUNC => array(
],
self::EXPRESSION_TERNARY_FUNC => [
self::TYPE_BRACE_OPEN => self::EXPRESSION_TERNARY_OP
),
self::PAREN_EXPRESSION => array(
],
self::PAREN_EXPRESSION => [
self::TYPE_BRACE_OPEN => self::PAREN_EXPRESSION_OP,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION_OP
),
self::PAREN_EXPRESSION_OP => array(
],
self::PAREN_EXPRESSION_OP => [
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION_OP
),
self::PAREN_EXPRESSION_FUNC => array(
],
self::PAREN_EXPRESSION_FUNC => [
self::TYPE_BRACE_OPEN => self::PAREN_EXPRESSION_OP
),
self::PROPERTY_EXPRESSION => array(
],
self::PROPERTY_EXPRESSION => [
self::TYPE_BRACE_OPEN => self::PROPERTY_EXPRESSION_OP,
self::TYPE_PAREN_OPEN => self::PROPERTY_EXPRESSION_OP
),
self::PROPERTY_EXPRESSION_OP => array(
],
self::PROPERTY_EXPRESSION_OP => [
self::TYPE_PAREN_OPEN => self::PROPERTY_EXPRESSION_OP
),
self::PROPERTY_EXPRESSION_FUNC => array(
],
self::PROPERTY_EXPRESSION_FUNC => [
self::TYPE_BRACE_OPEN => self::PROPERTY_EXPRESSION_OP
)
);
]
];
// $pop : Rules for when to pop a state from the stack
$pop = array(
self::STATEMENT => array( self::TYPE_BRACE_CLOSE => true ),
self::PROPERTY_ASSIGNMENT => array( self::TYPE_BRACE_CLOSE => true ),
self::EXPRESSION => array( self::TYPE_BRACE_CLOSE => true ),
self::EXPRESSION_NO_NL => array( self::TYPE_BRACE_CLOSE => true ),
self::EXPRESSION_OP => array( self::TYPE_BRACE_CLOSE => true ),
self::EXPRESSION_TERNARY_OP => array( self::TYPE_COLON => true ),
self::PAREN_EXPRESSION => array( self::TYPE_PAREN_CLOSE => true ),
self::PAREN_EXPRESSION_OP => array( self::TYPE_PAREN_CLOSE => true ),
self::PROPERTY_EXPRESSION => array( self::TYPE_BRACE_CLOSE => true ),
self::PROPERTY_EXPRESSION_OP => array( self::TYPE_BRACE_CLOSE => true )
);
$pop = [
self::STATEMENT => [ self::TYPE_BRACE_CLOSE => true ],
self::PROPERTY_ASSIGNMENT => [ self::TYPE_BRACE_CLOSE => true ],
self::EXPRESSION => [ self::TYPE_BRACE_CLOSE => true ],
self::EXPRESSION_NO_NL => [ self::TYPE_BRACE_CLOSE => true ],
self::EXPRESSION_OP => [ self::TYPE_BRACE_CLOSE => true ],
self::EXPRESSION_TERNARY_OP => [ self::TYPE_COLON => true ],
self::PAREN_EXPRESSION => [ self::TYPE_PAREN_CLOSE => true ],
self::PAREN_EXPRESSION_OP => [ self::TYPE_PAREN_CLOSE => true ],
self::PROPERTY_EXPRESSION => [ self::TYPE_BRACE_CLOSE => true ],
self::PROPERTY_EXPRESSION_OP => [ self::TYPE_BRACE_CLOSE => true ]
];
// $semicolon : Rules for when a semicolon insertion is appropriate
$semicolon = array(
self::EXPRESSION_NO_NL => array(
$semicolon = [
self::EXPRESSION_NO_NL => [
self::TYPE_UN_OP => true,
self::TYPE_INCR_OP => true,
self::TYPE_ADD_OP => true,
@ -370,8 +369,8 @@ class JavaScriptMinifier {
self::TYPE_DO => true,
self::TYPE_FUNC => true,
self::TYPE_LITERAL => true
),
self::EXPRESSION_OP => array(
],
self::EXPRESSION_OP => [
self::TYPE_UN_OP => true,
self::TYPE_INCR_OP => true,
self::TYPE_BRACE_OPEN => true,
@ -380,16 +379,16 @@ class JavaScriptMinifier {
self::TYPE_DO => true,
self::TYPE_FUNC => true,
self::TYPE_LITERAL => true
)
);
]
];
// $divStates : Contains all states that can be followed by a division operator
$divStates = array(
$divStates = [
self::EXPRESSION_OP => true,
self::EXPRESSION_TERNARY_OP => true,
self::PAREN_EXPRESSION_OP => true,
self::PROPERTY_EXPRESSION_OP => true
);
];
// Here's where the minifying takes place: Loop through the input, looking for tokens
// and output them to $out, taking actions to the above defined rules when appropriate.
@ -399,24 +398,24 @@ class JavaScriptMinifier {
$lineLength = 0;
$newlineFound = true;
$state = self::STATEMENT;
$stack = array();
$stack = [];
$last = ';'; // Pretend that we have seen a semicolon yet
while( $pos < $length ) {
while ( $pos < $length ) {
// First, skip over any whitespace and multiline comments, recording whether we
// found any newline character
$skip = strspn( $s, " \t\n\r\xb\xc", $pos );
if( !$skip ) {
if ( !$skip ) {
$ch = $s[$pos];
if( $ch === '/' && substr( $s, $pos, 2 ) === '/*' ) {
if ( $ch === '/' && substr( $s, $pos, 2 ) === '/*' ) {
// Multiline comment. Search for the end token or EOT.
$end = strpos( $s, '*/', $pos + 2 );
$skip = $end === false ? $length - $pos : $end - $pos + 2;
}
}
if( $skip ) {
if ( $skip ) {
// The semicolon insertion mechanism needs to know whether there was a newline
// between two tokens, so record it now.
if( !$newlineFound && strcspn( $s, "\r\n", $pos, $skip ) !== $skip ) {
if ( !$newlineFound && strcspn( $s, "\r\n", $pos, $skip ) !== $skip ) {
$newlineFound = true;
}
$pos += $skip;
@ -425,7 +424,7 @@ class JavaScriptMinifier {
// Handle C++-style comments and html comments, which are treated as single line
// comments by the browser, regardless of whether the end tag is on the same line.
// Handle --> the same way, but only if it's at the beginning of the line
if( ( $ch === '/' && substr( $s, $pos, 2 ) === '//' )
if ( ( $ch === '/' && substr( $s, $pos, 2 ) === '//' )
|| ( $ch === '<' && substr( $s, $pos, 4 ) === '<!--' )
|| ( $ch === '-' && $newlineFound && substr( $s, $pos, 3 ) === '-->' )
) {
@ -441,7 +440,7 @@ class JavaScriptMinifier {
// of any next token in the stream.
$end = $pos + 1;
// Handle string literals
if( $ch === "'" || $ch === '"' ) {
if ( $ch === "'" || $ch === '"' ) {
// Search to the end of the string literal, skipping over backslash escapes
$search = $ch . '\\';
do{
@ -452,7 +451,7 @@ class JavaScriptMinifier {
$end += strcspn( $s, $search, $end ) + 2;
// If the last character in our search for a quote or a backlash
// matched a backslash and we haven't reached the end, keep searching..
} while( $end - 2 < $length && $s[$end - 2] === '\\' );
} while ( $end - 2 < $length && $s[$end - 2] === '\\' );
// Correction (1): Undo speculative add, keep only one (end of string literal)
$end--;
if ( $end > $length ) {
@ -463,9 +462,9 @@ class JavaScriptMinifier {
}
// We have to distinguish between regexp literals and division operators
// A division operator is only possible in certain states
} elseif( $ch === '/' && !isset( $divStates[$state] ) ) {
} elseif ( $ch === '/' && !isset( $divStates[$state] ) ) {
// Regexp literal
for( ; ; ) {
for ( ; ; ) {
// Search until we find "/" (end of regexp), "\" (backslash escapes),
// or "[" (start of character classes).
do{
@ -474,7 +473,7 @@ class JavaScriptMinifier {
// We'll correct this outside the loop.
$end += strcspn( $s, '/[\\', $end ) + 2;
// If backslash escape, keep searching...
} while( $end - 2 < $length && $s[$end - 2] === '\\' );
} while ( $end - 2 < $length && $s[$end - 2] === '\\' );
// Correction (1): Undo speculative add, keep only one (end of regexp)
$end--;
if ( $end > $length ) {
@ -494,41 +493,45 @@ class JavaScriptMinifier {
// We'll substract one outside the loop.
$end += strcspn( $s, ']\\', $end ) + 2;
// If backslash escape, keep searching...
} while( $end - 2 < $length && $s[$end - 2] === '\\' );
} while ( $end - 2 < $length && $s[$end - 2] === '\\' );
// Correction (1): Undo speculative add, keep only one (end of regexp)
$end--;
}
// Search past the regexp modifiers (gi)
while( $end < $length && ctype_alpha( $s[$end] ) ) {
while ( $end < $length && ctype_alpha( $s[$end] ) ) {
$end++;
}
} elseif(
} elseif (
$ch === '0'
&& ($pos + 1 < $length) && ($s[$pos + 1] === 'x' || $s[$pos + 1] === 'X' )
&& ( $pos + 1 < $length ) && ( $s[$pos + 1] === 'x' || $s[$pos + 1] === 'X' )
) {
// Hex numeric literal
$end++; // x or X
$len = strspn( $s, '0123456789ABCDEFabcdef', $end );
if ( !$len ) {
return self::parseError($s, $pos, 'Expected a hexadecimal number but found ' . substr( $s, $pos, 5 ) . '...' );
return self::parseError(
$s,
$pos,
'Expected a hexadecimal number but found ' . substr( $s, $pos, 5 ) . '...'
);
}
$end += $len;
} elseif(
} elseif (
ctype_digit( $ch )
|| ( $ch === '.' && $pos + 1 < $length && ctype_digit( $s[$pos + 1] ) )
) {
$end += strspn( $s, '0123456789', $end );
$decimal = strspn( $s, '.', $end );
if ($decimal) {
if ( $decimal ) {
if ( $decimal > 2 ) {
return self::parseError($s, $end, 'The number has too many decimal points' );
return self::parseError( $s, $end, 'The number has too many decimal points' );
}
$end += strspn( $s, '0123456789', $end + 1 ) + $decimal;
}
$exponent = strspn( $s, 'eE', $end );
if( $exponent ) {
if ( $exponent ) {
if ( $exponent > 1 ) {
return self::parseError($s, $end, 'Number with several E' );
return self::parseError( $s, $end, 'Number with several E' );
}
$end++;
@ -536,13 +539,17 @@ class JavaScriptMinifier {
$end += strspn( $s, '-+', $end );
$len = strspn( $s, '0123456789', $end );
if ( !$len ) {
return self::parseError($s, $pos, 'No decimal digits after e, how many zeroes should be added?' );
return self::parseError(
$s,
$pos,
'No decimal digits after e, how many zeroes should be added?'
);
}
$end += $len;
}
} elseif( isset( $opChars[$ch] ) ) {
} elseif ( isset( $opChars[$ch] ) ) {
// Punctuation character. Search for the longest matching operator.
while(
while (
$end < $length
&& isset( $tokenTypes[substr( $s, $pos, $end - $pos + 1 )] )
) {
@ -558,26 +565,25 @@ class JavaScriptMinifier {
$token = substr( $s, $pos, $end - $pos ); // so $end - $pos == strlen( $token )
$type = isset( $tokenTypes[$token] ) ? $tokenTypes[$token] : self::TYPE_LITERAL;
if( $newlineFound && isset( $semicolon[$state][$type] ) ) {
if ( $newlineFound && isset( $semicolon[$state][$type] ) ) {
// This token triggers the semicolon insertion mechanism of javascript. While we
// could add the ; token here ourselves, keeping the newline has a few advantages.
$out .= "\n";
$state = self::STATEMENT;
$lineLength = 0;
} elseif( $maxLineLength > 0 && $lineLength + $end - $pos > $maxLineLength &&
!isset( $semicolon[$state][$type] ) && $type !== self::TYPE_INCR_OP )
{
} elseif ( $maxLineLength > 0 && $lineLength + $end - $pos > $maxLineLength &&
!isset( $semicolon[$state][$type] ) && $type !== self::TYPE_INCR_OP ) {
// This line would get too long if we added $token, so add a newline first.
// Only do this if it won't trigger semicolon insertion and if it won't
// put a postfix increment operator on its own line, which is illegal in js.
$out .= "\n";
$lineLength = 0;
// Check, whether we have to separate the token from the last one with whitespace
} elseif( !isset( $opChars[$last] ) && !isset( $opChars[$ch] ) ) {
} elseif ( !isset( $opChars[$last] ) && !isset( $opChars[$ch] ) ) {
$out .= ' ';
$lineLength++;
// Don't accidentally create ++, -- or // tokens
} elseif( $last === $ch && ( $ch === '+' || $ch === '-' || $ch === '/' ) ) {
} elseif ( $last === $ch && ( $ch === '+' || $ch === '-' || $ch === '/' ) ) {
$out .= ' ';
$lineLength++;
}
@ -597,19 +603,19 @@ class JavaScriptMinifier {
$newlineFound = false;
// Now that we have output our token, transition into the new state.
if( isset( $push[$state][$type] ) && count( $stack ) < self::STACK_LIMIT ) {
if ( isset( $push[$state][$type] ) && count( $stack ) < self::STACK_LIMIT ) {
$stack[] = $push[$state][$type];
}
if( $stack && isset( $pop[$state][$type] ) ) {
if ( $stack && isset( $pop[$state][$type] ) ) {
$state = array_pop( $stack );
} elseif( isset( $goto[$state][$type] ) ) {
} elseif ( isset( $goto[$state][$type] ) ) {
$state = $goto[$state][$type];
}
}
return $out;
}
static function parseError($fullJavascript, $position, $errorMsg) {
static function parseError( $fullJavascript, $position, $errorMsg ) {
// TODO: Handle the error: trigger_error, throw exception, return false...
return false;
}