B
    ÀÅVÆ0  ã               @   sú   d Z ddlZddlZddlmZ ddlmZmZmZm	Z	 ddl
mZmZ ddlmZ G 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eƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZdd„ Zdd„ ZdS )z0This module can be used for finding similar codeé    N)Úlibutils)ÚcodeanalyzeÚ
exceptionsÚastÚbuiltins)Ú
patchedastÚ	wildcards)ÚMismatchedTokenErrorc               @   s   e Zd ZdS )ÚBadNameInCheckErrorN)Ú__name__Ú
__module__Ú__qualname__© r   r   ú:lib/python3.7/site-packages/rope/refactor/similarfinder.pyr
      s   r
   c               @   s:   e Zd ZdZddd„Zi ddfdd„Zdd	„ Zd
d„ ZdS )ÚSimilarFinderz`SimilarFinder` can be used to find similar pieces of code

    See the notes in the `rope.refactor.restructure` module for more
    info.

    Nc             C   s–   |j | _yt|j | ¡ | jƒ| _W n& tk
rH   td|jj	 ƒ ‚ Y nX || _
|dkrŒi | _x2tjj |jj¡gD ]}|| j| ¡ < qtW n|| _dS )zConstruct a SimilarFinderz
in file %sN)Zsource_codeÚsourceÚRawSimilarFinderÚget_astÚ_does_matchÚ
raw_finderr	   ÚprintÚresourceÚpathÚpymoduler   ÚropeZrefactorZDefaultWildcardZpycoreZprojectÚget_name)Úselfr   r   Zwildcardr   r   r   Ú__init__   s    
zSimilarFinder.__init__r   c             C   sb   || _ |d krt| jƒ}d }d| di ¡krN|d d \}}|| j ¡ krN|}| jj||||dS )NÚskipÚ )ÚstartÚendr   )ÚargsÚlenr   Úgetr   Zget_resourcer   Úget_matches)r   Úcoder"   r    r!   Zskip_regionr   Úregionr   r   r   r%   *   s    
zSimilarFinder.get_matchesc             o   s$   x| j ||ŽD ]}| ¡ V  qW d S )N)r%   Ú
get_region)r   r"   ÚkwdsÚmatchr   r   r   Úget_match_regions6   s    zSimilarFinder.get_match_regionsc             C   sR   | j  |d¡}d}t|ttfƒr0|d }|d }t | j||¡}| j|  ||¡S )Nr   Údefaultr   é   )	r"   r$   Ú
isinstanceÚtupleÚlistr   ZSuspectr   Úmatches)r   ÚnodeÚnameÚargZkindZsuspectr   r   r   r   :   s    zSimilarFinder._does_match)N)r   r   r   Ú__doc__r   r%   r+   r   r   r   r   r   r      s
   
r   c               @   sL   e Zd ZdZddd„Zdd„ Zdd„ Zdd
d„Zdd„ Zdd„ Z	dd„ Z
dS )r   z6A class for finding similar expressions and statementsNc             C   s:   |d krt  |¡}|d kr$| j| _n|| _|  ||¡ d S )N)r   ÚparseÚ_simple_does_matchÚ
does_matchÚ_init_using_ast)r   r   r2   r8   r   r   r   r   G   s    

zRawSimilarFinder.__init__c             C   s   t |tjtjfƒS )N)r.   r   ÚexprÚName)r   r2   r3   r   r   r   r7   P   s    z#RawSimilarFinder._simple_does_matchc             C   s,   || _ i | _t|dƒs"t ||¡ || _d S )Nr'   )r   Ú_matched_astsÚhasattrr   Z	patch_astr   )r   r2   r   r   r   r   r9   S   s
    
