Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR 3 for #570: the name 'ast' #580

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 11 additions & 9 deletions rope/base/arguments.py
@@ -1,5 +1,6 @@
import rope.base.evaluate
from rope.base import ast
import ast

from rope.base import builtins, evaluate, pyobjects


class Arguments:
Expand Down Expand Up @@ -36,9 +37,10 @@ def get_pynames(self, parameters):
def get_instance_pyname(self):
if self.args:
return self._evaluate(self.args[0])
return None

def _evaluate(self, ast_node):
return rope.base.evaluate.eval_node(self.scope, ast_node)
return evaluate.eval_node(self.scope, ast_node)


def create_arguments(primary, pyfunction, call_node, scope):
Expand Down Expand Up @@ -99,13 +101,13 @@ def _is_method_call(primary, pyfunction):
return False
pyobject = primary.get_object()
if (
isinstance(pyobject.get_type(), rope.base.pyobjects.PyClass)
and isinstance(pyfunction, rope.base.pyobjects.PyFunction)
and isinstance(pyfunction.parent, rope.base.pyobjects.PyClass)
isinstance(pyobject.get_type(), pyobjects.PyClass)
and isinstance(pyfunction, pyobjects.PyFunction)
and isinstance(pyfunction.parent, pyobjects.PyClass)
):
return True
if isinstance(
pyobject.get_type(), rope.base.pyobjects.AbstractClass
) and isinstance(pyfunction, rope.base.builtins.BuiltinFunction):
if isinstance(pyobject.get_type(), pyobjects.AbstractClass) and isinstance(
pyfunction, builtins.BuiltinFunction
): # pylint: disable=no-member
return True
return False
68 changes: 0 additions & 68 deletions rope/base/ast.py

This file was deleted.

75 changes: 56 additions & 19 deletions rope/base/astutils.py
@@ -1,21 +1,6 @@
from rope.base import ast
import ast


def get_name_levels(node):
"""Return a list of ``(name, level)`` tuples for assigned names

The `level` is `None` for simple assignments and is a list of
numbers for tuple assignments for example in::

a, (b, c) = x

The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for
`c` is ``[1, 1]``.

"""
visitor = _NodeNameCollector()
ast.walk(node, visitor)
return visitor.names
from rope.base.astwrapper import walk


class _NodeNameCollector:
Expand Down Expand Up @@ -49,8 +34,8 @@ def _Tuple(self, node):
new_levels.append(self.index)
self.index += 1
visitor = _NodeNameCollector(new_levels)
for child in ast.get_child_nodes(node):
ast.walk(child, visitor)
for child in get_child_nodes(node):
walk(child, visitor)
self.names.extend(visitor.names)

def _Subscript(self, node):
Expand All @@ -61,3 +46,55 @@ def _Attribute(self, node):

def _Slice(self, node):
self._add_node(node)


def get_child_nodes(node):
if isinstance(node, ast.Module):
return node.body
result = []
if node._fields is not None:
for name in node._fields:
child = getattr(node, name)
if isinstance(child, list):
for entry in child:
if isinstance(entry, ast.AST):
result.append(entry)
if isinstance(child, ast.AST):
result.append(child)
return result


def get_name_levels(node):
"""Return a list of ``(name, level)`` tuples for assigned names

The `level` is `None` for simple assignments and is a list of
numbers for tuple assignments for example in::

a, (b, c) = x

The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for
`c` is ``[1, 1]``.

"""
visitor = _NodeNameCollector()
walk(node, visitor)
return visitor.names


def call_for_nodes(node, callback, recursive=False):
"""If callback returns `True` the child nodes are skipped"""
result = callback(node)
if recursive and not result:
for child in get_child_nodes(node):
call_for_nodes(child, callback, recursive)


def get_children(node):
result = []
if node._fields is not None:
for name in node._fields:
if name in ["lineno", "col_offset"]:
continue
child = getattr(node, name)
result.append(child)
return result
33 changes: 33 additions & 0 deletions rope/base/astwrapper.py
@@ -0,0 +1,33 @@
"""Wrappers for stdlib.ast.parse and stdlib.ast.walk."""
import ast

from rope.base import astutils, fscommands


def parse(source, filename="<string>"):
# NOTE: the raw string should be given to `compile` function
if isinstance(source, str):
source = fscommands.unicode_to_file_data(source)
if b"\r" in source:
source = source.replace(b"\r\n", b"\n").replace(b"\r", b"\n")
if not source.endswith(b"\n"):
source += b"\n"
try:
return ast.parse(source, filename="<unknown>")
except (TypeError, ValueError) as e:
error = SyntaxError()
error.lineno = 1
error.filename = filename
error.msg = str(e)
raise error


def walk(node, walker) -> None:
"""Walk the syntax tree"""
method_name = "_" + node.__class__.__name__
method = getattr(walker, method_name, None)
if method is not None:
method(node)
return
for child in astutils.get_child_nodes(node):
walk(child, walker)
5 changes: 3 additions & 2 deletions rope/base/builtins.py
@@ -1,9 +1,10 @@
"""This module tries to support builtin types and functions."""
import ast
import inspect
import io

