o
    DDi                     @   s  d dl Z d dlZd dlmZ d dlmZmZ d dlmZ d dl	m
Z
mZ d dlmZmZmZmZmZmZmZmZmZmZmZ d dlZd dlmZ d dlmZ d d	lmZ d d
lm Z  d dl!m"Z"m#Z# ej$ej%ej&ej'ej(ej)ej*ej+ej,ej-ej.ej/ej0ej1ej2ej3ej4ej5fZ6eeddG dd dZ7G dd deZ8eeddG dd dZ9G dd de j:Z;G dd de;Z<G dd de;Z=G dd de<Z>G dd dZ?G dd  d Z@G d!d" d"e j:ZAG d#d$ d$eAZBG d%d& d&eAZCG d'd( d(eAe j:ZDG d)d* d*eDZEG d+d, d,eDZFG d-d. d.eDZGG d/d0 d0eDZHd1eejIejJf d2eeeKeejIejJf f  fd3d4ZLd1ejMd5ejMd2eNfd6d7ZOeddG d8d9 d9ZPG d:d; d;ejQZRG d<d= d=e eeA  ZSdS )>    N)defaultdict)contextmanager	ExitStack)	dataclass)autoEnum)
CollectionDictIteratorListMappingMutableMappingOptionalSetTupleTypeUnion)ensure_type)	add_slots)get_full_name_for_node)BatchableMetadataProvider)ExpressionContextExpressionContextProviderF)frozenc                
   @   s   e Zd ZU dZeejejejf e	d< de	d< e
e	d< e
e	d< ed e	d< ee	d	< dejddde
de
d
df
ddZd
efddZed
ed fddZed
efddZdddZded
dfddZdS )Accessa  
    An Access records an access of an assignment.

    .. note::
       This scope analysis only analyzes access via a :class:`~libcst.Name` or  a :class:`~libcst.Name`
       node embedded in other node like :class:`~libcst.Call` or :class:`~libcst.Attribute`.
       It doesn't support type annontation using :class:`~libcst.SimpleString` literal for forward
       references. E.g. in this example, the ``"Tree"`` isn't parsed as an access::

           class Tree:
               def __new__(cls) -> "Tree":
                   ...
    nodeScopescopeis_annotationis_type_hintBaseAssignment_Access__assignments_Access__indexreturnNc                 C   s,   || _ || _|| _|| _t | _|j| _d S N)r   r   r   r   setr!   _assignment_countr"   )selfr   r   r   r    r(   W/var/www/Datamplify/venv/lib/python3.10/site-packages/libcst/metadata/scope_provider.py__init__`   s   zAccess.__init__c                 C      t | S r$   idr'   r(   r(   r)   __hash__j      zAccess.__hash__c                 C      | j S )z%Return all assignments of the access.)r!   r.   r(   r(   r)   	referentsm   s   zAccess.referentsc                 C   r1   r$   )r"   r.   r(   r(   r)   _indexr      zAccess._index
assignmentc                 C   s,   |j | j ks|j| jk r| j| d S d S r$   )r   r3   r"   r!   add)r'   r5   r(   r(   r)   record_assignmentv      zAccess.record_assignmentnamec                    s\    j | j } fdd|D }|s%|r% j j j kr% j j| j }  j|O  _d S )Nc                    s(   h | ]}|j  j ks|j jk r|qS r(   )r   r3   r"   ).0r5   r.   r(   r)   	<setcomp>}   
    z,Access.record_assignments.<locals>.<setcomp>)r   _resolve_scope_for_accessparentr!   )r'   r9   assignmentsprevious_assignmentsr(   r.   r)   record_assignmentsz   s   
