This repository has been archived by the owner on Mar 7, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
linter.py
88 lines (73 loc) · 3.12 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
#
# linter.py
# Linter for SublimeLinter3, a code checking framework for Sublime Text 3
#
# Written by Alec Thomas
# Copyright (c) 2014 Alec Thomas
#
# License: MIT
#
"""This module exports the Gometalinter plugin class."""
import os
import shlex
import tempfile
from SublimeLinter.lint import Linter, highlight, util
from SublimeLinter.lint.persist import settings
class GolangCILint(Linter):
"""Provides an interface to golangci-lint."""
syntax = ('go', 'gosublime-go', 'gotools', 'anacondago-go')
cmd = 'golangci-lint run --fast --enable typecheck'
regex = r'(?:[^:]+):(?P<line>\d+):(?P<col>\d+)?:\s*(?P<message>.*)'
error_stream = util.STREAM_BOTH
default_type = highlight.ERROR
def run(self, cmd, code):
filename = os.path.basename(self.filename)
if settings.get('lint_mode') == 'background':
out = self._live_lint(cmd, code)
else:
out = self._in_place_lint(cmd)
lines = [line for line in out.splitlines()
if line.startswith(filename + ':')]
return '\n'.join(lines)
def _dir_env(self):
settings = self.get_view_settings()
dir = os.path.dirname(self.filename)
env = self.get_environment(settings)
return dir, env
def _live_lint(self, cmd, code):
dir, env = self._dir_env()
if not dir:
print('golangci-lint: skipped linting of unsaved file')
return
filename = os.path.basename(self.filename)
print('golangci-lint: live linting {} in {}: {}'.format(filename, dir, ' '.join(map(shlex.quote, cmd))))
files = [f for f in os.listdir(dir) if f.endswith('.go')]
if len(files) > 40:
print("golangci-lint: too many files ({}), live linting skipped".format(len(files)))
return ''
return tmpdir(cmd, dir, files, self.filename, code, env=env)
def _in_place_lint(self, cmd):
dir, env = self._dir_env()
if not dir:
print('golangci-lint: skipped linting of unsaved file')
return
filename = os.path.basename(self.filename)
print('golangci-lint: in-place linting {}: {}'.format(filename, ' '.join(map(shlex.quote, cmd))))
out = util.communicate(cmd, output_stream=util.STREAM_BOTH, env=env, cwd=dir)
return out or ''
def tmpdir(cmd, dir, files, filename, code, env=None):
"""Run an external executable using a temp dir filled with files and return its output."""
with tempfile.TemporaryDirectory(dir=dir, prefix=".golangci-lint-") as tmpdir:
for f in files:
target = os.path.join(tmpdir, f)
f = os.path.join(dir, f)
if os.path.basename(target) == os.path.basename(filename):
# source file hasn't been saved since change, so update it from our live buffer
with open(target, 'wb') as f:
if isinstance(code, str):
code = code.encode('utf8')
f.write(code)
else:
os.link(f, target)
out = util.communicate(cmd, output_stream=util.STREAM_BOTH, env=env, cwd=tmpdir)
return out or ''