z RawSimilarFinder._init_using_astr   c             c   sn   |dkrt | jƒ}xV|  |¡D ]H}| ¡ \}}||kr||kr|dk	r`|d |k r`|d |kr`q|V  qW dS )a%  Search for `code` in source and return a list of `Match`\es

        `code` can contain wildcards.  ``${name}`` matches normal
        names and ``${?name} can match any expression.  You can use
        `Match.get_ast()` for getting the node that has matched a
        given pattern.

        Nr   r-   )r#   r   Ú_get_matched_astsr(   )r   r&   r    r!   r   r*   Zmatch_startZ	match_endr   r   r   r%   Z   s    	
zRawSimilarFinder.get_matchesc             C   s<   || j kr2|  |¡}t| j|| jƒ ¡ }|| j |< | j | S )N)r<   Ú_create_patternÚ_ASTMatcherr   r8   Úfind_matches)r   r&   Úwantedr1   r   r   r   r>   m   s    


z"RawSimilarFinder._get_matched_astsc             C   sJ   |   |¡}t |¡}|j}t|ƒdkrBt|d tjƒrB|d j}n|}|S )Nr-   r   )Ú_replace_wildcardsr   r6   Úbodyr#   r.   ZExprÚvalue)r   Ú
expressionr2   ÚnodesrB   r   r   r   r?   u   s    

z RawSimilarFinder._create_patternc             C   s<   t ƒ }t|ƒ}i }x| ¡ D ]}| |¡||< qW | |¡S )N)Ú_RopeVariableÚCodeTemplateÚ	get_namesÚget_varÚ
substitute)r   rF   ÚropevarÚtemplateÚmappingr3   r   r   r   rC      s    z#RawSimilarFinder._replace_wildcards)NN)r   NN)r   r   r   r5   r   r7   r9   r%   r>   r?   rC   r   r   r   r   r   D   s   
	
r   c               @   s\   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ ZdS )r@   c             C   s$   || _ || _d| _tƒ | _|| _dS )z—Searches the given pattern in the body AST.

        body is an AST node and pattern can be either an AST node or
        a list of ASTs nodes
        N)rD   Úpatternr1   rH   rM   Úmatches_callback)r   rD   rP   r8   r   r   r   r   Œ   s
    z_ASTMatcher.__init__c             C   s*   | j d kr$g | _ tj| j| jdd | j S )NT)Ú	recursive)r1   r   Zcall_for_nodesrD   Ú_check_node)r   r   r   r   rA   ˜   s    
z_ASTMatcher.find_matchesc             C   s&   t | jtƒr|  |¡ n
|  |¡ d S )N)r.   rP   r0   Ú_check_statementsÚ_check_expression)r   r2   r   r   r   rS   ž   s    z_ASTMatcher._check_nodec             C   s*   i }|   | j||¡r&| j t||ƒ¡ d S )N)Ú_match_nodesrP   r1   ÚappendÚExpressionMatch)r   r2   rO   r   r   r   rU   ¤   s    z_ASTMatcher._check_expressionc             C   s0   x*t  |¡D ]}t|ttfƒr|  |¡ qW d S )N)r   Úget_childrenr.   r0   r/   Ú_ASTMatcher__check_stmt_list)r   r2   Úchildr   r   r   rT   ©   s    z_ASTMatcher._check_statementsc             C   sh   xbt t|ƒƒD ]R}t|ƒ| t| jƒkr|||t| jƒ … }i }|  ||¡r| j t||ƒ¡ qW d S )N)Úranger#   rP   Ú_match_stmtsr1   rW   ÚStatementMatch)r   rG   ÚindexÚcurrent_stmtsrO   r   r   r   Z__check_stmt_list®   s    z_ASTMatcher.__check_stmt_listc       
      C   s  t |tjƒr(| j |j¡r(|  |||¡S t |tjƒs<||kS |j|jkrLdS |  	|¡}|  	|¡}t
|ƒt
|ƒkrtdS x t||ƒD ]’\}}t |tjƒr¨|  |||¡s¦dS q€t |ttfƒrt |ttfƒrÖt
|ƒt
|ƒkrÚdS x6t||ƒD ]\}}	|  ||	|¡sædS qæW q€||kr€dS q€W dS )NFT)r.   r   r;   rM   Úis_varÚidÚ_match_wildcardZASTÚ	__class__Ú_get_childrenr#   ÚziprV   r0   r/   )
r   Úexpectedr2   rO   Z	children1Z	children2Zchild1Zchild2Zc1Zc2r   r   r   rV   ¶   s2    


z_ASTMatcher._match_nodesc             C   s   t  |¡}dd„ |D ƒS )z0Return not `ast.expr_context` children of `node`c             S   s   g | ]}t |tjƒs|‘qS r   )r.   r   Zexpr_context)Ú.0r[   r   r   r   ú
<listcomp>Ö   s    z-_ASTMatcher._get_children.<locals>.<listcomp>)r   rY   )r   r2   Zchildrenr   r   r   re   Ó   s    
z_ASTMatcher._get_childrenc             C   sF   t |ƒt | jƒkrdS x*t|| jƒD ]\}}|  |||¡s$dS q$W dS )NFT)r#   rP   rf   rV   )r   r`   rO   Zstmtrg   r   r   r   r]   Ù   s    z_ASTMatcher._match_stmtsc             C   sH   | j  |j¡}||kr2|  ||¡r.|||< dS dS |  || |i ¡S d S )NTF)rM   Úget_baserb   rQ   rV   )r   Znode1Znode2rO   r3   r   r   r   rc   á   s    z_ASTMatcher._match_wildcardN)r   r   r   r   rA   rS   rU   rT   rZ   rV   re   r]   rc   r   r   r   r   r@   Š   s   r@   c               @   s$   e Zd Zdd„ Zdd„ Zdd„ ZdS )ÚMatchc             C   s
   || _ d S )N)rO   )r   rO   r   r   r   r   î   s    zMatch.__init__c             C   s   dS )zReturns match regionNr   )r   r   r   r   r(   ñ   s    zMatch.get_regionc             C   s   | j  |d¡S )z3Return the ast node that has matched rope variablesN)rO   r$   )r   r3   r   r   r   r   ô   s    zMatch.get_astN)r   r   r   r   r(   r   r   r   r   r   rk   ì   s   rk   c                   s$   e Zd Z‡ fdd„Zdd„ Z‡  ZS )rX   c                s   t t| ƒ |¡ || _d S )N)ÚsuperrX   r   r   )r   r   rO   )rd   r   r   r   û   s    zExpressionMatch.__init__c             C   s   | j jS )N)r   r'   )r   r   r   r   r(   ÿ   s    zExpressionMatch.get_region)r   r   r   r   r(   Ú__classcell__r   r   )rd   r   rX   ù   s   rX   c                   s$   e Zd Z‡ fdd„Zdd„ Z‡  ZS )r^   c                s   t t| ƒ |¡ || _d S )N)rl   r^   r   Úast_list)r   rn   rO   )rd   r   r   r     s    zStatementMatch.__init__c             C   s    | j d jd | j d jd fS )Nr   éÿÿÿÿr-   )rn   r'   )r   r   r   r   r(   	  s    zStatementMatch.get_region)r   r   r   r   r(   rm   r   r   )rd   r   r^     s   r^   c               @   s<   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	Zed