zAccess.record_assignments)r5   r    r#   N)__name__
__module____qualname____doc__r   cstName	Attribute
BaseString__annotations__boolr   intr*   r/   propertyr   r2   r3   r7   strrA   r(   r(   r(   r)   r   =   s4   
 


r   c                   @   s   e Zd Ze Ze Ze ZdS )QualifiedNameSourceN)rB   rC   rD   r   IMPORTBUILTINLOCALr(   r(   r(   r)   rO      s    
rO   Tc                   @   s   e Zd ZU eed< eed< dS )QualifiedNamer9   sourceN)rB   rC   rD   rN   rJ   rO   r(   r(   r(   r)   rS      s   
 rS   c                   @   s   e Zd ZU dZeed< ded< ee ed< deddddfdd	Zd
eddfddZ	dee ddfddZ
edee fddZdefddZedefddZejdedee fddZdS )r    zIAbstract base class of :class:`Assignment` and :class:`BuitinAssignment`.r9   r   r   _BaseAssignment__accessesr#   Nc                 C   s   || _ || _t | _d S r$   )r9   r   r%   rU   r'   r9   r   r(   r(   r)   r*      s   zBaseAssignment.__init__accessc                 C   s,   |j | j ks| j|jk r| j| d S d S r$   )r   r3   rU   r6   )r'   rW   r(   r(   r)   record_access   r8   zBaseAssignment.record_accessaccessesc                    sd    fdd|D }  j |O  _ || }|r, jj jkr. jj j D ]}|| q$d S d S d S )Nc                    s(   h | ]}|j  j ks j|jk r|qS r(   )r   r3   )r:   rW   r.   r(   r)   r;      r<   z1BaseAssignment.record_accesses.<locals>.<setcomp>)rU   r   r>   r9   record_accesses)r'   rY   later_accessesearlier_accessesshadowed_assignmentr(   r.   r)   rZ      s   
zBaseAssignment.record_accessesc                 C   r1   )z&Return all accesses of the assignment.)rU   r.   r(   r(   r)   
references   s   zBaseAssignment.referencesc                 C   r+   r$   r,   r.   r(   r(   r)   r/      r0   zBaseAssignment.__hash__c                 C      dS )zEReturn an integer that represents the order of assignments in `scope`r(   r.   r(   r(   r)   r3         zBaseAssignment._index	full_namec                 C      d S r$   r(   r'   rb   r(   r(   r)   get_qualified_names_for      z&BaseAssignment.get_qualified_names_for)rB   rC   rD   rE   rN   rJ   r   r   r*   rX   rZ   rM   r   r^   rL   r/   r3   abcabstractmethodrS   re   r(   r(   r(   r)   r       s   
 r    c                
       st   e Zd ZU dZejed< eed< dedddejdedd	f
 fd
dZ	e
defddZdedee fddZ  ZS )
Assignmentz9An assignment records the name, CSTNode and its accesses.r   _Assignment__indexr9   r   r   indexr#   Nc                    s   || _ || _t || d S r$   )r   rj   superr*   )r'   r9   r   r   rk   	__class__r(   r)   r*      s   zAssignment.__init__c                 C   r1   r$   )rj   r.   r(   r(   r)   r3      r4   zAssignment._indexrb   c                 C   s(   t | jjr| jj d| n|tjhS N.)rS   r   _name_prefixrO   rR   rd   r(   r(   r)   re      s   z"Assignment.get_qualified_names_for)rB   rC   rD   rE   rF   CSTNoderJ   rL   rN   r*   rM   r3   r   rS   re   __classcell__r(   r(   rm   r)   ri      s$   
 
ri   c                   @   s&   e Zd ZdZdedee fddZdS )BuiltinAssignmenta)  
    A BuiltinAssignment represents an value provide by Python as a builtin, including
    `functions <https://docs.python.org/3/library/functions.html>`_,
    `constants <https://docs.python.org/3/library/constants.html>`_, and
    `types <https://docs.python.org/3/library/stdtypes.html>`_.
    rb   r#   c                 C   s   t d| j tjhS )Nz	builtins.)rS   r9   rO   rQ   rd   r(   r(   r)   re         z)BuiltinAssignment.get_qualified_names_forN)rB   rC   rD   rE   rN   r   rS   re   r(   r(   r(   r)   rt      s    rt   c                       sn   e Zd ZU dZejed< dedddejdedejdd	f fd
dZ	defddZ
dedee fddZ  ZS )ImportAssignmentz4An assignment records the import node and it's aliasas_namer9   r   r   r   rk   r#   Nc                    s   t  |||| || _d S r$   )rl   r*   rw   )r'   r9   r   r   rk   rw   rm   r(   r)   r*      s   
zImportAssignment.__init__c                 C   sJ   d}t | jtjr#| jj}| jj}|rt|pd}|r#dt| | }|S )N rp   )
isinstancer   rF   
ImportFrommodulerelativer   len)r'   r{   module_attrr|   r(   r(   r)   get_module_name_for_import
  s   z+ImportAssignment.get_module_name_for_importrb   c                    s4  |   }t }t| jtjtjfsJ | jj}t|tjs|D ]x}t	|j
}|s)q|d  fddtt ddD }|D ]W}|}|rQ|drQ| | }n	|rZ| d| }|rh|jrh|j}	|	d urh|	}||r||dd }
|
r}|
ds}q?|
d}
|t|
r| d|
 n|tj  nq?q|S )Nrp   c                    s   g | ]}d   d| qS )rp   N)join)r:   ipartsr(   r)   
<listcomp>"  s    z<ImportAssignment.get_qualified_names_for.<locals>.<listcomp>r   r`      )r   r%   ry   r   rF   rz   Importnames
ImportStarr   r9   splitranger}   endswithasnameevaluated_alias
startswithlstripr6   rS   rO   rP   )r'   rb   r{   resultsimport_namesr9   	real_name
real_namesrw   
eval_aliasremaining_namer(   r   r)   re     sL   





z(ImportAssignment.get_qualified_names_for)rB   rC   rD   rE   rF   rr   rJ   rN   rL   r*   r   r   rS   re   rs   r(   r(   rm   r)   rv      s$   
 
rv   c                   @   |   e Zd ZdZdeeee f ddfddZde	e fddZ
d	eeejf dee fd
dZd	eeejf defddZdS )Assignmentsz2A container to provide all assignments in a scope.r?   r#   Nc                 C   
   || _ d S r$   )_assignments)r'   r?   r(   r(   r)   r*   E     
