# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of astroid.
#
# astroid is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version.
#
# astroid is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>.
"""This module contains base classes and functions for the nodes and some
inference utils.
"""

__docformat__ = "restructuredtext en"

import sys
from contextlib import contextmanager

from logilab.common.decorators import cachedproperty

from astroid.exceptions import (InferenceError, AstroidError, NotFoundError,
                                UnresolvableName, UseInferenceDefault)


if sys.version_info >= (3, 0):
    BUILTINS = 'builtins'
else:
    BUILTINS = '__builtin__'


class Proxy(object):
    """a simple proxy object"""

    _proxied = None # proxied object may be set by class or by instance

    def __init__(self, proxied=None):
        if proxied is not None:
            self._proxied = proxied

    def __getattr__(self, name):
        if name == '_proxied':
            return getattr(self.__class__, '_proxied')
        if name in self.__dict__:
            return self.__dict__[name]
        return getattr(self._proxied, name)

    def infer(self, context=None):
        yield self


# Inference ##################################################################

MISSING = object()


class InferenceContext(object):
    __slots__ = ('path', 'callcontext', 'boundnode', 'infered')

    def __init__(self,
            path=None, callcontext=None, boundnode=None, infered=None):
        if path is None:
            self.path = frozenset()
        else:
            self.path = path
        self.callcontext = callcontext
        self.boundnode = boundnode
        if infered is None:
            self.infered = {}
        else:
            self.infered = infered

    def push(self, key):
        # This returns a NEW context with the same attributes, but a new key
        # added to `path`.  The intention is that it's only passed to callees
        # and then destroyed; otherwise scope() may not work correctly.
        # The cache will be shared, since it's the same exact dict.
        if key in self.path:
            # End the containing generator
            raise StopIteration

        return InferenceContext(
            self.path.union([key]),
            self.callcontext,
            self.boundnode,
            self.infered,
        )

    @contextmanager
    def scope(self, callcontext=MISSING, boundnode=MISSING):
        try:
            orig = self.callcontext, self.boundnode
            if callcontext is not MISSING:
                self.callcontext = callcontext
            if boundnode is not MISSING:
                self.boundnode = boundnode
            yield
        finally:
            self.callcontext, self.boundnode = orig

    def cache_generator(self, key, generator):
        results = []
        for result in generator:
            results.append(result)
            yield result

        self.infered[key] = tuple(results)
        return


def _infer_stmts(stmts, context, frame=None, lookupname=None):
    """return an iterator on statements inferred by each statement in <stmts>
    """
    stmt = None
    infered = False
    if context is None:
        context = InferenceContext()
    for stmt in stmts:
        if stmt is YES:
            yield stmt
            infered = True
            continue

        kw = {}
        infered_name = stmt._infer_name(frame, lookupname)
        if infered_name is not None:
            # only returns not None if .infer() accepts a lookupname kwarg
            kw['lookupname'] = infered_name

        try:
            for infered in stmt.infer(context, **kw):
                yield infered
                infered = True
        except UnresolvableName:
            continue
        except InferenceError:
            yield YES
            infered = True
    if not infered:
        raise InferenceError(str(stmt))


# special inference objects (e.g. may be returned as nodes by .infer()) #######

class _Yes(object):
    """a yes object"""
    def __repr__(self):
        return 'YES'
    def __getattribute__(self, name):
        if name == 'next':
            raise AttributeError('next method should not be called')
        if name.startswith('__') and name.endswith('__'):
            # to avoid inspection pb
            return super(_Yes, self).__getattribute__(name)
        return self
    def __call__(self, *args, **kwargs):
        return self


YES = _Yes()


