move indenter to a new module source.py

Reviewed By: akotulski

Differential Revision: D2642187

fb-gh-sync-id: 92fdfdf
master
Jules Villard 9 years ago committed by facebook-github-bot-7
parent 88b615d8ab
commit 2ec2858b66

@ -21,7 +21,7 @@ import shutil
import subprocess import subprocess
import sys import sys
from inferlib import analyze, utils from inferlib import analyze, source, utils
HTML_REPORT_DIR = 'report.html' HTML_REPORT_DIR = 'report.html'
TRACES_REPORT_DIR = 'traces' TRACES_REPORT_DIR = 'traces'
@ -87,7 +87,7 @@ class Tracer(object):
def __init__(self, args, level=sys.maxsize): def __init__(self, args, level=sys.maxsize):
self.args = args self.args = args
self.max_level = level self.max_level = level
self.indenter = utils.Indenter() self.indenter = source.Indenter()
def build_node_tags(self, node): def build_node_tags(self, node):
pass pass
@ -109,10 +109,10 @@ class Tracer(object):
if not self.args.no_source: if not self.args.no_source:
self.indenter.indent_push(node[utils.JSON_INDEX_TRACE_LEVEL]) self.indenter.indent_push(node[utils.JSON_INDEX_TRACE_LEVEL])
mode = utils.TERMINAL_FORMATTER mode = source.TERMINAL_FORMATTER
if self.args.html: if self.args.html:
mode = utils.PLAIN_FORMATTER mode = source.PLAIN_FORMATTER
self.indenter.add(utils.build_source_context(fname, self.indenter.add(source.build_source_context(fname,
mode, mode,
report_line)) report_line))
self.indenter.indent_pop() self.indenter.indent_pop()

@ -19,7 +19,7 @@ import sys
import tempfile import tempfile
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from . import config, utils from . import config, source, utils
# Increase the limit of the CSV parser to sys.maxlimit # Increase the limit of the CSV parser to sys.maxlimit
@ -117,11 +117,11 @@ def print_errors(json_report, bugs_out):
line = row[utils.JSON_INDEX_LINE] line = row[utils.JSON_INDEX_LINE]
error_type = row[utils.JSON_INDEX_TYPE] error_type = row[utils.JSON_INDEX_TYPE]
msg = row[utils.JSON_INDEX_QUALIFIER] msg = row[utils.JSON_INDEX_QUALIFIER]
indenter = utils.Indenter() indenter = source.Indenter()
indenter.indent_push() indenter.indent_push()
indenter.add( indenter.add(
utils.build_source_context(filename, source.build_source_context(filename,
utils.TERMINAL_FORMATTER, source.TERMINAL_FORMATTER,
int(line))) int(line)))
source_context = unicode(indenter) source_context = unicode(indenter)
text_errors_list.append( text_errors_list.append(

@ -0,0 +1,99 @@
# Copyright (c) 2013 - present Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import codecs
try:
import pygments
import pygments.formatters
import pygments.lexers
except ImportError:
pygments = None
import sys
from . import utils
BASE_INDENT = 2
# how many lines of context around each report
SOURCE_CONTEXT = 2
# syntax highlighting modes
PLAIN_FORMATTER = 0
TERMINAL_FORMATTER = 1
class Indenter(str):
def __init__(self):
super(Indenter, self).__init__()
self.text = ''
self.indent = []
def indent_get(self):
indent = ''
for i in self.indent:
indent += i
return indent
def indent_push(self, n=1):
self.indent.append(n * BASE_INDENT * ' ')
def indent_pop(self):
return self.indent.pop()
def newline(self):
self.text += '\n'
def add(self, x):
if type(x) != unicode:
x = x.decode(utils.LOCALE)
lines = x.splitlines()
indent = self.indent_get()
lines = [indent + l for l in lines]
self.text += '\n'.join(lines)
def __unicode__(self):
return self.text
def __str__(self):
return unicode(self).encode(utils.LOCALE)
def build_source_context(source_name, mode, report_line):
start_line = max(1, report_line - SOURCE_CONTEXT)
# could go beyond last line, checked in the loop
end_line = report_line + SOURCE_CONTEXT
n_length = len(str(end_line))
line_number = 1
s = ''
with codecs.open(source_name, 'r', encoding=utils.LOCALE) as source_file:
for line in source_file:
if start_line <= line_number <= end_line:
num = str(line_number).zfill(n_length)
caret = ' '
if line_number == report_line:
caret = '> '
s += u'%s. %s%s' % (num, caret, line)
line_number += 1
return _syntax_highlighting(source_name, mode, s)
def _syntax_highlighting(source_name, mode, s):
if pygments is None or mode == PLAIN_FORMATTER:
return s
lexer = pygments.lexers.get_lexer_for_filename(source_name)
formatter = None
if mode == TERMINAL_FORMATTER:
if not sys.stdout.isatty():
return s
formatter = pygments.formatters.TerminalFormatter()
return pygments.highlight(s, lexer, formatter)

@ -20,12 +20,6 @@ import locale
import logging import logging
import os import os
import re import re
try:
import pygments
import pygments.formatters
import pygments.lexers
except ImportError:
pygments = None
import subprocess import subprocess
import sys import sys
import tempfile import tempfile
@ -108,14 +102,6 @@ BUCK_INFER_OUT = 'infer'
FORMAT = '[%(levelname)s] %(message)s' FORMAT = '[%(levelname)s] %(message)s'
DEBUG_FORMAT = '[%(levelname)s:%(filename)s:%(lineno)03d] %(message)s' DEBUG_FORMAT = '[%(levelname)s:%(filename)s:%(lineno)03d] %(message)s'
BASE_INDENT = 2
# how many lines of context around each report
SOURCE_CONTEXT = 2
# syntax highlighting modes
PLAIN_FORMATTER = 0
TERMINAL_FORMATTER = 1
# Monkey patching subprocess (I'm so sorry!). # Monkey patching subprocess (I'm so sorry!).
if "check_output" not in dir(subprocess): if "check_output" not in dir(subprocess):
@ -413,72 +399,3 @@ class AbsolutePathAction(argparse.Action):
"""Convert a path from relative to absolute in the arg parser""" """Convert a path from relative to absolute in the arg parser"""
def __call__(self, parser, namespace, values, option_string=None): def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, os.path.abspath(values)) setattr(namespace, self.dest, os.path.abspath(values))
class Indenter(str):
def __init__(self):
super(Indenter, self).__init__()
self.text = ''
self.indent = []
def indent_get(self):
indent = ''
for i in self.indent:
indent += i
return indent
def indent_push(self, n=1):
self.indent.append(n * BASE_INDENT * ' ')
def indent_pop(self):
return self.indent.pop()
def newline(self):
self.text += '\n'
def add(self, x):
if type(x) != unicode:
x = x.decode(LOCALE)
lines = x.splitlines()
indent = self.indent_get()
lines = [indent + l for l in lines]
self.text += '\n'.join(lines)
def __unicode__(self):
return self.text
def __str__(self):
return unicode(self).encode(LOCALE)
def syntax_highlighting(source_name, mode, s):
if pygments is None or mode == PLAIN_FORMATTER:
return s
lexer = pygments.lexers.get_lexer_for_filename(source_name)
formatter = None
if mode == TERMINAL_FORMATTER:
if not sys.stdout.isatty():
return s
formatter = pygments.formatters.TerminalFormatter()
return pygments.highlight(s, lexer, formatter)
def build_source_context(source_name, mode, report_line):
start_line = max(1, report_line - SOURCE_CONTEXT)
# could go beyond last line, checked in the loop
end_line = report_line + SOURCE_CONTEXT
n_length = len(str(end_line))
line_number = 1
s = ''
with codecs.open(source_name, 'r', encoding=LOCALE) as source_file:
for line in source_file:
if start_line <= line_number <= end_line:
num = str(line_number).zfill(n_length)
caret = ' '
if line_number == report_line:
caret = '> '
s += u'%s. %s%s' % (num, caret, line)
line_number += 1
return syntax_highlighting(source_name, mode, s)

Loading…
Cancel
Save