zAssignments.__init__c                 c   &    | j  D ]
}|D ]}|V  q
qdS )zBIterate through all assignments by ``for i in scope.assignments``.N)r   values)r'   r?   r5   r(   r(   r)   __iter__H     zAssignments.__iter__r   c                 C   s&   t |}|| jv rt| j| S t S )z[Get assignments given a name str or :class:`~libcst.CSTNode` by ``scope.assignments[node]``)r   r   r%   r'   r   r9   r(   r(   r)   __getitem__N  s   zAssignments.__getitem__c                 C      t | | dkS )zcCheck if a name str or :class:`~libcst.CSTNode` has any assignment by ``node in scope.assignments``r   r}   r'   r   r(   r(   r)   __contains__S     zAssignments.__contains__)rB   rC   rD   rE   r   rN   r   r    r*   r
   r   r   rF   rr   r   rK   r   r(   r(   r(   r)   r   B        r   c                   @   r   )Accessesz/A container to provide all accesses in a scope.rY   r#   Nc                 C   r   r$   )	_accesses)r'   rY   r(   r(   r)   r*   [  r   zAccesses.__init__c                 c   r   )z<Iterate through all accesses by ``for i in scope.accesses``.N)r   r   )r'   rY   rW   r(   r(   r)   r   ^  r   zAccesses.__iter__r   c                 C   s"   t |}|| jv r| j| S t S )zUGet accesses given a name str or :class:`~libcst.CSTNode` by ``scope.accesses[node]``)r   r   r%   r   r(   r(   r)   r   d  s   zAccesses.__getitem__c                 C   r   )z\Check if a name str or :class:`~libcst.CSTNode` has any access by ``node in scope.accesses``r   r   r   r(   r(   r)   r   i  r   zAccesses.__contains__)rB   rC   rD   rE   r   rN   r   r   r*   r
   r   r   rF   rr   r   rK   r   r(   r(   r(   r)   r   X  r   r   c                       s  e Zd ZU dZd ed< ded< eeee f ed< e	ed< eeee
 f ed< eejee
 f ed< eed	< d2 fddZdedejd
dfddZdedejdejd
dfddZded
d fddZdede
d
dfddZdd d
efddZ	d3dd ded  d
d fddZejded
efd d!Zded
ee fd"d#Zejdedd d
ee fd$d%Zd
e	fd&d'Zejded
dfd(d)Zejded
dfd*d+Zdeeejf d
ee  fd,d-Z!e"d
e#fd.d/Z$e"d
e%fd0d1Z&  Z'S )4r   a  
    Base class of all scope classes. Scope object stores assignments from imports,
    variable assignments, function definition or class definition.
    A scope has a parent scope which represents the inheritance relationship. That means
    an assignment in parent scope is viewable to the child scope and the child scope may
    overwrites the assignment by using the same name.

    Use ``name in scope`` to check whether a name is viewable in the scope.
    Use ``scope[name]`` to retrieve all viewable assignments in the scope.

    .. note::
       This scope analysis module only analyzes local variable names and it doesn't handle
       attribute names; for example, given ``a.b.c = 1``, local variable name ``a`` is recorded
       as an assignment instead of ``c`` or ``a.b.c``. To analyze the assignment/access of
       arbitrary object attributes, we leave the job to type inference metadata provider
       coming in the future.
    r>   GlobalScopeglobalsr   r&   _accesses_by_name_accesses_by_noderq   r#   Nc                    sF   t    || _|j| _tt| _d| _tt| _tt| _	d| _
d S )Nr   rx   )rl   r*   r>   r   r   r%   r   r&   r   r   rq   )r'   r>   rm   r(   r)   r*     s   




zScope.__init__r9   r   c                 C   s,   |  |}|j| t||||jd d S )N)r9   r   r   rk   )_find_assignment_targetr   r6   ri   r&   )r'   r9   r   targetr(   r(   r)   r7     s   


zScope.record_assignmentrw   c              	   C   s.   |  |}|j| t|||||jd d S )N)r9   r   r   rw   rk   )r   r   r6   rv   r&   )r'   r9   r   rw   r   r(   r(   r)   record_import_assignment  s   