class Instance(Proxy):
    """a special node representing a class instance"""
    def getattr(self, name, context=None, lookupclass=True):
        try:
            values = self._proxied.instance_attr(name, context)
        except NotFoundError:
            if name == '__class__':
                return [self._proxied]
            if lookupclass:
                # class attributes not available through the instance
                # unless they are explicitly defined
                if name in ('__name__', '__bases__', '__mro__', '__subclasses__'):
                    return self._proxied.local_attr(name)
                return self._proxied.getattr(name, context)
            raise NotFoundError(name)
        # since we've no context information, return matching class members as
        # well
        if lookupclass:
            try:
                return values + self._proxied.getattr(name, context)
            except NotFoundError:
                pass
        return values

    def igetattr(self, name, context=None):
        """inferred getattr"""
        if not context:
            context = InferenceContext()
        try:
            # avoid recursively inferring the same attr on the same class
            new_context = context.push((self._proxied, name))
            # XXX frame should be self._proxied, or not ?
            get_attr = self.getattr(name, new_context, lookupclass=False)
            return _infer_stmts(
                self._wrap_attr(get_attr, new_context),
                new_context,
                frame=self,
            )
        except NotFoundError:
            try:
                # fallback to class'igetattr since it has some logic to handle
                # descriptors
                return self._wrap_attr(self._proxied.igetattr(name, context),
                                            context)
            except NotFoundError:
                raise InferenceError(name)

    def _wrap_attr(self, attrs, context=None):
        """wrap bound methods of attrs in a InstanceMethod proxies"""
        for attr in attrs:
            if isinstance(attr, UnboundMethod):
                if BUILTINS + '.property' in attr.decoratornames():
                    for infered in attr.infer_call_result(self, context):
                        yield infered
                else:
                    yield BoundMethod(attr, self)
            else:
                yield attr

    def infer_call_result(self, caller, context=None):
        """infer what a class instance is returning when called"""
        infered = False
        for node in self._proxied.igetattr('__call__', context):
            if node is YES:
                continue
            for res in node.infer_call_result(caller, context):
                infered = True
                yield res
        if not infered:
            raise InferenceError()

    def __repr__(self):
        return '<Instance of %s.%s at 0x%s>' % (self._proxied.root().name,
                                                self._proxied.name,
                                                id(self))
    def __str__(self):
        return 'Instance of %s.%s' % (self._proxied.root().name,
                                      self._proxied.name)

    def callable(self):
        try:
            self._proxied.getattr('__call__')
            return True
        except NotFoundError:
            return False

    def pytype(self):
        return self._proxied.qname()

    def display_type(self):
        return 'Instance of'


class UnboundMethod(Proxy):
    """a special node representing a method not bound to an instance"""
    def __repr__(self):
        frame = self._proxied.parent.frame()
        return '<%s %s of %s at 0x%s' % (self.__class__.__name__,
                                         self._proxied.name,
                                         frame.qname(), id(self))

    def is_bound(self):
        return False

    def getattr(self, name, context=None):
        if name == 'im_func':
            return [self._proxied]
        return super(UnboundMethod, self).getattr(name, context)

    def igetattr(self, name, context=None):
        if name == 'im_func':
            return iter((self._proxied,))
        return super(UnboundMethod, self).igetattr(name, context)

    def infer_call_result(self, caller, context):
        # If we're unbound method __new__ of builtin object, the result is an
        # instance of the class given as first argument.
        if (self._proxied.name == '__new__' and
                self._proxied.parent.frame().qname() == '%s.object' % BUILTINS):
            infer = caller.args[0].infer() if caller.args else []
            return ((x is YES and x or Instance(x)) for x in infer)
        return self._proxied.infer_call_result(caller, context)


class BoundMethod(UnboundMethod):
    """a special node representing a method bound to an instance"""
    def __init__(self, proxy, bound):
        UnboundMethod.__init__(self, proxy)
        self.bound = bound

    def is_bound(self):
        return True

    def infer_call_result(self, caller, context):
        with context.scope(boundnode=self.bound):
            for infered in self._proxied.infer_call_result(caller, context):
                yield infered


class Generator(Instance):
    """a special node representing a generator.

    Proxied class is set once for all in raw_building.
    """
    def callable(self):
        return False

    def pytype(self):
        return '%s.generator' % BUILTINS

    def display_type(self):
        return 'Generator'

    def __repr__(self):
        return '<Generator(%s) l.%s at 0x%s>' % (self._proxied.name, self.lineno, id(self))

    def __str__(self):
        return 'Generator(%s)' % (self._proxied.name)


# decorators ##################################################################