d„ ƒZ	d	S )rI   c             C   s   || _ |  ¡  d S )N)rN   Ú_find_names)r   rN   r   r   r   r     s    zCodeTemplate.__init__c             C   sŠ   i | _ x~t ¡  | j¡D ]j}d| ¡ kr| d¡d k	r| d¡\}}| j|d |d … }|| j krng | j |< | j |  ||f¡ qW d S )Nr3   é   r-   )	ÚnamesrI   Ú_get_patternÚfinditerrN   Ú	groupdictÚgroupÚspanrW   )r   r*   r    r!   r3   r   r   r   rp     s    

zCodeTemplate._find_namesc             C   s
   | j  ¡ S )N)rr   Úkeys)r   r   r   r   rJ     s    zCodeTemplate.get_namesc             C   sf   t  | j¡}x>| j ¡ D ]0\}}x&|D ]}| |d |d || ¡ q&W qW | ¡ }|d krb| jS |S )Nr   r-   )r   ÚChangeCollectorrN   rr   ÚitemsÚ
add_changeÚget_changed)r   rO   Ú	collectorr3   Zoccurrencesr'   Úresultr   r   r   rL   !  s    
"zCodeTemplate.substituteNc             C   s8   | j d kr2t ¡ d t ¡  d d }t |¡| _ | j S )Nú|z(?P<name>\$\{[^\s\$\}]*\}))Ú_match_patternr   Zget_comment_patternZget_string_patternÚreÚcompile)ÚclsrP   r   r   r   rs   -  s
    