zScope.record_import_assignmentc                 C   s   | S r$   r(   r'   r9   r(   r(   r)   r     rf   zScope._find_assignment_targetrW   c                 C   s&   | j | | | j|j | d S r$   )r   r6   r   r   )r'   r9   rW   r(   r(   r)   rX     s   zScope.record_access
from_scopec                 C   r_   )a  Returns if the assignments in this scope can be accessed from children.

        This is normally True, except for class scopes::

            def outer_fn():
                v = ...  # outer_fn's declaration
                class InnerCls:
                    v = ...  # shadows outer_fn's declaration
                    class InnerInnerCls:
                        v = ...  # shadows all previous declarations of v
                        def inner_fn():
                            nonlocal v
                            v = ...  # this refers to outer_fn's declaration
                                     # and not to any of the inner classes' as those are
                                     # hidden from their children.
        Tr(   r'   r   r(   r(   r)   _is_visible_from_children  s   zScope._is_visible_from_childrenfirstc                 C   s0   |d ur|n| j }||s|j }||r|S r$   )r>   r   )r'   r   r   r>   r(   r(   r)   _next_visible_parent  s
   

zScope._next_visible_parentc                 C   r_   )zBCheck if the name str exist in current scope by ``name in scope``.Nr(   r   r(   r(   r)   r     ra   zScope.__contains__c                 C   s   |  || S )ak  
        Get assignments given a name str by ``scope[name]``.

        .. note::
           *Why does it return a list of assignments given a name instead of just one assignment?*

           Many programming languages differentiate variable declaration and assignment.
           Further, those programming languages often disallow duplicate declarations within
           the same scope, and will often hoist the declaration (without its assignment) to
           the top of the scope. These design decisions make static analysis much easier,
           because it's possible to match a name against its single declaration for a given scope.

           As an example, the following code would be valid in JavaScript::

               function fn() {
                 console.log(value);  // value is defined here, because the declaration is hoisted, but is currently 'undefined'.
                 var value = 5;  // A function-scoped declaration.
               }
               fn();  // prints 'undefined'.

           In contrast, Python's declaration and assignment are identical and are not hoisted::

               if conditional_value:
                   value = 5
               elif other_conditional_value:
                   value = 10
               print(value)  # possibly valid, depending on conditional execution

           This code may throw a ``NameError`` if both conditional values are falsy.
           It also means that depending on the codepath taken, the original declaration
           could come from either ``value = ...`` assignment node.
           As a result, instead of returning a single declaration,
           we're forced to return a collection of all of the assignments we think could have
           defined a given name by the time a piece of code is executed.
           For the above example, value would resolve to a set of both assignments.
        )r=   r   r(   r(   r)   r     s   %zScope.__getitem__c                 C   rc   r$   r(   r'   r9   r   r(   r(   r)   r=     ra   zScope._resolve_scope_for_accessc                 C   r+   r$   r,   r.   r(   r(   r)   r/     r0   zScope.__hash__c                 C   rc   r$   r(   r   r(   r(   r)   record_global_overwrite  rf   zScope.record_global_overwritec                 C   rc   r$   r(   r   r(   r(   r)   record_nonlocal_overwrite  rf   zScope.record_nonlocal_overwritec           	      C   s   t |tjr| j|nd}|rdd |D S t|}|du r"t S t }|}|rE|| v r2| | }n|d}|dkr=dn|d| }|s)t |tsa|D ]}t |t	r`t
||jr`||  S qLt }|D ]	}|||O }qf|S )a  Get all :class:`~libcst.metadata.QualifiedName` in current scope given a
        :class:`~libcst.CSTNode`.
        The source of a qualified name can be either :attr:`QualifiedNameSource.IMPORT`,
        :attr:`QualifiedNameSource.BUILTIN` or :attr:`QualifiedNameSource.LOCAL`.
        Given the following example, ``c`` has qualified name ``a.b.c`` with source ``IMPORT``,
        ``f`` has qualified name ``Cls.f`` with source ``LOCAL``, ``a`` has qualified name
        ``Cls.f.<locals>.a``, ``i`` has qualified name ``Cls.f.<locals>.<comprehension>.i``,
        and the builtin ``int`` has qualified name ``builtins.int`` with source ``BUILTIN``::

            from a.b import c
            class Cls:
                def f(self) -> "c":
                    c()
                    a = int("1")
                    [i for i in c()]

        We extends `PEP-3155 <https://www.python.org/dev/peps/pep-3155/>`_
        (defines ``__qualname__`` for class and function only; function namespace is followed
        by a ``<locals>``) to provide qualified name for all :class:`~libcst.CSTNode`
        recorded by :class:`~libcst.metadata.Assignment` and :class:`~libcst.metadata.Access`.
        The namespace of a comprehension (:class:`~libcst.ListComp`, :class:`~libcst.SetComp`,
        :class:`~libcst.DictComp`) is represented with ``<comprehension>``.

        An imported name may be used for type annotation with :class:`~libcst.SimpleString` and
        currently resolving the qualified given :class:`~libcst.SimpleString` is not supported
        considering it could be a complex type annotation in the string which is hard to
        resolve, e.g. ``List[Union[int, str]]``.
        Nc                 S   s.   h | ]}|j D ]}||jD ]}|qqqS r(   )r2   re   r9   )r:   rW   referentqnamer(   r(   r)   r;   ,  s    

z0Scope.get_qualified_names_for.<locals>.<setcomp>rp   r`   )ry   rF   rr   r   getr   r%   rfindrN   ri   _is_assignmentr   re   )	r'   r   node_accessesrb   r?   prefixidxr5   r   r(   r(   r)   re     s:   !

zScope.get_qualified_names_forc                 C   
   t | jS )zYReturn an :class:`~libcst.metadata.Assignments` contains all assignmens in current scope.)r   r   r.   r(   r(   r)   r?   L     
zScope.assignmentsc                 C   r   )zTReturn an :class:`~libcst.metadata.Accesses` contains all accesses in current scope.)r   r   r.   r(   r(   r)   rY   Q  r   zScope.accesses)r>   r   r#   Nr$   )(rB   rC   rD   rE   rJ   r   rN   r   r    rL   r   rF   rr   r*   r7   r   r   rX   rK   r   r   r   rg   rh   r   r   r=   r/   r   r   r   r   rS   re   rM   r   r?   r   rY   rs   r(   r(   rm   r)   r   n  sp   
 


'
Dr   c                       s   e Zd ZdZdeddf fddZdedefdd	Zded
dde	e
 fddZdeddfddZdeddfddZdeddfddZ  ZS )BuiltinScopezt
    A BuiltinScope represents python builtin declarations. See https://docs.python.org/3/library/builtins.html
    r   r#   Nc                    s   || _ t j| d d S N)r>   )r   rl   r*   )r'   r   rm   r(   r)   r*   \  s   zBuiltinScope.__init__r9   c                 C   s
   t t|S r$   )hasattrbuiltinsr   r(   r(   r)   r   `  r   zBuiltinScope.__contains__r   r   c                 C   sD   || j v r
| j | S tt|r| j | t||  | j | S t S r$   )r   r   r   r6   rt   r%   r   r(   r(   r)   r=   c  s   



z&BuiltinScope._resolve_scope_for_accessc                 C      t d)Nz1global overwrite in builtin scope are not allowedNotImplementedErrorr   r(   r(   r)   r   p  r0   z$BuiltinScope.record_global_overwritec                 C   r   )Nz-declarations in builtin scope are not allowedr   r   r(   r(   r)   r   s  r0   z&BuiltinScope.record_nonlocal_overwritec                 C   r   )Nz,assignments in builtin scope are not allowedr   r   r(   r(   r)   r   v  r0   z$BuiltinScope._find_assignment_target)rB   rC   rD   rE   r   r*   rN   rK   r   r   r    r=   r   r   r   rs   r(   r(   rm   r)   r   W  s    
r   c                       sr   e Zd ZdZd fddZdedefddZded	d
dee	 fddZ
deddfddZdeddfddZ  ZS )r   zi
    A GlobalScope is the scope of module. All module level assignments are recorded in GlobalScope.
    r#   Nc                    s   t  jt| d d S r   )rl   r*   r   r.   rm   r(   r)   r*     ru   zGlobalScope.__init__r9   c                 C   s*   || j v rt| j | dkS || | v S Nr   )r   r}   r   r   r(   r(   r)   r     s   