def path_wrapper(func):
    """return the given infer function wrapped to handle the path"""
    def wrapped(node, context=None, _func=func, **kwargs):
        """wrapper function handling context"""
        if context is None:
            context = InferenceContext()
        context = context.push((node, kwargs.get('lookupname')))

        yielded = set()
        for res in _func(node, context, **kwargs):
            # unproxy only true instance, not const, tuple, dict...
            if res.__class__ is Instance:
                ares = res._proxied
            else:
                ares = res
            if not ares in yielded:
                yield res
                yielded.add(ares)
    return wrapped

def yes_if_nothing_infered(func):
    def wrapper(*args, **kwargs):
        infered = False
        for node in func(*args, **kwargs):
            infered = True
            yield node
        if not infered:
            yield YES
    return wrapper

def raise_if_nothing_infered(func):
    def wrapper(*args, **kwargs):
        infered = False
        for node in func(*args, **kwargs):
            infered = True
            yield node
        if not infered:
            raise InferenceError()
    return wrapper


# Node  ######################################################################

class NodeNG(object):
    """Base Class for all Astroid node classes.

    It represents a node of the new abstract syntax tree.
    """
    is_statement = False
    optional_assign = False # True  for For (and for Comprehension if py <3.0)
    is_function = False # True for Function nodes
    # attributes below are set by the builder module or by raw factories
    lineno = None
    fromlineno = None
    tolineno = None
    col_offset = None
    # parent node in the tree
    parent = None
    # attributes containing child node(s) redefined in most concrete classes:
    _astroid_fields = ()
    # instance specific inference function infer(node, context)
    _explicit_inference = None

    def infer(self, context=None, **kwargs):
        """main interface to the interface system, return a generator on infered
        values.

        If the instance has some explicit inference function set, it will be
        called instead of the default interface.
        """
        if self._explicit_inference is not None:
            # explicit_inference is not bound, give it self explicitly
            try:
                return self._explicit_inference(self, context, **kwargs)
            except UseInferenceDefault:
                pass

        if not context:
            return self._infer(context, **kwargs)

        key = (self, kwargs.get('lookupname'), context.callcontext, context.boundnode)
        if key in context.infered:
            return iter(context.infered[key])

        return context.cache_generator(key, self._infer(context, **kwargs))

    def _repr_name(self):
        """return self.name or self.attrname or '' for nice representation"""
        return getattr(self, 'name', getattr(self, 'attrname', ''))

    def __str__(self):
        return '%s(%s)' % (self.__class__.__name__, self._repr_name())

    def __repr__(self):
        return '<%s(%s) l.%s [%s] at 0x%x>' % (self.__class__.__name__,
                                               self._repr_name(),
                                               self.fromlineno,
                                               self.root().name,
                                               id(self))


    def accept(self, visitor):
        func = getattr(visitor, "visit_" + self.__class__.__name__.lower())
        return func(self)

    def get_children(self):
        for field in self._astroid_fields:
            attr = getattr(self, field)
            if attr is None:
                continue
            if isinstance(attr, (list, tuple)):
                for elt in attr:
                    yield elt
            else:
                yield attr

    def last_child(self):
        """an optimized version of list(get_children())[-1]"""
        for field in self._astroid_fields[::-1]:
            attr = getattr(self, field)
            if not attr: # None or empty listy / tuple
                continue
            if attr.__class__ in (list, tuple):
                return attr[-1]
            else:
                return attr
        return None

    def parent_of(self, node):
        """return true if i'm a parent of the given node"""
        parent = node.parent
        while parent is not None:
            if self is parent:
                return True
            parent = parent.parent
        return False

    def statement(self):
        """return the first parent node marked as statement node"""
        if self.is_statement:
            return self
        return self.parent.statement()

    def frame(self):
        """return the first parent frame node (i.e. Module, Function or Class)
        """
        return self.parent.frame()

    def scope(self):
        """return the first node defining a new scope (i.e. Module, Function,
        Class, Lambda but also GenExpr)
        """
        return self.parent.scope()

    def root(self):
        """return the root node of the tree, (i.e. a Module)"""
        if self.parent:
            return self.parent.root()
        return self

    def child_sequence(self, child):
        """search for the right sequence where the child lies in"""
        for field in self._astroid_fields:
            node_or_sequence = getattr(self, field)
            if node_or_sequence is child:
                return [node_or_sequence]
            # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
            if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence:
                return node_or_sequence
        else:
            msg = 'Could not find %s in %s\'s children'
            raise AstroidError(msg % (repr(child), repr(self)))

    def locate_child(self, child):
        """return a 2-uple (child attribute name, sequence or node)"""
        for field in self._astroid_fields:
            node_or_sequence = getattr(self, field)
            # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
            if child is node_or_sequence:
                return field, child
            if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence:
                return field, node_or_sequence
        msg = 'Could not find %s in %s\'s children'
        raise AstroidError(msg % (repr(child), repr(self)))
    # FIXME : should we merge child_sequence and locate_child ? locate_child
    # is only used in are_exclusive, child_sequence one time in pylint.

    def next_sibling(self):
        """return the next sibling statement"""
        return self.parent.next_sibling()

    def previous_sibling(self):
        """return the previous sibling statement"""
        return self.parent.previous_sibling()

    def nearest(self, nodes):
        """return the node which is the nearest before this one in the
        given list of nodes
        """
        myroot = self.root()
        mylineno = self.fromlineno
        nearest = None, 0
        for node in nodes:
            assert node.root() is myroot, \
                   'nodes %s and %s are not from the same module' % (self, node)
            lineno = node.fromlineno
            if node.fromlineno > mylineno:
                break
            if lineno > nearest[1]:
                nearest = node, lineno
        # FIXME: raise an exception if nearest is None ?
        return nearest[0]

    # these are lazy because they're relatively expensive to compute for every
    # single node, and they rarely get looked at

    @cachedproperty
    def fromlineno(self):
        if self.lineno is None:
            return self._fixed_source_line()
        else:
            return self.lineno

    @cachedproperty
    def tolineno(self):
        if not self._astroid_fields:
            # can't have children
            lastchild = None
        else:
            lastchild = self.last_child()
        if lastchild is None:
            return self.fromlineno
        else:
            return lastchild.tolineno

        # TODO / FIXME:
        assert self.fromlineno is not None, self
        assert self.tolineno is not None, self

    def _fixed_source_line(self):
        """return the line number where the given node appears

        we need this method since not all nodes have the lineno attribute
        correctly set...
        """
        line = self.lineno
        _node = self
        try:
            while line is None:
                _node = next(_node.get_children())
                line = _node.lineno
        except StopIteration:
            _node = self.parent
            while _node and line is None:
                line = _node.lineno
                _node = _node.parent
        return line

    def block_range(self, lineno):
        """handle block line numbers range for non block opening statements
        """
        return lineno, self.tolineno

    def set_local(self, name, stmt):
        """delegate to a scoped parent handling a locals dictionary"""
        self.parent.set_local(name, stmt)

    def nodes_of_class(self, klass, skip_klass=None):
        """return an iterator on nodes which are instance of the given class(es)

        klass may be a class object or a tuple of class objects
        """
        if isinstance(self, klass):
            yield self
        for child_node in self.get_children():
            if skip_klass is not None and isinstance(child_node, skip_klass):
                continue
            for matching in child_node.nodes_of_class(klass, skip_klass):
                yield matching

    def _infer_name(self, frame, name):
        # overridden for From, Import, Global, TryExcept and Arguments
        return None

    def _infer(self, context=None):
        """we don't know how to resolve a statement by default"""
        # this method is overridden by most concrete classes
        raise InferenceError(self.__class__.__name__)

    def infered(self):
        '''return list of infered values for a more simple inference usage'''
        return list(self.infer())

    def instanciate_class(self):
        """instanciate a node if it is a Class node, else return self"""
        return self

    def has_base(self, node):
        return False

    def callable(self):
        return False

    def eq(self, value):
        return False

    def as_string(self):
        from astroid.as_string import to_code
        return to_code(self)

    def repr_tree(self, ids=False):
        from astroid.as_string import dump
        return dump(self)


class Statement(NodeNG):
    """Statement node adding a few attributes"""
    is_statement = True

    def next_sibling(self):
        """return the next sibling statement"""
        stmts = self.parent.child_sequence(self)
        index = stmts.index(self)
        try:
            return stmts[index +1]
        except IndexError:
            pass

    def previous_sibling(self):
        """return the previous sibling statement"""
        stmts = self.parent.child_sequence(self)
        index = stmts.index(self)
        if index >= 1:
            return stmts[index -1]
