Files
2013-04-04 08:54:25 -04:00

146 lines
4.5 KiB
Python

import re
import os
import subprocess
try:
import simplejson
except ImportError:
import json as simplejson
from base_linter import BaseLinter, TEMPFILES_DIR
CONFIG = {'language': 'CoffeeScript'}
class Linter(BaseLinter):
coffeelint_config = {}
def _test_executable(self, executable):
try:
args = [executable]
args.extend(self.test_existence_args)
subprocess.Popen(
args,
startupinfo=self.get_startupinfo(),
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
).communicate()
return True
except OSError:
return False
def get_executable(self, view):
if os.name == 'nt':
lint_command, coffee_command = (
'coffeelint.cmd',
'coffee.cmd',
)
else:
lint_command, coffee_command = (
'coffeelint',
'coffee',
)
executable = None
if self._test_executable(lint_command):
executable = lint_command
self.mode = 'coffeelint'
elif self._test_executable(coffee_command):
self.mode = 'coffee'
executable = coffee_command
enabled = executable != None
return (
enabled,
executable,
'using "%s" for executable' % executable if enabled else 'neither coffeelint nor coffee are available'
)
def get_lint_args(self, view, code, filename):
if self.mode == 'coffeelint':
args = [
'--stdin',
'--nocolor',
'--csv',
]
new_config = view.settings().get('coffeelint_options', {})
if new_config != {}:
# config based on tab/space and indentation settings set in
# ST2 if these values aren't already set
new_config['no_tabs']['level'] = new_config['no_tabs'].get(
'level',
'error' if view.settings().get('translate_tabs_to_spaces', False) else 'ignore'
)
new_config['indentation']['value'] = new_config['indentation'].get(
'value',
view.settings().get('tab_size', 8) if view.settings().get('translate_tabs_to_spaces', False) else 1
)
if new_config != self.coffeelint_config:
self.coffeelint_config = new_config
self.write_config_file()
args += ['--file', self.coffeelint_config_file]
return args
else:
return ('-s', '-l')
def parse_errors(self, view, errors, lines, errorUnderlines,
violationUnderlines, warningUnderlines, errorMessages,
violationMessages, warningMessages):
for line in errors.splitlines():
match = re.match(
r'(?:stdin,\d+,error,)?Error: Parse error on line (?P<line>\d+): (?P<error>.+)',
line
)
if match == None:
match = re.match(
r'stdin,(?P<line>\d+),(?P<type>[a-z]+),(?P<error>.*)',
line
)
if match == None:
match = re.match(
r'Error: (?P<error>.+) on line (?P<line>\d+)',
line
)
if match:
line_num, error_text = (
int(match.group('line')),
match.group('error'),
)
try:
error_type = match.group('type')
except IndexError:
error_type = None
self.add_message(
line_num,
lines,
error_text,
errorMessages if error_type == 'error' else warningMessages
)
def write_config_file(self):
"""
coffeelint requires a config file to be able to pass configuration
variables to the program. this function writes a configuration file to
hold them and sets the location of the file
"""
self.coffeelint_config_file = os.path.join(TEMPFILES_DIR, 'coffeelint.json')
temp_file = open(self.coffeelint_config_file, 'w')
temp_file.write(
simplejson.dumps(
self.coffeelint_config,
separators=(',', ':')
)
)
temp_file.close()