zGlobalScope.__contains__r   r   c                 C   s&   || j v r
| j | S | |}|| S r$   )r   r   )r'   r9   r   r>   r(   r(   r)   r=     s   


z%GlobalScope._resolve_scope_for_accessc                 C   rc   r$   r(   r   r(   r(   r)   r     rf   z#GlobalScope.record_global_overwritec                 C   r   )Nz0nonlocal declaration not allowed at module levelr   r   r(   r(   r)   r     r0   z%GlobalScope.record_nonlocal_overwriter#   N)rB   rC   rD   rE   r*   rN   rK   r   r   r    r=   r   r   rs   r(   r(   rm   r)   r   z  s    
	r   c                	       s   e Zd ZU eeef ed< ee ed< ej	ed< 	ddedej	dee ddf fddZ
deddfd	d
ZdeddfddZdeddf fddZdedefddZdedddee fddZdefddZ  ZS )
LocalScope_scope_overwritesr9   r   Nr>   r#   c                    s,   t  | || _|| _i | _|  | _d S r$   )rl   r*   r9   r   r   _make_name_prefixrq   )r'   r>   r   r9   rm   r(   r)   r*     s
   zLocalScope.__init__c                 C      | j | j|< d S r$   )r   r   r   r(   r(   r)   r        z"LocalScope.record_global_overwritec                 C   r   r$   )r>   r   r   r(   r(   r)   r     r   z$LocalScope.record_nonlocal_overwriter   c                    s2   || j v r| j | }| | ||S t |S r$   )r   r   r   rl   rV   rm   r(   r)   r     s   

z"LocalScope._find_assignment_targetc                 C   sB   || j v r|| j | v S || jv rt| j| dkS || | v S r   )r   r   r}   r   r   r(   r(   r)   r     s
   

zLocalScope.__contains__r   c                 C   sN   || j v r| j | }| ||||S || jv r| j| S | |||S r$   )r   r   r=   r   )r'   r9   r   r   r(   r(   r)   r=     s   




z$LocalScope._resolve_scope_for_accessc                 C   s   d td | jj| jdgS )Nrp   z<locals>r   filterr>   rq   r9   r.   r(   r(   r)   r     s   zLocalScope._make_name_prefixr$   )rB   rC   rD   r	   rN   r   rJ   r   rF   rr   r*   r   r   r   rK   r   r   r    r=   r   rs   r(   r(   rm   r)   r     s4   
 


r   c                   @   s   e Zd ZdZdS )FunctionScopezA
    When a function is defined, it creates a FunctionScope.
    N)rB   rC   rD   rE   r(   r(   r(   r)   r     s    r   c                   @   s0   e Zd ZdZdddefddZdefddZd	S )

ClassScopez;
    When a class is defined, it creates a ClassScope.
    r   r   r#   c                 C   s   |j | u o	t|tS r$   )r>   ry   AnnotationScoper   r(   r(   r)   r     s   z$ClassScope._is_visible_from_childrenc                 C   s   d td | jj| jgS ro   r   r.   r(   r(   r)   r     s   zClassScope._make_name_prefixN)rB   rC   rD   rE   rK   r   rN   r   r(   r(   r(   r)   r     s    r   c                   @      e Zd ZdZdefddZdS )ComprehensionScopez
    Comprehensions and generator expressions create their own scope. For example, in

        [i for i in range(10)]

    The variable ``i`` is only viewable within the ComprehensionScope.
    r#   c                 C   s   d td | jjdgS )Nrp   z<comprehension>)r   r   r>   rq   r.   r(   r(   r)   r     s   z$ComprehensionScope._make_name_prefixNrB   rC   rD   rE   rN   r   r(   r(   r(   r)   r     s    r   c                   @   r   )r   z
    Scopes used for type aliases and type parameters as defined by PEP-695.

    These scopes are created for type parameters using the special syntax, as well as
    type aliases. See https://peps.python.org/pep-0695/#scoping-behavior for more.
    r#   c                 C   s   | j jS r$   )r>   rq   r.   r(   r(   r)   r     s   z!AnnotationScope._make_name_prefixNr   r(   r(   r(   r)   r     s    r   r   r#   c                 c   s   t | tjr| j| fV  d S | j}t |tjrI|j}t |tjtjfrGt|}zt|\}}W n
 t	y:   Y d S w ||fV  |E d H  d S d S t |tjtjfrt|}zt|\}}W n
 t	yh   Y d S w | d| j