zCodeTemplate._get_pattern)
r   r   r   r   rp   rJ   rL   r€   Úclassmethodrs   r   r   r   r   rI     s   
rI   c               @   sP   e Zd ZdZdZdZdd„ Zdd„ Zdd	„ Zd
d„ Z	dd„ Z
dd„ Zdd„ ZdS )rH   z.Transform and identify rope inserted wildcardsZ__rope__variable_normal_Z__rope__variable_any_c             C   s"   |  d¡r|  |¡S |  |¡S d S )Nú?)Ú
startswithÚ_get_anyÚ_get_normal)r   r3   r   r   r   rK   =  s    

z_RopeVariable.get_varc             C   s   |   |¡p|  |¡S )N)Ú
_is_normalÚ_is_var)r   r3   r   r   r   ra   C  s    z_RopeVariable.is_varc             C   s@   |   |¡r|t| jƒd … S |  |¡r<d|t| jƒd …  S d S )Nr…   )r‰   r#   Ú_normal_prefixrŠ   Ú_any_prefix)r   r3   r   r   r   rj   F  s    

z_RopeVariable.get_basec             C   s
   | j | S )N)r‹   )r   r3   r   r   r   rˆ   L  s    z_RopeVariable._get_normalc             C   s   | j |dd …  S )Nr-   )rŒ   )r   r3   r   r   r   r‡   O  s    z_RopeVariable._get_anyc             C   s   |  | j¡S )N)r†   r‹   )r   r3   r   r   r   r‰   R  s    z_RopeVariable._is_normalc             C   s   |  | j¡S )N)r†   rŒ   )r   r3   r   r   r   rŠ   U  s    z_RopeVariable._is_varN)r   r   r   r5   r‹   rŒ   rK   ra   rj   rˆ   r‡   r‰   rŠ   r   r   r   r   rH   7  s   rH   c       
      C   s‚   t |ƒ}t | ¡}dd„ }t| |d}xB|D ]:}x4| d| ¡D ]"}| ¡ \}}| ||d| ¡ q@W q,W | ¡ }	|	d k	r~|	S | S )Nc             S   s   t | tjƒo| j|kS )N)r.   r   r;   rb   )r2   r3   r   r   r   r8   ]  s    z make_pattern.<locals>.does_match)r8   z${%s})Úsetr   ry   r   r%   r(   r{   r|   )
r&   Z	variablesr}   r8   ÚfinderZvariabler*   r    r!   r~   r   r   r   Úmake_patternY  s    

r   c             C   sh   g }t | tjtjfƒr"d|  ¡  S x$| jd k	rF| d|  ¡ ¡ | j} q$W t | j	¡}d 
| d¡| ¡S )Nz__builtins__.r   Ú.)r.   r   ZBuiltinClassZBuiltinFunctionr   ÚparentÚinsertr   Úmodnamer   ÚjoinÚsplit)Z	pydefinedZaddressZmodule_namer   r   r   Ú_pydefined_to_strh  s    
r–   )r5   r   Zrope.refactor.wildcardsr   Z	rope.baser   r   r   r   r   Zrope.refactorr   r   Zrope.refactor.patchedastr	   ZRefactoringErrorr
   Úobjectr   r   r@   rk   rX   r^   rI   rH   r   r–   r   r   r   r   Ú<module>   s"   4Fb

*"