import rope.base.evaluate
from rope.base import ast, pynames, pyobjects, arguments, utils
from rope.base import arguments, pynames, pyobjects, utils


try:
Expand Down Expand Up @@ -39,7 +40,7 @@ def attributes(self):
if self.pycore is not None:
submodules = self.pycore._builtin_submodules(self.name)
for name, module in submodules.items():
result[name] = rope.base.builtins.BuiltinName(module)
result[name] = BuiltinName(module) # pylint: disable=no-member
return result

@property
Expand Down
8 changes: 4 additions & 4 deletions rope/base/evaluate.py
@@ -1,18 +1,18 @@
import ast
from operator import itemgetter
from typing import Optional, Tuple

import rope.base.builtins
import rope.base.pynames
import rope.base.pyobjects
from rope.base import (
ast,
astutils,
exceptions,
pyobjects,
pyobjectsdef,
arguments,
worder,
)
from rope.base.astwrapper import parse, walk


BadIdentifierError = exceptions.BadIdentifierError
Expand All @@ -39,7 +39,7 @@ def eval_node(scope, node):

def eval_node2(scope, node):
evaluator = StatementEvaluator(scope)
ast.walk(node, evaluator)
walk(node, evaluator)
return evaluator.old_result, evaluator.result


Expand All @@ -50,7 +50,7 @@ def eval_str(holding_scope, name):
def eval_str2(holding_scope, name):
try:
# parenthesizing for handling cases like 'a_var.\nattr'
node = ast.parse("(%s)" % name)
node = parse("(%s)" % name)
except SyntaxError:
raise BadIdentifierError("Not a resolvable python identifier selected.")
return eval_node2(holding_scope, node)
Expand Down
37 changes: 19 additions & 18 deletions rope/base/oi/soa.py
@@ -1,7 +1,8 @@
import rope.base.ast
import ast
import rope.base.oi.soi
import rope.base.pynames
from rope.base import pyobjects, evaluate, astutils, arguments
from rope.base.astwrapper import walk
from rope.base import arguments, astutils, evaluate, pyobjects


def analyze_module(pycore, pymodule, should_analyze, search_subscopes, followed_calls):
Expand Down Expand Up @@ -30,11 +31,9 @@ def _follow(pyfunction):
pycore, pyfunction, return_true, return_false, new_followed_calls
)

if not followed_calls:
_follow = None
visitor = SOAVisitor(pycore, pydefined, _follow)
for child in rope.base.ast.get_child_nodes(pydefined.get_ast()):
rope.base.ast.walk(child, visitor)
visitor = SOAVisitor(pycore, pydefined, _follow if followed_calls else None)
for child in astutils.get_child_nodes(pydefined.get_ast()):
walk(child, visitor)


class SOAVisitor:
Expand All @@ -51,8 +50,8 @@ def _ClassDef(self, node):
pass

def _Call(self, node):
for child in rope.base.ast.get_child_nodes(node):
rope.base.ast.walk(child, self)
for child in astutils.get_child_nodes(node):
walk(child, self)
primary, pyname = evaluate.eval_node2(self.scope, node.func)
if pyname is None:
return
Expand Down Expand Up @@ -89,7 +88,9 @@ def _call(self, pyfunction, args):
if after != before:
self.follow(pyfunction)
# XXX: Maybe we should not call every builtin function
if isinstance(pyfunction, rope.base.builtins.BuiltinFunction):
if isinstance(
pyfunction, rope.base.builtins.BuiltinFunction
): # pylint: disable=no-member
pyfunction.get_returned_object(args)

def _parameter_objects(self, pyfunction):
Expand All @@ -99,23 +100,23 @@ def _parameter_objects(self, pyfunction):
]

def _AnnAssign(self, node):
for child in rope.base.ast.get_child_nodes(node):
rope.base.ast.walk(child, self)
for child in astutils.get_child_nodes(node):
walk(child, self)
visitor = _SOAAssignVisitor()
nodes = []

rope.base.ast.walk(node.target, visitor)
walk(node.target, visitor)
nodes.extend(visitor.nodes)

self._evaluate_assign_value(node, nodes, type_hint=node.annotation)

def _Assign(self, node):
for child in rope.base.ast.get_child_nodes(node):
rope.base.ast.walk(child, self)
for child in astutils.get_child_nodes(node):
walk(child, self)
visitor = _SOAAssignVisitor()
nodes = []
for child in node.targets:
rope.base.ast.walk(child, visitor)
walk(child, visitor)
nodes.extend(visitor.nodes)
self._evaluate_assign_value(node, nodes)

Expand Down Expand Up @@ -145,7 +146,7 @@ def __init__(self):
self.nodes = []

def _added(self, node, levels):
if isinstance(node, rope.base.ast.Subscript) and isinstance(
node.slice, (rope.base.ast.Index, rope.base.ast.expr)
if isinstance(node, ast.Subscript) and isinstance(
node.slice, (ast.Index, ast.expr)
):
self.nodes.append((node, levels))