j | fV  ||fV  |E d H  d S d S ro   )ry   rF   rG   valueCallfuncrH   _gen_dotted_namesnextStopIterationattr)r   r   name_values	next_name	next_noder(   r(   r)   r     s6   
	
r   assignment_nodec                 C   sp   | |u rdS t |tjtjfr6|j}t |tjrdS |D ]}|j| u r& dS |j}|dur5|j| u r5 dS qdS )a!  
    Returns true if ``node`` is part of the assignment at ``assignment_node``.

    Normally this is just a simple identity check, except for imports where the
    assignment is attached to the entire import statement but we are interested in
    ``Name`` nodes inside the statement.
    TFN)ry   rF   r   rz   r   r   r9   r   )r   r   aliasesaliasr   r(   r(   r)   r   *  s   

r   c                   @   s2   e Zd ZU eed< eej ed< eej ed< dS )DeferredAccessrW   enclosing_attributeenclosing_string_annotationN)	rB   rC   rD   r   rJ   r   rF   rH   rI   r(   r(   r(   r)   r   B  s   
 r   c                       s  e Zd ZdV fddZe	dWdee dejd	e	e
 ded fd
dZededed fddZdeejejf defddZdejde	e fddZdejde	e fddZdejde	e fddZdejde	e fddZdejddfddZdejde	e fddZdejddfddZdejde	e fd d!Zdej de	e fd"d#Z!deejej f defd$d%Z"dej#de	e fd&d'Z$dej#ddfd(d)Z%dej&de	e fd*d+Z'dej(de	e fd,d-Z)dej*de	e fd.d/Z+dej,de	e fd0d1Z-dej.defd2d3Z/dej0de	e fd4d5Z1dej0ddfd6d7Z2dej0ddfd8d9Z3dej4de	e fd:d;Z5dej6de	e fd<d=Z7dej8de	e fd>d?Z9dej:de	e fd@dAZ;dej<de	e fdBdCZ=dej>de	e fdDdEZ?deej8ej:ej<ej>f defdFdGZ@dejAde	e fdHdIZBdXdJdKZCdejddf fdLdMZDdejEde	e fdNdOZFdejGde	e fdPdQZHdejIde	e fdRdSZJdejKde	e fdTdUZL  ZMS )YScopeVisitorproviderScopeProviderr#   Nc                    sN   t    || _t | _g | _d g| _dg| _dg| _t	 | _
d | _d| _d S )NFr   )rl   r*   r   r   r    _ScopeVisitor__deferred_accesses(_ScopeVisitor__top_level_attribute_stack"_ScopeVisitor__in_annotation_stack!_ScopeVisitor__in_type_hint_stackr%   #_ScopeVisitor__in_ignored_subscript%_ScopeVisitor__last_string_annotation _ScopeVisitor__ignore_annotation)r'   r   rm   r(   r)   r*   K  s   

zScopeVisitor.__init__kindr   r9   c                 c   s2    | j }||||| _ z	d V  W || _ d S || _ w r$   r   )r'   r   r   r9   parent_scoper(   r(   r)   
_new_scopeW  s   zScopeVisitor._new_scoper   c                 c   s*    | j }|| _ z	d V  W || _ d S || _ w r$   r   )r'   r   current_scoper(   r(   r)   _switch_scopeb  s   zScopeVisitor._switch_scopec           	      C   s   |j }t|tjrdS |D ]6}| j|| j |j}|d ur,tt	|j
tj}|j
}nt|j
}|j
}|D ]\}}| j||| q6qdS NF)r   ry   rF   r   r   set_metadatar   r   r   r   r9   rG   r   )	r'   r   r   r9   r   r   import_node_asname
name_value_r(   r(   r)   _visit_import_alikek  s"   
z ScopeVisitor._visit_import_alikec                 C   
   |  |S r$   r   r   r(   r(   r)   visit_Import  r   zScopeVisitor.visit_Importc                 C   r   r$   r   r   r(   r(   r)   visit_ImportFrom  r   zScopeVisitor.visit_ImportFromc                 C   s@   | j d d u r|| j d< |j|  | j d |u rd | j d< dS )Nr`   F)r   r   visitr   r(   r(   r)   visit_Attribute  s   

zScopeVisitor.visit_Attributec                 C   s   | j d  | jd dd | j|D }d|v sd|v r;|j|  d| jd< |jdd  D ]}||  q1dS d	|v rp|j|  t|jd
krn| jd |jd
 |  | j	  |jdd  D ]}||  qfdS dS )NFc                 S      h | ]}|j qS r(   r9   r:   qnr(   r(   r)   r;         z*ScopeVisitor.visit_Call.<locals>.<setcomp>ztyping.NewTypeztyping.TypeVarTr`   r   ztyping.castr   )
r   appendr   r   re   r   r  argsr}   pop)r'   r   qnamesargr(   r(   r)   
visit_Call  s&   

