Skip to content

Instantly share code, notes, and snippets.

@ibizaman
Created April 14, 2014 13:38
Show Gist options
  • Select an option

  • Save ibizaman/10648726 to your computer and use it in GitHub Desktop.

Select an option

Save ibizaman/10648726 to your computer and use it in GitHub Desktop.
from baron.rendering_dictionnary import rendering_dictionnary as d
from baron.dumper import dumps
import json
class Position:
def __init__(self, line, column):
self.line = line
self.column = column
def advance_columns(self, columns):
self.column += columns
def advance_line(self):
self.advance_lines(1)
def advance_lines(self, lines):
self.line += 1
self.column = 1
def path_to_location(tree, line, column):
current = Position(1,1)
target = Position(line, column)
found = path_to_location_walk(tree, current, target)
if not found:
return None
else:
return json.dumps(found)
def path_to_location_walk(node, current, target):
if isinstance(node, list):
for pos, child in enumerate(node):
found = path_to_location_walk(child, current, target)
if found is not None:
found["path"] = [pos] + found["path"]
return found
elif isinstance(node, dict):
if node['type'] == "endl":
current.advance_line()
for render_pos, key_type, render_key, value in render(node):
if key_type == 'list':
found = path_to_location_walk(node[render_key], current, target)
else:
found = path_to_location_walk(value, current, target)
if found is not None:
if render_key is not None:
found["path"] = [render_key] + found["path"]
if found["type"] is None:
found["type"] = node["type"]
found["position_in_rendering_list"] = render_pos
return found
else:
advance_by = len(node)
if is_on_targetted_node(target, current, advance_by):
return {"path":[], "type":None, "position_in_rendering_list":None}
current.advance_columns(advance_by)
return None
def is_on_targetted_node(target, current, length):
return target.line == current.line \
and target.column >= current.column \
and target.column < current.column + length
def render(node):
for pos, (key_type, render_key) in enumerate(d[node['type']](node)):
if key_type == 'list':
value = ''
elif key_type == 'key':
value = node[render_key]
elif key_type == 'constant':
value = render_key
render_key = None
elif key_type == 'formatting':
value = dumps(node[render_key])
yield (pos+1, key_type, render_key, value)
#rendering_dictionnary = {
# "ternary_operator": [
# ("key", "first" ),
# ("list", "first_formatting" ),
# ("constant", "if" ),
# ("list", "second_formatting"),
# ("key", "value" ),
# ("list", "third_formatting" ),
# ("constant", "else" ),
# ("list", "fourth_formatting"),
# ("key", "second" )
# ],
# "assignment": [
# ("key", "target" ),
# ("list", "first_formatting" ),
# ("key", "operator" ),
# ("constant", "=" ),
# ("list", "second_formatting"),
# ("key", "value" )
# ],
# "funcdef": [
# ("list", "decorators" ),
# ("constant", "def" ),
# ("list", "first_formatting" ),
# ("key", "name" ),
# ("list", "second_formatting"),
# ("constant", "(" ),
# ("list", "third_formatting" ),
# ("list", "arguments" ),
# ("list", "fourth_formatting"),
# ("constant", ")" ),
# ("list", "fifth_formatting" ),
# ("constant", ":" ),
# ("list", "sixth_formatting" ),
# ("list", "value" )
# ],
# "space": [
# ("key", "value")
# ],
# "name": [
# ("key", "value")
# ]
# }
rendering_dictionnary = {}
def node(key=""):
def wrap(func):
if not key:
rendering_dictionnary[func.__name__ if not func.__name__.endswith("_") else func.__name__[:-1]] = func
rendering_dictionnary[key] = func
return func
return wrap
@node()
def assignment(node):
yield ("key", "target")
yield ("formatting", "first_formatting")
if node.get("operator"):
# FIXME should probably be a different node type
yield ("key", "operator")
yield ("constant", "=")
yield ("formatting", "second_formatting")
yield ("key", "value")
@node("int")
@node("name")
@node("space")
def get_value(node):
yield ("key", "value")
def endl(node):
yield ("formatting", "formatting")
yield ("key", "value")
yield ("formatting", "indent")
from baron.baron import parse
import baron.finder as finder
import json
def make_path(path, type, pos):
return json.dumps({"path":path, "type":type, "position_in_rendering_list":pos})
def check_path(line, column, target_node):
code = """def fun(arg1, arg2):
var *= 1
@deco("arg")
def fun2(arg1 = default, **kwargs):
arg1.attr = 3
"""
code = """vara = 1"""
assert finder.path_to_location(parse(code), line, column) == target_node
def test_line_before_scope():
check_path(-1, 3, None)
def test_column_before_scope():
check_path(1, -3, None)
def test_line_after_scope():
check_path(3, 3, None)
def test_column_after_scope():
check_path(1, 100, None)
def test_assignment():
check_path(1, 100, None)
def test_assignement_target():
path = make_path([0, "target", "value"], "name", 1)
check_path(1, 1, path)
check_path(1, 2, path)
check_path(1, 3, path)
check_path(1, 4, path)
def test_assignement_first_formatting():
path = make_path([0, "first_formatting"], "assignment", 2)
check_path(1, 5, path)
def test_assignement_operator():
path = make_path([0], "assignment", 3)
check_path(1, 6, path)
def test_assignement_second_formatting():
path = make_path([0, "second_formatting"], "assignment", 4)
check_path(1, 7, path)
def test_assignement_target():
path = make_path([0, "value", "value"], "int", 1)
check_path(1, 8, path)
#def test_first_def():
# path = make_path([0, "value"], "funcdef", 2)
# check_path(1, 1, path)
# check_path(1, 2, path)
# check_path(1, 3, path)
#
#def test_first_formatting():
# path = make_path([0, "value"], "funcdef", 3)
# check_path(1, 4, path)
#
#def test_first_name():
# path = make_path([0, "value"], "funcdef", 4)
# check_path(1, 5, path)
# check_path(1, 6, path)
# check_path(1, 7, path)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment