B
    ¢èåSK-  ã               @   s|   d dl Z d dlmZmZmZmZmZ d dlmZ d dlm	Z	m
Z
mZ d dlmZ G dd„ deƒZdd	„ ZG d
d„ deƒZdS )é    N)ÚchangeÚ
taskhandleÚbuiltinsÚastÚcodeanalyze)Úlibutils)Ú
patchedastÚsimilarfinderÚsourceutils)Úmodule_importsc               @   sZ   e Zd ZdZddd„Zddde ¡ fdd„Zdd„ Zd	d
„ Z	dd„ Z
dd„ Zddd„ZdS )ÚRestructurea  A class to perform python restructurings

    A restructuring transforms pieces of code matching `pattern` to
    `goal`.  In the `pattern` wildcards can appear.  Wildcards match
    some piece of code based on their kind and arguments that are
    passed to them through `args`.

    `args` is a dictionary of wildcard names to wildcard arguments.
    If the argument is a tuple, the first item of the tuple is
    considered to be the name of the wildcard to use; otherwise the
    "default" wildcard is used.  For getting the list arguments a
    wildcard supports, see the pydoc of the wildcard.  (see
    `rope.refactor.wildcard.DefaultWildcard` for the default
    wildcard.)

    `wildcards` is the list of wildcard types that can appear in
    `pattern`.  See `rope.refactor.wildcards`.  If a wildcard does not
    specify its kind (by using a tuple in args), the wildcard named
    "default" is used.  So there should be a wildcard with "default"
    name in `wildcards`.

    `imports` is the list of imports that changed modules should
    import.  Note that rope handles duplicate imports and does not add
    the import if it already appears.

    Example #1::

      pattern ${pyobject}.get_attribute(${name})
      goal ${pyobject}[${name}]
      args pyobject: instance=rope.base.pyobjects.PyObject

    Example #2::

      pattern ${name} in ${pyobject}.get_attributes()
      goal ${name} in {pyobject}
      args pyobject: instance=rope.base.pyobjects.PyObject

    Example #3::

      pattern ${pycore}.create_module(${project}.root, ${name})
      goal generate.create_module(${project}, ${name})

      imports
       from rope.contrib import generate

      args
       project: type=rope.base.project.Project

    Example #4::

      pattern ${pow}(${param1}, ${param2})
      goal ${param1} ** ${param2}
      args pow: name=mod.pow, exact

    Example #5::

      pattern ${inst}.longtask(${p1}, ${p2})
      goal
       ${inst}.subtask1(${p1})
       ${inst}.subtask2(${p2})
      args
       inst: type=mod.A,unsure

    Nc             C   sV   || _ || _|| _|| _| jdkr(i | _|| _| jdkr>g | _|| _t | j¡| _dS )z_Construct a restructuring

        See class pydoc for more info about the arguments.

        N)	ÚprojectÚpatternÚgoalÚargsÚimportsÚ	wildcardsr	   ÚCodeTemplateÚtemplate)Úselfr   r   r   r   r   r   © r   ú8lib/python3.7/site-packages/rope/refactor/restructure.pyÚ__init__K   s    

zRestructure.__init__c                s>  |dk	r>t jdtdd x$| ¡ D ]\}}t |¡ˆ j|< q"W |dk	r\t jdtdd |ˆ _t 	dˆ j
ˆ jf ¡}|dk	rŽ‡ fdd„|D ƒ}n
ˆ j ¡ }| d	t|ƒ¡}	x|D ]ˆ}
|	 |
j¡ ˆ j |
¡}tj|ˆ jd
}t| ˆ j
ˆ j¡ƒ}ˆ  ||¡}| ¡ }|dk	r.ˆ  |
|ˆ j¡}| t |
|¡¡ |	 ¡  q®W |S )aó  Get the changes needed by this restructuring

        `resources` can be a list of `rope.base.resources.File`\s to
        apply the restructuring on.  If `None`, the restructuring will
        be applied to all python files.

        `checks` argument has been deprecated.  Use the `args` argument
        of the constructor.  The usage of::

          strchecks = {'obj1.type': 'mod.A', 'obj2': 'mod.B',
                       'obj3.object': 'mod.C'}
          checks = restructuring.make_checks(strchecks)

        can be replaced with::

          args = {'obj1': 'type=mod.A', 'obj2': 'name=mod.B',
                  'obj3': 'object=mod.C'}

        where obj1, obj2 and obj3 are wildcard names that appear
        in restructuring pattern.

        Nz]The use of checks parameter is deprecated; use the args parameter of the constructor instead.é   )Ú