zScopeVisitor.visit_Calloriginal_nodec                 C   s   | j   | j  d S r$   )r   r  r   r'   r  r(   r(   r)   
leave_Call  s   
zScopeVisitor.leave_Callc                 C   s   | j d d S )NT)r   r
  r   r(   r(   r)   visit_Annotation  r   zScopeVisitor.visit_Annotationc                 C   s   | j   d S r$   )r   r  r  r(   r(   r)   leave_Annotation  s   zScopeVisitor.leave_Annotationc                 C   s   |  | dS r   _handle_string_annotationr   r(   r(   r)   visit_SimpleString  s   
zScopeVisitor.visit_SimpleStringc                 C   s   |  | S r$   r  r   r(   r(   r)   visit_ConcatenatedString  s   z%ScopeVisitor.visit_ConcatenatedStringc                 C   sx   | j d s
| jd r:| js:|j}|r:| jdu }|r|| _zt|}||  W n
 tjy2   Y nw |r8d| _dS dS )z=Returns whether it successfully handled the string annotationr`   NTF)	r   r   r   evaluated_valuer   rF   parse_moduler  ParserSyntaxError)r'   r   r   top_level_annotationmodr(   r(   r)   r    s*   

z&ScopeVisitor._handle_string_annotationc                 C   sl   d}t |jtjr.dd | j|jD }tdd |D r d}d|v s(d|v r.| j| | j	
| dS )	NFc                 S   r  r(   r  r  r(   r(   r)   r;     r	  z/ScopeVisitor.visit_Subscript.<locals>.<setcomp>c                 s   s    | ]}| d V  qdS ))ztyping.ztyping_extensions.N)r   r  r(   r(   r)   	<genexpr>  s    z/ScopeVisitor.visit_Subscript.<locals>.<genexpr>Tztyping.Literalztyping_extensions.Literal)ry   r   rF   rG   r   re   anyr   r6   r   r
  )r'   r   in_type_hintr  r(   r(   r)   visit_Subscript  s   zScopeVisitor.visit_Subscriptc                 C   s   | j   | j| d S r$   )r   r  r   discardr  r(   r(   r)   leave_Subscript  s   
zScopeVisitor.leave_Subscriptc                 C   s   | j t|d }|tjkr| j|j| d S |tjtj	d fv rHt
|| jt| jd o-| j t| jd d}| jt|| jd | jd d S d S )Nr`   )r   r   )rW   r   r   )r   get_metadatar   r   STOREr   r7   r   LOADDELr   rK   r   r   r   r   r
  r   r   r   )r'   r   contextrW   r(   r(   r)   
visit_Name  s(   
zScopeVisitor.visit_Namec              	   C   s   | j |jj| | j|j| j  t _}|jr)|| 	t
|d  |j|  | 	t|t|j |j|  |j|  W d    n1 sJw   Y  |jD ]}||  qR|j}|rl||  W d    dS W d    dS 1 sww   Y  dS r   )r   r7   r9   r   r   r   r   type_parametersenter_contextr   r   r  r   r   paramsbody
decoratorsreturns)r'   r   stack	decoratorr/  r(   r(   r)   visit_FunctionDef  s0   


zScopeVisitor.visit_FunctionDefc                 C   sJ   |  t| |j|  |j|  W d    dS 1 sw   Y  dS r   )r   r   r,  r  r-  r   r(   r(   r)   visit_Lambda
  s   
zScopeVisitor.visit_Lambdac                 C   sx   | j |jj| | j|j| j  | | j j |j|j	fD ]	}|r)|
|  q W d    dS 1 s5w   Y  dS r   )r   r7   r9   r   r   r   r   r>   default
annotationr  )r'   r   fieldr(   r(   r)   visit_Param  s   

