-
Notifications
You must be signed in to change notification settings - Fork 19
/
ESLintSniff.php
121 lines (108 loc) · 3.01 KB
/
ESLintSniff.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
<?php
namespace HM\Sniffs\Debug;
use PHP_CodeSniffer\Config;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
/**
* Run ESLint on the file.
*/
class ESLintSniff implements Sniff {
/**
* Path to default configuration.
*/
const DEFAULT_CONFIG = 'vendor/humanmade/coding-standards/packages/eslint-config-humanmade/.eslintrc';
/**
* A list of tokenizers this sniff supports.
*
* @var array
*/
public $supportedTokenizers = [ 'JS' ];
/**
* ESLint configuration file path.
*
* @var string|null Path to eslintrc. Null to autodetect.
*/
public $configFile = null;
/**
* Returns the token types that this sniff is interested in.
*
* @return int[]
*/
public function register() {
return array(T_OPEN_TAG);
}
/**
* Processes the tokens that this sniff is interested in.
*
* @param File $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where
* the token was found.
*
* @return void
* @throws PHP_CodeSniffer_Exception If jslint.js could not be run
*/
public function process( File $phpcsFile, $stackPtr ) {
$filename = $phpcsFile->getFilename();
$eslint_path = Config::getConfigData( 'eslint_path' );
if ( $eslint_path === null ) {
return;
}
$config_file = $this->configFile;
if ( empty( $config_file ) ) {
// Attempt to autodetect.
$candidates = glob( '.eslintrc{.js,.yaml,.yml,.json}', GLOB_BRACE );
if ( ! empty( $candidates ) ) {
$config_file = $candidates[0];
} else {
$config_file = static::DEFAULT_CONFIG;
}
}
$eslint_options = [
sprintf( '--config %s', $config_file ),
'--format json',
];
$cmd = sprintf(
'"%s" %s "%s"',
$eslint_path,
implode( ' ', $eslint_options ),
$filename
);
$descriptors = [
0 => [ 'pipe', 'r' ],
1 => [ 'pipe', 'w' ],
2 => [ 'pipe', 'w' ],
];
$env = array_merge( $_ENV, [
'NODE_PATH' => dirname( dirname( dirname( __DIR__ ) ) ) . '/packages',
] );
$process = proc_open( $cmd, $descriptors, $pipes, null, $env );
// Ignore stdin.
fclose( $pipes[0] );
$stdout = stream_get_contents( $pipes[1] );
$stderr = stream_get_contents( $pipes[2] );
fclose( $pipes[1] );
fclose( $pipes[2] );
// Close, and start working!
$code = proc_close( $process );
if ( $code > 0 ) {
$data = json_decode( $stdout );
// Detect errors:
if ( json_last_error() !== JSON_ERROR_NONE ) {
$error = 'Unable to run eslint: %s';
$phpcsFile->addError( $error, $stackPtr, 'CouldNotStart', [ $stdout ] );
} else {
// Data is a list of files, but we only pass a single one.
$messages = $data[0]->messages;
foreach ( $messages as $error ) {
if ( ! empty( $error->fatal ) || $error->severity === 2 ) {
$phpcsFile->addErrorOnLine( $error->message, $error->line, $error->ruleId );
} else {
$phpcsFile->addWarningOnLine( $error->message, $error->line, $error->ruleId );
}
}
}
}
// Ignore the rest of the file.
return ($phpcsFile->numTokens + 1);
}
}