stacklevelz^The use of imports parameter is deprecated; use imports parameter of the constructor, instead.zRestructuring <%s> to <%s>c                s   g | ]}t  ˆ j|¡r|‘qS r   )r   Zis_python_filer   )Ú.0Úresource)r   r   r   ú
<listcomp>†   s    z+Restructure.get_changes.<locals>.<listcomp>zCollecting Changes)r   )ÚwarningsÚwarnÚDeprecationWarningÚitemsr	   Z_pydefined_to_strr   r   r   Z	ChangeSetr   r   r   Zget_python_filesZcreate_jobsetÚlenZstarted_jobÚpathZget_pymoduleZSimilarFinderr   ÚlistÚget_matchesÚ_compute_changesÚget_changedÚ_add_importsÚ
add_changeZChangeContentsZfinished_job)r   Úchecksr   Z	resourcesZtask_handleÚnameÚvalueZchangesÚfilesZjob_setr   ÚpymoduleÚfinderÚmatchesÚcomputerÚresultZimported_sourcer   )r   r   Úget_changes^   s@    






zRestructure.get_changesc             C   s   t |j| ¡ |j| j|ƒS )N)Ú_ChangeComputerZsource_codeÚget_astÚlinesr   )r   r0   r.   r   r   r   r&   ›   s    
zRestructure._compute_changesc             C   sR   |s|S |   ||¡}t | j||¡}t | j|¡}x|D ]}| |¡ q8W | ¡ S )N)Ú_get_import_infosr   Úget_string_moduler   r   ÚModuleImportsZ
add_importZget_changed_source)r   r   Úsourcer   Zimport_infosr.   Úimport_infor   r   r   r(       s    
zRestructure._add_importsc             C   s4   t  | jd |¡|¡}t | j|¡}dd„ |jD ƒS )NÚ
c             S   s   g | ]
}|j ‘qS r   )r;   )r   r   r   r   r   r   ®   s   z1Restructure._get_import_infos.<locals>.<listcomp>)r   r8   r   Újoinr   r9   r   )r   r   r   r.   r   r   r   r7   ª   s
    zRestructure._get_import_infosc             C   sT   i }xJ|  ¡ D ]>\}}| d¡ o,| d¡ }| j||d}|dk	r|||< qW |S )zpConvert str to str dicts to str to PyObject dicts

        This function is here to ease writing a UI.

        z.objectz.type)Ú	is_pynameN)r!   ÚendswithÚ	_evaluate)r   Zstring_checksr*   Úkeyr,   r>   Z	evaluatedr   r   r   Úmake_checks±   s    zRestructure.make_checksTc             C   s€   |  d¡}d }|d dkr2G dd„ dtƒ}|ƒ }n| j |d ¡}x0|dd … D ] }|| }|d krhd S | ¡ }qPW |r||S |S )NÚ.r   )Z__builtin__Ú__builtins__c               @   s   e Zd Zdd„ ZdS )z,Restructure._evaluate.<locals>._BuiltinsStubc             S   s
   t j | S )N)r   )r   r+   r   r   r   Úget_attributeÅ   s    z:Restructure._evaluate.<locals>._BuiltinsStub.get_attributeN)Ú__name__Ú
__module__Ú__qualname__rE   r   r   r   r   Ú_BuiltinsStubÄ   s   rI   é   )ÚsplitÚobjectr   Z
get_moduleZ
get_object)r   Úcoder>   Z
attributesZpynamerI   ZpyobjectZ	attributer   r   r   r@   À   s    
zRestructure._evaluate)NNN)T)rF   rG   rH   Ú__doc__r   r   ZNullTaskHandler3   r&   r(   r7   rB   r@   r   r   r   r   r   	   s   @ 
<
r   c       
      C   s^   t  | ¡}t| |¡ƒ}t | ¡}t | ¡}t  |¡}t	| ||||ƒ}| 