zScopeVisitor.visit_Paramc                 C   s   |j }|r
||  dS r   )r   r  )r'   r   r   r(   r(   r)   	visit_Arg  s   
zScopeVisitor.visit_Argc              	   C   s  | j |jj| | j|j| j  |jD ]}||  qt `}|j	r4|
| t|d  |j	|  |jD ]}||  q7|jD ]}||  qB| t|t|j |jjD ]}||  qYW d    n1 skw   Y  W d    dS W d    dS 1 sw   Y  dS r   )r   r7   r9   r   r   r   r.  r  r   r*  r+  r   r   baseskeywordsr   r   r-  )r'   r   r1  r0  basekeyword	statementr(   r(   r)   visit_ClassDef!  s0   




zScopeVisitor.visit_ClassDefc                 C   s   |  j d7  _ d S Nr   r   r   r(   r(   r)   visit_ClassDef_bases6     z!ScopeVisitor.visit_ClassDef_basesc                 C   s   |  j d8  _ d S r?  r@  r   r(   r(   r)   leave_ClassDef_bases9  rB  z!ScopeVisitor.leave_ClassDef_basesc                 C       |j D ]
}| j|jj qdS r   )r   r   r   r9   r   r'   r   	name_itemr(   r(   r)   visit_Global<     
zScopeVisitor.visit_Globalc                 C   rD  r   )r   r   r   r9   r   rE  r(   r(   r)   visit_NonlocalA  rH  zScopeVisitor.visit_Nonlocalc                 C   r   r$   _visit_comp_aliker   r(   r(   r)   visit_ListCompF  r   zScopeVisitor.visit_ListCompc                 C   r   r$   rJ  r   r(   r(   r)   visit_SetCompI  r   zScopeVisitor.visit_SetCompc                 C   r   r$   rJ  r   r(   r(   r)   visit_DictCompL  r   zScopeVisitor.visit_DictCompc                 C   r   r$   rJ  r   r(   r(   r)   visit_GeneratorExpO  r   zScopeVisitor.visit_GeneratorExpc                 C   s   |j }|j|  | j|| j | t|M |j|  | j j	d7  _	|j
D ]}||  q)|j}|r;||  t|tjrN|j|  |j|  n|j|  W d   dS W d   dS 1 sgw   Y  dS )a[  
        Cheat sheet: `[elt for target in iter if ifs]`

        Terminology:
            target: The variable or pattern we're storing each element of the iter in.
            iter: The thing we're iterating over.
            ifs: A list of conditions provided
            elt: The value that will be computed and "yielded" each time the loop
                iterates. For most comprehensions, this is just the `node.elt`, but
                DictComp has `key` and `value`, which behave like `node.elt` would.


        Nested Comprehension: ``[a for b in c for a in b]`` is a "nested" ListComp.
        The outer iterator is in ``node.for_in`` and the inner iterator is in
        ``node.for_in.inner_for_in``.


        The first comprehension object's iter in generators is evaluated
        outside of the ComprehensionScope. Every other comprehension's iter is
        evaluated inside the ComprehensionScope. Even though that doesn't seem very sane,
        but that appears to be how it works.

            non_flat = [ [1,2,3], [4,5,6], [7,8]
            flat = [y for x in non_flat for y in x]  # this works fine

            # This will give a "NameError: name 'x' is not defined":
            flat = [y for x in x for y in x]
            # x isn't defined, because the first iter is evaluted outside the scope.

            # This will give an UnboundLocalError, indicating that the second
            # comprehension's iter value is evaluated inside the scope as its elt.
            # UnboundLocalError: local variable 'y' referenced before assignment
            flat = [y for x in non_flat for y in y]
        r   NF)for_initerr  r   r   r   r   r   r   r&   ifsinner_for_inry   rF   DictCompkeyr   elt)r'   r   rP  	conditionrS  r(   r(   r)   rK  R  s,   %



zScopeVisitor._visit_comp_alikec                 C   sL   |j |  | j jd7  _|j|j|j|jfD ]}|d ur#||  qdS )Nr   F)r   r  r   r&   rQ  r-  orelseasynchronous)r'   r   childr(   r(   r)   	visit_For  s   
zScopeVisitor.visit_Forc                 C   s   t t}| jD ]K}|j|j|j}}}t|jtj	j
}|d ur5t|D ]\}}||jv r4||_|} nq$|d ur<||_||j|f | || |j|| q| D ]\\}	}}
|	||	D ]}||
 qcqWg | _d S r$   )r   r%   r   rW   r   r   r   r   rF   rG   r   r   r   r6   rA   rX   itemsr=   rZ   )r'   scope_name_accesses
def_accessrW   r   r   r9   	attr_namer   r   rY   r5   r(   r(   r)   infer_accesses  s0   




zScopeVisitor.infer_accessesc                    s:   | j || j t|tr| j jd7  _t | d S r?  )r   r   r   ry   _ASSIGNMENT_LIKE_NODESr&   rl   on_leaver  rm   r(   r)   rb    s   
zScopeVisitor.on_leavec                 C   sh   | j |jj| | t|d  |jd ur|j|  |j|  W d    dS 1 s-w   Y  dS r   )r   r7   r9   r   r   r   r*  r  r   r(   r(   r)   visit_TypeAlias  s   

zScopeVisitor.visit_TypeAliasc                 C   s,   | j |jj| |jd ur|j|  dS r   )r   r7   r9   r   boundr  r   r(   r(   r)   visit_TypeVar  s   
zScopeVisitor.visit_TypeVarc                 C      | j |jj| dS r   r   r7   r9   r   r   r(   r(   r)   visit_TypeVarTuple     zScopeVisitor.visit_TypeVarTuplec                 C   rf  r   rg  r   r(   r(   r)   visit_ParamSpec  ri  zScopeVisitor.visit_ParamSpec)r   r   r#   Nr$   r   )NrB   rC   rD   r*   r   r   r   rF   rr   r   rN   r
   r   r   r   r   r   rz   rK   r   r  r  rH   r  r   r  r  
Annotationr  r  SimpleStringr  ConcatenatedStringr  r  	Subscriptr!  r#  rG   r)  FunctionDefr2  Lambdar3  Paramr7  Argr8  ClassDefr>  rA  rC  GlobalrG  NonlocalrI  ListComprL  SetComprM  rT  rN  GeneratorExprO  rK  Forr[  r`  rb  	TypeAliasrc  TypeVarre  TypeVarTuplerh  	ParamSpecrj  rs   r(   r(   rm   r)   r   I  st    



8
"
 r   c                   @   s.   e Zd ZdZefZdejdee	 fddZ
dS )r   a$  
    :class:`ScopeProvider` traverses the entire module and creates the scope inheritance
    structure. It provides the scope of name assignment and accesses. It is useful for
    more advanced static analysis. E.g. given a :class:`~libcst.FunctionDef`
    node, we can check the type of its Scope to figure out whether it is a class method
    (:class:`ClassScope`) or a regular function (:class:`GlobalScope`).

    Scope metadata is available for most node types other than formatting information nodes
    (whitespace, parentheses, etc.).
    r   r#   c                 C   s   t | }|| |  d S r$   )r   r  r`  )r'   r   visitorr(   r(   r)   visit_Module  s   
zScopeProvider.visit_ModuleN)rB   rC   rD   rE   r   METADATA_DEPENDENCIESrF   Moduler   rK   r  r(   r(   r(   r)   r     s    r   )Trg   r   collectionsr   
contextlibr   r   dataclassesr   enumr   r   typingr   r	   r
   r   r   r   r   r   r   r   r   libcstrF   r   libcst._add_slotsr   libcst.helpersr   libcst.metadata.base_providerr   +libcst.metadata.expression_context_providerr   r   	AnnAssignAsNameAssign	AugAssignrs  CompForro  rt  r   rz   	NamedExprru  
ParametersWithItemr{  rz  r|  r}  ra  r   rO   rS   ABCr    ri   rt   rv   r   r   r   r   r   r   r   r   r   r   rH   rG   rN   r   rr   rK   r   r   
CSTVisitorr   r   r(   r(   r(   r)   <module>   s   4J	3!H j#<	
   