forked from SublimeLinter/SublimeLinter-eslint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
linter.py
129 lines (107 loc) · 4 KB
/
linter.py
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
122
123
124
125
126
127
128
129
#
# linter.py
# Linter for SublimeLinter3, a code checking framework for Sublime Text 3
#
# Written by roadhump
# Copyright (c) 2014 roadhump
#
# License: MIT
#
"""This module exports the ESLint plugin class."""
import json
import logging
import re
from SublimeLinter.lint import NodeLinter, LintMatch
logger = logging.getLogger('SublimeLinter.plugin.eslint')
class ESLint(NodeLinter):
"""Provides an interface to the eslint executable."""
cmd = 'eslint --format json --stdin'
missing_config_regex = re.compile(
r'^(.*?)\r?\n\w*(ESLint couldn\'t find a configuration file.)',
re.DOTALL
)
line_col_base = (1, 1)
defaults = {
'selector': 'source.js - meta.attribute-with-value',
'--stdin-filename': '${file}'
}
def on_stderr(self, stderr):
# Demote 'annoying' config is missing error to a warning.
if self.missing_config_regex.match(stderr):
logger.warning(stderr)
self.notify_failure()
elif (
'DeprecationWarning' in stderr
or 'ExperimentalWarning' in stderr
or 'in the next version' in stderr # is that a proper deprecation?
):
logger.warning(stderr)
else:
logger.error(stderr)
self.notify_failure()
def find_errors(self, output):
"""Parse errors from linter's output."""
try:
# It is possible that users output debug messages to stdout, so we
# only parse the last line, which is hopefully the actual eslint
# output.
# https://github.com/SublimeLinter/SublimeLinter-eslint/issues/251
last_line = output.rstrip().split('\n')[-1]
content = json.loads(last_line)
except ValueError:
logger.error(
"JSON Decode error: We expected JSON from 'eslint', "
"but instead got this:\n{}\n\n"
"Be aware that we only parse the last line of above "
"output.".format(output))
self.notify_failure()
return
if logger.isEnabledFor(logging.INFO):
import pprint
logger.info(
'{} output:\n{}'.format(self.name, pprint.pformat(content)))
for entry in content:
filename = entry.get('filePath', None)
if filename == '<text>':
filename = 'stdin'
for match in entry['messages']:
if match['message'].startswith('File ignored'):
continue
column = match.get('column', None)
if column is not None:
# apply line_col_base manually
column = column - 1
if 'line' not in match:
logger.error(match['message'])
self.notify_failure()
continue
yield LintMatch(
match=match,
filename=filename,
line=match['line'] - 1, # apply line_col_base manually
col=column,
error_type='error' if match['severity'] == 2 else 'warning',
code=match.get('ruleId', ''),
message=match['message'],
)
def reposition_match(self, line, col, m, vv):
match = m.match
if (
col is None
or 'endLine' not in match
or 'endColumn' not in match
):
return super().reposition_match(line, col, m, vv)
# apply line_col_base manually
end_line = match['endLine'] - 1
end_column = match['endColumn'] - 1
for _line in range(line, end_line):
text = vv.select_line(_line)
end_column += len(text)
return line, col, end_column
def run(self, cmd, code):
# Workaround eslint bug https://github.com/eslint/eslint/issues/9515
# Fixed in eslint 4.10.0
if code == '':
code = ' '
return super().run(cmd, code)