¡ }	|	dkrZ| S |	S )zused by other refactoringsN)r	   ZRawSimilarFinderr$   r%   r   Zget_patched_astr   ZSourceLinesAdapterr   r4   r'   )
rM   r   r   r/   r0   r   r6   r   r1   r2   r   r   r   ÚreplaceÒ   s    



rO   c               @   sF   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zdd
d„Zdd„ Zdd„ Z	dS )r4   c             C   sR   || _ || _|| _|| _|| _i | _i | _|  ¡ rNx| jD ]}|| j|j< q:W d S )N)r:   r   r0   r   r6   Úmatched_astsÚ_nearest_rootsÚ_is_expression)r   rM   r   r6   r   r0   Úmatchr   r   r   r   â   s    z_ChangeComputer.__init__c             C   sŒ   |   ¡ r&|  | j¡}|| jkr"d S |S t | j¡}d}xH| jD ]>}| ¡ \}}||k r`|   ¡ s`q>|}|  |¡}| 	|||¡ q>W | 
¡ S d S )Néÿÿÿÿ)rR   Ú_get_node_textr   r:   r   ÚChangeCollectorr0   Ú
get_regionÚ_get_matched_textr)   r'   )r   r2   Ú	collectorZlast_endrS   ÚstartÚendZreplacementr   r   r   r'   î   s     

z_ChangeComputer.get_changedc             C   s   | j ot| j d tjƒS )Nr   )r0   Ú
isinstancer	   ZExpressionMatch)r   r   r   r   rR     s    z_ChangeComputer._is_expressionc             C   sz   i }xT| j  ¡ D ]F}| |¡}|d kr4t d| ¡‚|  ¡ oD|j|k}|  ||¡||< qW | j  |¡}|  	| 
¡ d |¡S )NzUnknown name <%s>r   )r   Z	get_namesr5   r	   ZBadNameInCheckErrorrR   r   rU   Z
substituteÚ_auto_indentrW   )r   rS   Úmappingr+   ÚnodeÚforceZ
unindentedr   r   r   rX     s    

z!_ChangeComputer._get_matched_textFc       
      C   sš   |s|| j kr|  | j | ¡S t |¡\}}| j||… }t |¡}x<|  |¡D ].}t |¡\}}| || || |  	|¡¡ qPW | 
¡ }	|	d kr–|S |	S )N)rP   rX   r   Znode_regionr:   r   rV   Ú_get_nearest_rootsr)   rU   r'   )
r   r_   r`   rZ   r[   Z	main_textrY   Z	sub_startZsub_endr2   r   r   r   rU     s    
z_ChangeComputer._get_node_textc             C   sl   | j  |¡}t | j |¡}g }xBt| d¡ƒD ]0\}}|dkrT| ¡ rT| d| ¡ | |¡ q.W d |¡S )NTr   ú Ú )	r6   Zget_line_numberr
   Zget_indentsÚ	enumerateÚ
splitlinesÚstripÚappendr=   )r   ÚoffsetÚtextÚlinenoÚindentsr2   ÚindexÚliner   r   r   r]      s    z_ChangeComputer._auto_indentc             C   s\   || j krRg }x8t |¡D ]*}|| jkr4| |¡ q| |  |¡¡ qW || j |< | j | S )N)rQ   r   Zget_child_nodesrP   rg   Úextendra   )r   r_   r2   Zchildr   r   r   ra   *  s    


z"_ChangeComputer._get_nearest_rootsN)F)
rF   rG   rH   r   r'   rR   rX   rU   r]   ra   r   r   r   r   r4   à   s   

r4   )r   Z	rope.baser   r   r   r   r   r   Zrope.refactorr   r	   r
   Zrope.refactor.importutilsr   rL   r   rO   r4   r   r   r   r   Ú<module>   s    J