From cdcd77096fb4da4594cab33296d04e4478a8ad8a Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 22 Apr 2014 15:21:24 +0200 Subject: [PATCH 01/86] IDEA-123687 Velocity formatter inserts wrong linebreak --- .../templateLanguages/DataLanguageBlockWrapper.java | 4 ++++ .../formatting/templateLanguages/TemplateLanguageBlock.java | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockWrapper.java b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockWrapper.java index 08ead45552ce..7a43a184ce53 100644 --- a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockWrapper.java +++ b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockWrapper.java @@ -104,6 +104,10 @@ public class DataLanguageBlockWrapper implements ASTBlock, BlockEx, BlockWithPar @Override public Wrap getWrap() { + BlockWithParent parent = getParent(); + if (parent instanceof TemplateLanguageBlock) { + return ((TemplateLanguageBlock)parent).substituteTemplateChildWrap(this, myOriginal.getWrap()); + } return myOriginal.getWrap(); } diff --git a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/TemplateLanguageBlock.java b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/TemplateLanguageBlock.java index e4c8f40bb9ef..261cdeaa52e7 100644 --- a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/TemplateLanguageBlock.java +++ b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/TemplateLanguageBlock.java @@ -137,7 +137,7 @@ public abstract class TemplateLanguageBlock extends AbstractBlock implements Blo } protected Wrap createChildWrap(ASTNode child) { - return Wrap.createWrap(Wrap.NONE, false); + return Wrap.createWrap(WrapType.NONE, false); } protected Alignment createChildAlignment(ASTNode child) { @@ -152,5 +152,9 @@ public abstract class TemplateLanguageBlock extends AbstractBlock implements Blo return myForeignChildren; } + @Nullable + public Wrap substituteTemplateChildWrap(@NotNull DataLanguageBlockWrapper child, @Nullable Wrap childWrap) { + return childWrap; + } } From bf06d9dcf9b54f271d3e92b15ab1c61ed0d9a5fa Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 22 Apr 2014 16:27:20 +0200 Subject: [PATCH 02/86] read-action for getFilesForFastWordSearch --- .../src/com/intellij/find/impl/FindInProjectTask.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java index df47eead5c5b..90d2cc6385bd 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java @@ -121,7 +121,12 @@ class FindInProjectTask { try { myProgress.setIndeterminate(true); myProgress.setText("Scanning indexed files..."); - final Set filesForFastWordSearch = getFilesForFastWordSearch(); + final Set filesForFastWordSearch = ApplicationManager.getApplication().runReadAction(new Computable>() { + @Override + public Set compute() { + return getFilesForFastWordSearch(); + } + }); myProgress.setIndeterminate(false); searchInFiles(filesForFastWordSearch, processPresentation, consumer); From a95fd00fb31440bd7a2cb13b039b7ccb6536b74c Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 22 Apr 2014 16:42:20 +0200 Subject: [PATCH 03/86] remove copyright messages --- python/resources/pycharm_core_logo.png | Bin 30853 -> 43084 bytes python/resources/pycharm_core_logo@2x.png | Bin 41444 -> 50694 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/python/resources/pycharm_core_logo.png b/python/resources/pycharm_core_logo.png index 4fc68fae7b26f620be684346a7cff3f884870958..aa19d19984c6ec559d14cef235186c5e7d29b8a7 100644 GIT binary patch literal 43084 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
  • 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 diff --git a/python/resources/pycharm_core_logo@2x.png b/python/resources/pycharm_core_logo@2x.png index 9dfe7d323ce622d90e1afcf447114a5e7340ab72..97912f54bd9b497b384e9a5811657e7aeaad26b2 100644 GIT binary patch literal 50694 zcmeF3bzGE9_wX_C77!FcX#@r7?vhqgX#~UtmhN3@NkzJ(8w3QTmXdBM=~!T;m0p&R zT$=adj_2l%=jZQzKkuLNK^SMwIWzN}nKNgG>)L>)O0sy@Nv~sJVc|V_ETw{lb%`1a z>!Q}Ri$D(1Z6bQ$*Dtn@wINtoID}{aE?^}j-NnKZNHvn|Nb0t}@#0GpUui_omsG|*6+8Hvzn@+h(^+Dd{=%^t(-!KyGNHA9$% zp@0#MnCNw3XFor8;wor{fwi-m(zkX=BKgNOR}FB;M7KuXx& z$XHNCO6K?Kfd7fmm_nhpf^2L~PEM>&T&y{H8DY++5c?l-|9Cq{Ev>UgT3Xipp6XKz?NVupdJXofa6~Q*qYivZ6KyL|E0?R6#okG z-ztWh8UGi6XC?nt4eV_8U)0V@epCB(PW?92!T=OSML}hIGhq6IETwD=9nSjoL`oDW zU^Ox`5(M)a7;x}`jadvhKQ%_YFgFU>E(FT*Y_z|F%YA^C^-bE^L^`@|Xo1z8({e{Z=N z&~jr=P7VVuZbKF$BLSejMnDQ=$Sc4CGUj0i@pA}pgZTyiFnvz_AEu?i_GXS?BN=-e zt6vw4Eyx}MKAXHEG=I$A|E#dzss1|s1*qD>YfQ18O%*VpX&CSPR0A>fV zu=9cqK_CtzPB6$&nC&0xf3^vzK=`*}qyN{j`iJ_T*8jk9uFLetfJop{ssE~ZX*0c z{lC}YWD2$x1-v#l3p+OpC#M<*uOK&vAU78iJK(sbCVG5$IBXUkep(jE)~=7gG!jpYw|@^|S!oAjq4uoMUiKI04QhwLmI0%{z5 z09HY6-aq*M$H;Gzf3u-zV`OIR@`sK8Hb!SQ&Po2=2C$18fuNxOm6h|d=j<363L4wk zTY;dWW>z2*Fq^Hli7?xrndc<`vl|FX+F07y1I+@9atX8jTlP7vvwh&qa|6={^y@<5 z5N7*F-rwc5&RmwI!>{suob13C8^_tt-&M~S|6Nu4e^xzT{CCwqHPx-nprV|=*Y>yU zb6RJc)o(CVfdCCG%FDyU#Usr2_w2uGJT-F$TWU#}0ecwa%ysaeb?jHAznA>0ruLtj zynod^SMs~&Z>!{7F!k#q`Yjg-)qp6G?LT4SU)R@vJl6l`#GhUI|7`fYxu2Dsr}4w| zPh3AlbY9>muJbg0nEr|DhltJ#{KR#h#t+j!as3d{d4Zp}&eQl|`X{a*B04Yd6W4hf zKTQ9`^+QDG1%Bc>PveK_pSXUA=)AyBT<2;0F#QwP4-uUg_=)R0jUT3e;`$+?^8!C{ zou~1`^iNzrM08%@C$94}ewhA=>xYQW3;e`&p2iQ;KXLsK(RqQNxX#n~VfrVoA0j$0 z@Dta08b3_`#Pvf&=LLS^I#1(=>7TfMi0Hh)Ph96|{4o6!*AEe$7x;6itaQBEwYpjgIZR_? zo*bT5X1khogG!idkoMED5V7?)6y?oReZJ}~-^9fDL<+9Ml`qBXv+E}rVcLd+u|wIx z2T>3uH^xd+Snq2{+kM0FtyrP#tQh$WWIUhP?As4lq$7S|+I`(nOsJhdcJ3I$*Q%_h< zhSQ!uI#kjEX(W8X={cr(vM$?8Vwfb##>2n(y7Xb9vGD0rI7zN9>?FI1% zU^hH?i+%I?6FPxe*NZ%Fw19G3(@XiQpJhf)K*;P(ELc@QJ!{AP=Rg4#c`}wf$sM~k z5|a|rE30C?xnvbq;~q0pfwCb$sTWor_@2salfH`Fy=8p+LcGj!p~}5HdRRnW%FOC& zZ0>QO(GIp;gO<+J1Y4%qPU5(nkcYU)aN20d!Xr;oqbfWt3yjR#89v*$~UKlfi946PA{Nk$gbWQvo_ejDptXKmt?DojEy&lp6X3@_^vj_4$ zLS$DF^x-=DBgH@A)@yWYa(mXR)IA@_osISRq9HCswcF5}vPg*7n;UtjZ;^py9CD>j zBds}5zxU*13OVHc0JFufw6-s?iZ+bsaM%0#AQCU;*qqf_;~LOK><`f*TDkq;!@4Gz zr|9>?bqeu#qmubT{YyaM#eDB;*`KdvZ&d8%6+b#YD3|G-nl9wS zgIr{;T?&Ssi2Cy#MK>ju*!=?BcYtlIP^QaggN${p=Ui(h!yz$>HaYB7dnnr0l8*$ka&cwmee>@f za;`Mvy|eBSkan2)%5qp2ctF51?vs$kQ>Ux$6Sjc4);@3f|fD>7&ev{?;O@pceNt3k9tH?agMAg)4Yk%Fw67^|y_c6Dw@IWN( zk;d^9aT)GBo4MZZGJ)$W(W@whey9etdg%2%si3j@s+M^gJp$eK?qV(Wl1UFyu)Cn% z#&3+uAD6FW*|PYFhCX-Xxo)>>%pzp-hW2?m_JgXhCGSy4PPC=7YA5mc@H7+GRB1(>O5Z+JvGaCwEPXz_L)!NXqAT8DbnC6 z(jFTo!3;sY?0dRp!2~<^B*<~^JouhKS@kd(7oZ7{}i4kbM zaaN>`_la~m%BuDD{(NGe+v=gUzy6S0)=OA#L6;Saq-6&?$(%#7wE&dYk<#E4rg-{7 zS_3MbjgmZkY}YqmFE zA_|1t1G5&%tqY8TJf6js^3|#JZAn;~!0-=oMSfj8*f-8iLag%(>iq2dz2LV_zoURQ zvkRL0e42~T+}b~&Ob#El7!bq}UyQX8?PJe|AQ00J3@y}IUvg%bo2m~fExI^;KAH^_ zJ~8S_YmoOOrJJrs^LjG(#}~Rc><4#mXQwPir1Ca+5;c4P4`2E8G3lv^#6fRd5J3ax zd-8a*y4|%>jnz?&0t-!HsRz*`s~IC@d5%_#%cFmE0r!9I!lU;7;$L25i|u_=KCC&6 ziag$!K6+9g*S-MEOJG`>C-h(Uc`a{j8Q5z0n{YWWqo=sVDb`b^Qp@mB8Edd0c z_lmu$ky3EXlvBAM*L<}u=w^Q>ww8}>& zP1iWbVZr1o9yN6L_@>?g^K%ixbnG*4@zv|zxs~)6FK~V(*{ZFwMY;-;2F2Z+H>xt2 za6FV!%m}40Vncom7J$YkFMLV34ck( z%h(5IHq20(62#dKjdPn2jfZNE%(?d5!MWL-2}uTI?W+`&BbBn<`&9FZ;!R=}4to|` zG{Fa1TLoPN=oP*?jqQ;v9i_P1U2Z|9>Y2uo9pauUu7UQ#&DxRe6Fe@HCg~sz0Rxg)ilG2UfN;NK*R?3!P;(7qrGL+&z|}%H8zD#r${n4N_iAj4iw`N3B*S`wVPbU!OOsLy3fWw_Ok?GU4+A*)$Oj4mb?BB;Sz0xjyUulPhvhRd%%%k+N1R2?R6N4`N| zrSkDZ6{3v$lNvYZUOD8haLbE#IyK9|LnW#zJB+%ARAMlUU#opU+!&`quYh~7dx@^aeun6wgoH#(eB#S%Ou;9;N-x%^yh zoAVbb2rTFL?0}Ck!Rjw|#Mtu_G5UVjW1|dPv=?CXE$S|C+ug~pTR+^sj?>1IHh@@? zm`xfd5_IO&LuM{!T&av@QI{LsLVaZ*4m&>T(r0k(0xZ2V{B6{J+Z})8mL#i$s3~-u*E|=%s~CB} z-BP}JOrZTqJ5E5g{WTSxq}?@WSHD9BO2Dr}Zz{h1rlt`(tMmv#Pf&oG_Z>S7%*WJ9 zTRa#a8fz|4_m{&B&Tkx-a2Y(R%NKfdbG0FYhv;$QrPAXCf|)bdud5 z+;opeNX*W7-Cb){&yq8ypPPj;4B_-DY3ova8#`{blOp0Hf?g@!f$>}I^|aZ6$~GSZ zQ3)>YONzi}!+iC>tmTwCF})TGA1~$|6f<}%N#Au1r?<>|$=GdiP$#tRa3gb~iaHBs z`!vM$byT^!Bd0tAYTqPzd6`O)R)UxE3eEDa z=)VuA^>`;OtY2M!5Kz+>XJ4}X(2p8o80?}_r`r)n^^#LxuA|DH^OYblFO!L1x}>xV zWLps7+=C5H=4eI4wUy+nG3St5EmpH~C^{&TbG|Fy{+x62-ga}y05^zZfGTaFx%=8y zU0R&1k|9T*@tp1RX@Ae1B~(v4zPV@HR0kuk+&nO;$P=;hv{(g0GahE%3EHn$RyIt? zn&sbSG7Nv*Qf@Uf9AVBP0TYLl?YQgn8(B&9ywo+^=7vS>hZ>O5_SRm9d`R&9RJ zI_&~$;8l=fI-5!c--+)5rvKsv+U1%#v>ZzN4I2Aj;lwh=R4mni>k@bcb$nToG`zVjmFsHYbtXCfSnw_<1DR&l&AuSk-m~2ee=N0sAj3_n4!@;W*k7V>kDGWk z&G;T}TO5oujYHg;70yB11hr4Dnu=6-H|jv%u^F1jT%A;cJHFKgmsK{tW>ZOSDiLD3tRSI45zS+_>$rS7dK4N$t4Te$}xT0lO@`H~Ugws0+{eh4qa+XOoLBNq4&_ zHr7%cmIZB1Rrn-sgIc?L;(kPEhyo&CjSNc%@}M2n{8ZH1y-8`;VEx1{@F4Yzh+Ck z1Cl(((kcTspM!uNIML*?@G$lLO-v^pvN9fZ<3it7JUy9*lvRfYcsv{95l1WSzc7A( zF&!m$LrPJzdJRwo1{}iWOSJ+S27q*YnH-CGr0+;*hT&%$185{msl0(hXP_g~Ol5uF7Ysv}9Z8 z_;_xupM0W*3_I7a9}e~tp&_eBIr!6+j}^XS^xd5>9UnJkwIw7=(fmnZ8s8GScWv6b z$fbpry9fc#l*A7H9BTQsz&P=kM0TirbZ`4@3EL4u9`yzyj0P5#EO%oGMdD~6^NRqf zbT!6-OnZZ3t+c1_V&=x+vzEp=xA=U`?rIo8487yp0<~II!ecc9%u1?`Gnl3eZ#(Yde}u6O&f2X&u)H*` zYT@N^`aQ%7_}JiVwA9;YLRa-qEW(yliT@w6*K)UbQ&gK$woAw%|td*qXxhr7&~ zKrG=V+{boXzHEoE*=RD_$as!jz@>SP?M5U|V*LtE!G5n;NO$|{lk#VdQLQO}V@^kd znQn+^k8!3~m#e@ZBF%^Vt)r~K#fweO_tz_3#xv>Bfp>ig@*cF>Us-GpxVB}KF>>d= zq#aW)ZlL9%QFB^Dp5XB10GmX!;%z~MzzoWP*hrS&{b*3uG_D)Dy*@0lGfAdc7|jT& zyOTc8?Rhn;f-4&%fnbT?Aeq6Ul=@~i+nQAje;iZ4YAI5C7D#aF2z4)h(_2> zz6<~vyq@-8JI?kzMQt7sb12df^HdvzKb{-5lmrfmCpAzh^vkXrmKTpda8wd`57j8filif$V zyPDsOS>@a!vU(UTH^1dlO$?$5|2%Ksq9CJEjL)Wja(udZDxt9Dc|3h&(r}uAVUEup z`LaA%*?v8!7L}hw{ zeRscN6LZgvlF%%I1jhbv!6Xt7gG4M|g(2Q2bCGA#-i zlWJcWF2djG0aP_C6Fuz)3)T6;tQMI03Fcu4a1(CX>A?I+K+{{UVuSEBt_(>N z8O;a>^=oYS_1g1fy(c^1+|ylhCkt?CQOdZM z7KE{PWN>XoTBfBN7fSD{avUjH3{8q#9mTN0```w`F@lYoq;p_m@?;&BVtPD{t^E;o z?ExaQHehS+t_ptErEXNO@sUXoa(uFe{hmSBqv#3GcvO1nl^ldF5(Kv_!bl^?UiB{I zo28@H2VH@Uf9@4!v5=@5xpzLwkiFXp#bW0BS#PS^!Lj2$Lp?O%1)P{hNWh)>O^1cD zCzAbxyHSEnz$)yFZR7f9c(pQwuTvRA5jmp;((Mp1_R+d!zz|k!(ThffM zO`|5Cewqb8O*R4q?hb|>&Jog$`Rrp)+GVh)9CAk+Sz{_0izi*^T;`^S>#9f_n$ z;C9fSNoV>5wW#P;{87Djg=$JchvIc$?)*BDl2jbx7{iFlAnVjCbJNh{i@(LaxGt!oOpSfi6l_u(j)5q zGIHLF7n!{%xcw3no_!o{O<|dY-p^=nQ=es@#^}u(Rnx^i?NzjGa#(}Cc-z>!lWFf8 zx*ntFTAJ@X9S9kr;CS#N9k`AiG0`l(30wrO%*oNk&*li3-;Ye$zNEmQ*T*D4q<)!j z;EHCi;Mt8^JInj^Q4!I);Fs-r4J4r{Oky5+Ci!7;U#Hj_blmHM@vg|q zFjIIgrh3#Kr$!shmwIAw&MxMP=r4|NbD3XPG_7vCyCpL1pj$EHoZC`Fa%d)~{@}rQ86(n%d9PZ&YLFSl zM9jC<+9MG+6iY!f75#Vz98rgoa^j5eCk;P9y-W&J?If1dY5inuZ3q%+h!MHiKq07~ zPOpwx_vzUU>*1s^K5hBB>j?`LLOzM7-IgI4M@ec%;Pa?WMu@EbY4I2wq%vJ~a{Z zr!#arWf>`(+}R(V&&FZui*-{DkE*OvM(IxFDoh*c4kwfH^9*r~n6%Q0d*p*iWb}<| zHUlhb(4|a4VGDUA)!zBa4i{nggAAd~N%YNcyanU=!VwLEE%qo~iS6)PS;IaSk z|NX|$Z(PgO7R$$k-oUqG4yQYMw0o7|ls)Rv5(U-WD*lueMW1Q`-kp<1wr4`Hcu1iyuoslE3G+e8~(LTgxk}3e6LnOu>@BmIj23 z!PJXcX1D4>hv5x^L`)W@2{DDvdNQx$=ro~skQJ4x@3M-w>en-A)l6n(1T1XDK+lpZ z@_Y*3FwkD*3CVV?jSSf{*T`uI3xcu_vN+`8H< z$?dSaG3T3iGRs9~(`424)V%RN^H|2d1~X6nfq*=Ei_2b(Sxyh#Gxhg2O1 z<8w4i z-^DEwF4OwbP1|S?TpXwe5>*|cVUCvTeE!Dg;_#MQC|L@cl!#H8)Ts-;2rqnwc+WKn zN8jEYk|&%LsmnAdR!cX(xx2k0I;n_H5H7ZL~+Ta`R*(+2J~ndpmk z7L=bd9DVjF9y_&E>s#c%3b+K&V+N$L#)z?oZ*OqQ;nE=dyL3fxDV1*Jj?=WG1k~Xh zwq}*-lVMF^syCNzTw^xe9^7k0fqME$r8R@_$EZ5DQE3;& zx-W$qka=Z66QL6P-cH_{K}X@n2mMdeNqWk7#<^A8zswh(Y}-09QfAOIx%j|M2l3;~ z6v&e)>dI<2_VTbzrW-2J>&=U8lpe4OJqvIv?P9&>183;G>&d}N=fT8tYj9o^)9Ups z{>5-3?wEk=1Fra{H7&ZesMSw0lzsx-_eNuRnSuH6Jm4`;N5PCjS<%UNJ|~fJ)SGB! ze5jR)w_&h);C!!}s6Q4?Xo-D&?a50sD@FIN;qh^_g}wU|4zOUPqh+?1TJYPTR)ZL@ z$ibS&+j*r)&s>GcZRHauPop*#WuExi8lCwhbl&t^_OgufLX&k-sv7Q_ifjJjhi%wn zcV8wSFGYYz#IvAQPP@HZt$wBO)e&E{GQ?vB`B4J~9o@tipx{={jjTw&rVS`c)@G!~ zRJyCc*u+LzT?p=MQadeLUdr3Mm8dM_n24U2JFamQJk23CczmH#=!4LmHy;+3qglGd z^L1bO)&L*q2%W~bp;ku^q2uoi{oTo@pMZ911QA@BAug~^9dzmBDh_q=OC#D$6pvX8eSe6{1Q!3XeE1VK*1(U<)NRz{KH%g?!CjWsBhgbHQ(+R zit2l8wjS5*ySmwD1|{wr96M#*7K_G7L(3pA6W=x~8JXO;_j4A@87Xil$C}9*Kputi zCol9z)=gA)qmW|ZyIF08$;+gx@pU5Vozb65x%OR0>$yH7kGT^9SMx(=3q-YpWiop7 zu=V_wBTGB#-hG%M_-cBQKVS5t%qc!9OiRo#`{Zp($zj8>z9EF-!f2+VBN#)Kk)xIQ zy?Xk=5U$nCK|HmpXv2ol!U)%j(2`LxR5&ISKZUZRz*=z{RxVmI))p55!*cN*eT5tWlRi{N$>O_WjSBcl< zpds6I)sf*wAICbrMXk(eaMXM(7Ohwi=yAGX*J~K>oGwJ7*iIYpfrQ7Qi(oA1&;#iR zY~M+23rKq%d9ryoGb#x2r$D4y)A+vD1gp9*a=eUA#L#^*!@VO#t?Y@~^?4o7Lk9=W z$$m1TFUCpHTl0Dp>kbj0VWU%+LW=C5`&rPUI+T$*i~AfvxrjXahJqAUhm%@(4(^IF6fy~HCyl%B}{d5b>i?I zMrHc=L4rBb0>W|Vqqww_pPRcvqe<38?RJdPO)w4*BmC(O2QOv&2_to2!eXu#=IvkE z=cQYRYGhqqm9~Mi4q08qt^_78LVUk$k>k zAE{q=a@S&e(Ag>o*tQ{L`I5|$OK&1?0pS_{r)RP4ce@I#lc_3e(LVKBbj9CamIr`B zkLmq(ZxBzxImcbo8$eE<<&{Ry)(5XOaWkh{8ydPAiCHJZpFgX@Q ztMezSHsEv7skJ;#HV31c_!c^v_iu_E4rFe785mLCF<4qLT@N^^Y1p%dY)~U?=a8j{ ziqv0#=Xdr)CgA<|BZ8%8ZZh2rF}c-=p*KM74Ntot^0aGJgK?86bB?>Vo$&lBkRuO; z9WTUWnN_DDvUz(2^h}-}oNOKiOWsgPWVJrt__VD>Mbs^t^x~WDdleFxkATU5Y48hB z^HXxyBre29Zt)vSgz0<{4_yO&Yt&XI0?V-qQ;G5*)gN9+Ck2)Y)(!G;JUt92;o)kY zRGiyEO$t!8X@R&JlE8-it9TndU==o12bpor$x6`@?;Ac8plT6 z%Z{LFTgq~)zZ8)pHAZN-aWhnM2yCvn!khW~jQIlMr80^ibC;J%D@H10RrcF!=Ux&f zRzCW=iaD8YI7sz7`gVG7x~D(Y;2Lz}x-0B3XrFw82DnZ&kRBU0uomh%ZEc%=i+RMN zdvMCQ)61ZDynC2>dtJot?c9MgigZ*js=sVz7oMYg?4Nf9*@;1Q^t-^ZRj@5DnQfIy_qWcBvA4KJoej&BEu z=&JYm^vm+f^850EZ{59bWbU(!L9TVpWK15*ND#WFV#4dLyRAnXTN#60?+4ny!85dUcg##SIU-=d zjjYS5w__aQZ(P(4F79yZy~+0K)}&H(&N?ZcVuowc0o~PTamXwW$J9~#`V~)3t;KRs zrHPHe7II~ZtzO6SE#9luoaYD{+B@w|f!Mwe61#r`|NTt<;d{2ARjc>Y*nePv|7E;1rlp#}`V-F@XCpzy@iU`|>m1_LZDcdsE{y~MoVM<}5FG;CEPFzXhcu_F0I#Z^dOQxe0w%;c_)}G4s z*C6~>vEL?<=xRZEvY;d!`9bJDny1B6k5;6tJy|c`5<}ty^8&~BTtuVcP0b?fSM zbY-fusi>Pr{`%Y+z0WhEui6sVngo!$RG0Qs zsOan?>Wze#M)O_YYx3b$WZj^yYv?9GUiswhS$Vum<)OA{|8l8r_BbePacMs=R?PA1 zwr#pl^xFE^^Qq5;Cb7A*H#-nJOTASI10;h}IP;`bg{u%fS( zHQQ^^k;uNd$?%>KMObGCj>!RJf4gXgqyOvom(}#M&jTO5!SUEE;3`Lr=Bfy2(3qQ7 zmppy@ZTSgTj1#%~+$a6Z?6TAfw+&``RBIUL)I|0->nBuW?7lU1!?A)mcx}z&JWQ-y zJy$8{8ooQrreia~?~-fxI&``!GpPn`VN6Px5(i^_!A8E-?bE^(@9ROx$2J*QU6`Yu zeI8na-U$yNQj^o|(i@MjJ9Kk*+#%h++~Xe?|7uMGGkv+ER$X1IPvms1W8qWvB5YW5 z6^JU~SEDW%j*bfT-J$G>F1ga{k}f20vcNEpRk)l;nAaCOHvTeD#|OBdSo<~w135*A zX!JGt$00oqrX0!ScQQ!~XEl}G5AUQNhNKQUhV72*Cb@)?-FMgXQ(Knuy3#&Lb-aE` zm=++vsfc1iSK5`+TR|r~_!l)jHHTld#}mvP;TJy46Vh0Zj>e4E-j}!L0ACgQfPebE zYb|`LqoQxb-NkleU}AZDbE?6H#b$xeJ|NkQ@=zI1HkRxO_CmX`V~ z@};JD#KMGxM7|J-Hrg}x9(2ojh@hja7~(-B8p0(Mnpbd(G*a0__WZ`j35CF}yK7q^ zK0AD;1480$MTc;wEt`g^=VM={aH`5yRvQj?hlCbo*c2a@yXaT1ULZEKv@pxC_KIH9 z#21+$(i@hMI75d#ouv<{=da}o88s;4vkh~gWcKPUR%b9W2#Bx%?ogNKpxo9q)*a8F z{H@*otRM52tFj4bC;}E4ALu`uNdTt@L>Mv!iHyS+4=kUl!<21Bll<8WGo0j%i@F%b zGYekpmFr7=OhRW_OBYBfGY&*9lb|iO@0%KWtbWVJlMiE=NEO*?3LSW*(Y;K%3{QpC z@ZJy-_=sjhL-NXeZaAoFif(TRH>{5D?pK7N>ysBbnUXW83Jz80F zgsP)a$S}aiqU!r#@zdkf6(dLAo5Hu~{h|2Hca*xPfu|myaZ{|1JtJ#RuH$j=XJx%s z^wspBJLOo6B=yC~l6k#K+Xz4OsuDiFrC3+wAf(Q#;(Z>X3*)h$Y$@z)fa*A!8#i&P zGvKv_#oZ{XB&c(pqSAHdc3R@K%zTNUGCSJaw=1CORMw_&i<+r(%1!|@B z1>cQn;@1>a3&|uEM*mWD5xzQgFkT4B!~TAwXWL1c%*PZ5-I@vQ*jS4dS~vP ztk)G;Ri&{$7i;Qyt7r<#kmisrYT(-8ILC&nZz3hV@EAVJDyDN+uqJ~Wv>xCgcuxcK zxDS4EE8DWLCx2y``5D~k`-UJ3upu*dq@CRbLcLlA_-L~9axd$q6P0pGisaNoYlTR< z?r*z`)^KF>Eb==ajZPkoU8pTZ)l7|bbKY#5*QiiACNa1H-K!U^k-*jh-4Y>xN35P^ z9NdZ)S>mHn7a5q!L~qRsY_Vv-`vF6rOq~V~Q?e)fk3|ZaGWT z*4+8)kZp#E+XWtxIJ$-uT28qYc@USf7zj9sEMet6CU#)3B=)b(3Ff#bIFlU3ZkMw7 zbbZ2V7)=K04Askz<3N8;i5(++iK+&fEPkyC^$*h25)vMFk8tH~aR@5@bl_@Z8>F zbi$l>v}X2`n5}u`Gp`5G0uxKjrO;N{QU{w26k42{$O1zDX1T*(wLCrw8o?+i`O11Z zBbH8vHMF9l#@b=IQRM*xVk;~3Pi{u5aMToMMT+-5vccGTVxHp1-+OwOP*P;= zlOAVn7)KvS)Pef=>%snhPjo8<3d=F|vu=e-1pIWS%HCU1?UNxJf9G{F7e!=uTp9W~ za3Lg@raQqnH&Qa18ImPC*((+&fOIuOw$dg94zo~=bB)!YuUC|Pe8#6PUiCEn5_2y3;bJyulzkGJ>S5I1(UMWu?WE4lsKR)2|>w`1JBHwLYDx^^*NCi>lG(?Qt!(NSAf7#n`F%MNr3 zGO_Phs$5?={g7>YGty_C9w!O$1iY;KKQP}CR>R4A&e8_1pr~=Pd6a5a)Mmq%BeH@4H6FAj zmvXw#KrB_eG29Z0mM9A$XkB@oYUMV)C5#z9*7|z?BsXir{sdle1ohZE3P`>%(mxb3 z`Aabru{64WF>0|gPgQ<+XS7UXe`mrgms4lD<>ihK=fR%3J0lr|VlGbA`a_ig`}uG~ zA*I$Siu&LrF}s6foC4E4iJ_e5X_hzY(VCbW?(~J|Y?uu_9YY~T^F(0(F zwLePAWtngFSmsf;O0a*X7%P;OI(69e6VE#GoEP(4g7e%AzPQ49`qEL;3%JybZvp~9 z3W_PH5K zS?8@j#UI%l?l^EQ)dF_miS~lY6r@cU`(-Wcw%Gbj;tVxbic~z6x38>8br;YI3d?%p zbfLB%wfNudR)u%5+N_aQ2sy)yG`)r!vOB*S%x-H|4YO3tJlw2;c+4!%c~4J>%8_kN z_{B!)F=y)9ot$)c4yEf&gwNa)d5e1ciLU=KjGAkNdh+OCg0UR`BD3?PNBPM#vZ^4T zZ{DjBMKt#EK%+AfElD$@M_&uhju@~hIKKjVf zpfS;nWD(b6itvB2zoEl-x{!BFypDbpe?c0fKIz1zKRItf>K$q%)tx8i!K9uohzC5< z7kapYmi;0JZ2SC-MqBV~HtY|m0ji1xdolqXpm9375Rr-*2Dm>F($U?s>O(Ic7ePf# z5Lh`HoXuxUY*o1Q@Wq^xb~Wo>HKT08*L*f(4tz;35<|;hgKQ>|FJKv#8nppjcjQ)6 z8ET&TK{vo!?C{%zd83^A?XuK*r^Ur-;!?jFd@ok%6*Y30lxLg)f4?B=Rrh`voS=C& z#eM7Aq$be3ID0*1xt@(n!f|i&=L9<$GW*;Z^wir(foBo5-pz9^9MtDsFM8i6%n;4B zof#FuL{B&zJ9tx{qwOw}HBosCuQ}n7ZLh2HcAr=riV`)tbMn=oXt@`-UzKGIZC6j$ z3NCimoGI|!{5BLK3vtSJKYc1Hj(~ZPGM&+0@r@IeBaSc;%2D zt|Sxr>N=`raHCkB5creBmtS<0Pt7&H)&WLw<#6#_-RFeG%M|ZmZlRMM^6T-^>n=97!!Zn;g0&l zvHI=EjcdaTn-3%jpOwVr(Qz*ryr+MJt?g3pmTQT;A<%~lMaK+?l+4x^@0o^PQ7ZUY zRVnJaxW66Sds?+D7+qbh+;!R(eT93)oamdI!>A3f?u^df;?!$G!1n*wyh%M%5aKyw; zgEFpMFG{F!eQM+#J;Zgp40WedLwnq*Lwlgvrxk-pd(IYak$^(CbpPF&>p_XCYnN( z_ls}kS3;WHLUie z<4QKyQ|v05Yxh1TG#3>74Jm(H=r_4Ka&*)Du1p+pmjJ@y_+=rq zb6!J7&lOfA+^0T56D&m&I@@1%E&75+*?VZb!n)aA->Be}wm>PpzRc`^HUs!XTuE^^Ziz@_)pUY*m7UI1}{W35mbQ=@rM zNEHwGN?Q{bt+$B`qfg1Aiw3t!0UOENEQ?#~Mk}e&{=A(x#=6zV&*qBL#yn0rg|(~O z-NpO}wh9X#V9&w|tx%_ieDRvtWi5iwr!KRL;&e4O zg)eoQ(rVub$64Ke84bxS8>K_P;s+lBmyZr>vt4ET^7!nH%Wo7ldt-qc)*Gp076V5- zl1?JniXT~GvWZhYwu&mXOxh>DhG*)TPu@+{v)RR zUgq)4K<)Jh(fin3ptda+xD)2iG+r`AyxStV$las2R{x_W zb3KtL+SdFC{At62D~}MV1WYz#>>)yeCsKG_wt`=qLM(*%PIu9Kp6e8mZXvM35TCL{ z&#j$9&+SW0Bj1CJhsK10uO>5K_d+HLqI(K5Lo!WphFO__IZ#$U@4; z`U}Vsjr>B8mpa?-^@g3$+8&=Bs3$TMU6)g{8|rji9>aInkPHW%X_;23{`M9d;n@?4 z{H6|qPcxIML>!9b8NfkdVhyLjwgg?{*#YpPdMIFHrOW_gqx-Rwn4zo`@L^O}(fu|g}M%Wtzvk5IMNmd~ZBgQdEV@Dgl z%TEh;qBf_L#jMwQb5PQ-`cpQ~b(2nRyc{*g)INk6X++1|$Oy4RmlkWUaBW4o97R%x zQ6LUWO_{htWG}P^uKF2xhPJxewKG#CM+)zj9Jo4blZq917&Nl8QZv{I3$P2el)uv}) z9AZyaT@`Kj6NO8`gawjvsT1Bkb4|I%Nw;+KLhjA2EllPLYmJ`;-rIwr)o*}fIEYgN z(KX464Ltf6S%-3_1Ag~>$kg#A&_y_CC@#!7Tes%i?#i?*j$(=~@tHAB8z?R$Azgg^ zkb6xi#T?&$a)_+#)w1}Efc0bs_%KZOJ3K7~xCwIB91PT!K)NAIc}q+3 zkcy@fHWRcD+&$Ov2Nk_V39CbOtcaKE`l^(6{hmx?CIl6ogz#hfTc#q0-Aoi}^F-F4 zGxdB4j~twaJpaIQosu12!&?J+6t6#!f?6+M=~njS>lXBDcn-WR5ehHq%TA_lm7S~9 za1;UOQuN}$*_cvjSkf|ok^G*XcVk5*>jh9?ep;C(kYbZ3QS8sk4S&IE!fduo;Xte7 zewAKIDCqwX_TABNb#L3!C5VXV2_ZrB=$%9f!VtZV-h1yu61_+CHiGDk7G(w_qD32J zFwu!_Fww&(-|;-}yVm<#-}|l4n!ijr`<%1S-uHdo*LB^G)761e=+53#v~X@~ymux~ z%6?%=$h!TX#|gYV1Gmz78?bB|vu-cx< zTnIq6t%i?hGYil;3_t6jTwxP8V*b#NitJYJbFsC?M}gERWNq z!T3olb1zi;`Ybq(#&23PRVm)ipliRbjFHE#f4C`?kVYqI0sr%H_qzRCklhd zP7$ISG7#aJRl-T=G&*Dj&u1?msO|EVq9#(QtTc3gIz&aHdh&J&FG z0t>60?mdX>8dTJBW0-g?%R=y;w;Q2=KcegkxR}*+q#>|1$hywC;o$kYVzbX~bDZDP zo;LAq4%|HsX|WIPIS!o7pX2s+GIY28bWNwwC`jbo*V!u(Da+ohxPE>3^+1W=Y6wyD zMH64Wmfn!r62W&yqH0eN2f&Say%To*aH8Y^6Tm6n_uCw^%dD}C2DT{$5SsH*$v1`# z=(jb$6+Z3J7vr-_JSrQ+l$896;C}; z`zx?!3&4zrf`A^A;c7s9bg_DWPrqY?-__c8`A5`Ck0xLX6|%-09j0jFvipf!{Xc9q zx1I7e*N)GO0;QVf#yY>MnN1xt{#@{sQ4r!vN4QWw*OTjOQR@@<1-0Frd>rgmp3P&% zaqaQr!rVyFHCzy7a%IV7+5cif-Ua6 z>2-ky1_gTrkU9oZ zgAn3uD@#K=T$0cposUajlDSkM`%S11uYx$*KF?w_!ckk?abIXo|D4nS=oBL+*vsE; zqc?{2{dhC;tibQtC|{PuEf9wCdP3n6fXeOw=&ew5%Van~zik-{oH%hCa}0(L@m-Gy zTl0&rYkTc&w)rA#Qo(F>M$D|?b}%c`i(a zCuf&CN^-K1qpR=SWOhbR&%quZJv3eG(P8xnt^v-tza8c zd^6L)pX^r-o#bve+u(3R0fK10&3|dA?U(pXDHW(s7ySVQNc7%sCT6|#GV!W^lr8Vo zp7C1E+D^uma=iYjvTAxbarI0(%&x3Ijah(EZ;DS#eM_B)@`k&UkB3`pz}Lp31P)DQ zQt8&EWT(eB3GUebJ^OXkmK*4H`Ga)cm(2IDD8E#X&Cqc+pNf6}rosh2$-$0joyq^D zuLJ4}{%4ctn3gN@D4-aUBiE3mz+9J8&8{Pov?*XJGunz9&q{nHFAe8TU&!RU4@fkL z0TU0E;AW}j+9#$~X~MYVzPClTazlMbf9v&BiZouV zW=&B$EFAoqncYae?Va<`RJ+e=LkVGmc}a{C-Id6nVk~{J-+S^wMKg!kd-kRIoJSJW3CmA(^|#<0=F~ErR2*d@v4D(eKs+Ar z=jHGB_eWG5ydHo9;q{!fQm;6ObLeJ+WE%ha#`8ApIl75|2S9Z{66}IbHt^WH9B1=( z`?H?fIIBK6C&22q{Y`PN7?r+UyUga+)r+%!7$x`D?rU=zg`if5m)&n&Xb^lbeh$Fzvx z2FJX77{ystwJ?00;JpP$X0(%!4zM?G7rSQ>IY_demR|-*0)-6DX2dw&J+H>|Owi@t z7~>UHK4gS{uI(Jxl}UBmp^hI|Uya>_5b0paQrxGIV1u+F;+`U|`Cr~Fo4 z@a<@HCjg2o)m`et8L1uG03|W{i;kSBHV?+-Ab;~C@pCfM?h2r=3@raoujyR&wr>Yl z4Nj;Td^__5CbM}gkZ=VAE%ko5d<6gwCky6f$K(6$TbmQus^eH-Cy0+%l;HEXGk10O z#c)g_aaF2ZvnO37j`?r=d+_(XaPUdBgkI_6y zgAt6V%iXVfh1RGpluR>)X*pZ}2PZ?9n;jqpK|y>=rv!f|Z_gM^a8GBlF!kyI^!zuf zSkVz4fX>+cJEK!)ur(;3HHBttD&2&~aru5=9t>>rJZ|36#3EmutiO}SLeiqO{#q&- zFMr5vX6bm5m3gdNJ3!ph4i>*&@#*$Zi$8}e1iHCn;E$+&V%jyjs};=BSPO4^cD`k6 z|E0V-ao>LDW`*2Xw1Ry=WkW%EKpW!lRH3Qy`S;DYR!r8RQf>P!(h__|1Deu*M+y{1 zY?Gxhg;Q7MnYoIg!ZAa=o+M}B&?Rg zFPR{1m+$Plt9V;E04tRMMON@jL;P`)OYTM%^-Q|qEQP6(32G*A!XrO;cX6v`3IiXn z#9i!_ixtyOo)wHyZeq;=!Y&4aI{TCbPR9n9(3SG}!q z2a?*>i-?fQd)0God(Oc=RSHtCFZZSKbvr67Id93(fyc8x(U_YejVg5-dE5_MTU!|* z2V|{3;+Gs99W4?3V*;=a(PIi1@1HSAYp5I%kdt%A-z>FDXE&#)*9s@KogZ6%`A-b= z=+CKpf|ymFTC~@3IB9c0mZy4O zyPzD7M+3WO^Rc~C8hb@(xT=X~-Te7V8d9ROAn_{?5R2^~k$gUDCo?%~zwnG+2}jP- z$&E1-R^y z5F2m<3~2z>e5%3C(cA);D;g{a}q zjbrYY-9l6t>>J(X_Wpw25@%Z2cCts|)A@RHK#2jTC{E^>xR?d-L#9o*@uvtfgjMHf zx1qxZj{4RnK}@|Z`zpS+DMS2^B!I;7+lw_AqMjg4lRW5^xhno!(nJzMa*? zLxA>pZ!z`u>aUyq@y2=OWVHWjRgP%hl`!jmBQmOe^Zf*?i6k+7@_Lcf?&?N6 z`q`V#K({q;13-cRC?+k~)ALmvGHJ7a=6rnchxN|ZoizV9__E;nbd%;w(nbJJq7fWw z2`=?%X%qVjfCj#QvZf7{#SssIf9Cm^o1U)L0gNADqHl|f>g6<5Ck6x2><@ocbbS=I z7$7g)1-9fYw_t`L!0TVRs|$sJV^P>WYM@5u(k-H1QP?Kis|+YeJbx9lSrbuwgdK zSBBX1ODu5jR8LJ?87o^{DuYw&K!rse#_q|JCO z7gdn2;7FEnmT}N&R|uHs3DVbmVXVB7S)vD=V~~kF9AMjSijg|M2!oBxO-^e9+&i@v zzp`NWck2dTr|@R9hYysY)i4tr8(AY+6wNy!E;TGJRb3?tL{`(f@9U+S_m=zbL@dma z+Sm|?i~$rfY72l7?BMroL6<3N-LUO)@z+XHW?q$qNj7}n(aV4GW!x@D67HhCM<=l7 zg@)NW!sMkLv^F>&Ap9`F2)}^`V4XS+L&N?ojXpgwU`Lvp z^K#*0MuVOKZ=duULRjw*Vc|1^9Qw5kKO8Eg@3qpCZ@4_2H7NH@UGT6KfgDlJ{anrroc{p9a9&-h!&(5jxb zoXHE=h5#R-o#xn@+BtgaIkamu?Zx3NINh~3mTwJ=e#{%Jz`32Dr=j-7)-NnW`z4e zb@4NriNO+`#o3K8hh)^=d|B$Vn=T^_8nfm|J?^yH)+eYteh$pO1uC5f`w$u?oFBCu zBvMW-nl}|ZCqUa0UW?UR$Tm6eHLUS$$>x~5Xm;T^**gm4zL=mJ(c0QffX$y`s~TBT zp+nT-e&>#ChD|5BCfeeT{ylfDo}tWW@Z~vaM)Lf{2~}a`bqmgsq?WTKY-S$FSULcQ zX*6~cW-0gC^q#yp;z7QsSfjQ864Dd~6Ab8l6W8jLep=afZtdZg13XpFbc5F_6`90# zCo&HG@6sJh5yEz;+D>EtuHaHM+)-*sh_{2=(qggCwni9l>K4f4Vpni>m=%_Dx>MCQ z)okMhvWPutz;9n3WLU4`E=G>2E!3pj+JO34&KtBq)oGVKcY1%OmGxkg zf#GbmA$jY^an*s^eJ4)X`~~U!j#M4~N?(5NKIl3p9OTM8lH}fZ6xVja*OoeKyiV7K zSG}S`?-uf0p1TC%x)zk0&H1};qlg25;hF^2)Kqs@_?1d`*f+@J&nm0jpu;~iJ!zVd3;^jn+3D z&c&!rItJTErcZv;b7toN*K|py`kZ(UmqTp|l;xeb2F0sS15cI>DfsOVv)4`L^~(S} zLw`=ROtQHJ(ATAE0FOH60^(rju{_!YcsdPC2}<>H>j+VKtG2Z81_s6QHVD-{+dn+A z9MP)SASky7Rux_A(zug)0J@>EsPX*4T`4R)J=hiJ4tu2Z2G4S*@kYgfYl8JU6niUB zO0Uts*Bf;Xt&u{(56;8xG^1YtC565d4Pb`-S=HM9z+p`k;F0LU<+QBR2_|t3t{!-g)@5K@)oIuaWU&JDP-}9*fokR&Hfm}KhHlgrNbENIH}kfE;XJxi z*w3GnNxB}*0)sGmk>cMiTjck$kPa?pW*Ejb=SN`S&SXAnk%>M6NTJ)AIoIILkK+t4*&jI);ir zca@&N8YEB})z1A+0A9yBCsE%D0km%kdhf#k=ML893*D!czhZ=CfUP!&uWeqmVyuM~P^poFdj7dg(Uo0Z-Flo!gnyYd1idGNz|Lu# z^Rv+*B<0Im+4UP%-FlbH4}iV!tM0l1o8iDt-JVj1(=wl z_ruuSNr1TvsE|3yaZhkV#K(&BCP4__cgjFON!Ka>qw&97UVy>kfzaSDL501V-uE?s z4zx0W7ewu7`G0Y6aD!lE%6koTa|>o@=+XmIF3L1Gg~2$N#l@{sAC%LbK_Ch4SEGvW zW|=a1@8$2fckt`0^8NeOD(GW~SX|H4l-Sw~A4P};sN?x(<-4Gz*z+B=AelP?nMEKK zl?Q0s%mxHf==?5)X&h;8lmBY1@@>gfJGNkvwX=aJbkei2)AS;Eb!{X;`Hj};V6R#m znX=6%89yQkIk08TuMlwusagA4G-D4922z|SbtO_1?RO)sNk~X;!Rh8cXOjVs3x zWy1~5tA}WTmjuA}VN0WjDJ0-3E%q{_u#18owd8t2++3R)hA9x26vP$ESP+{3d{D}u)pfDDkX&5{zPc=B9WFfPfd`Th3B%MAsu;MK<9BfrD>1Sxm`0QQV>Eddc$9lYAOkK);` zqIF3RxAyAJV5~7M=DKBwQ7)J!*g^wckG&kh)9qtrmW~1SvYFxDxuNvs(G;!~c;@EL zI})gJ2htkuC0aWEIjDA~^`1l?G9XL6qn;Q8G#=8+ah%|8SBAJIK;IiW`r2j?G!dw{ zoSXv)@aD*QG*I3oht#QykE33H@-MJ)^>RTc*n^m1ec97}73+r|WkBWO`evzgtIY>N z_tVP34UUz*<(Q1-8Mkcnni7!`PcX)7#WJ=A27_soe&rm>R($R_t%DjC0Cl`fPP)s; zm!SgJsG*y=H3GTrxqXN6+XJqK6UZ_i>d@>H6jWeS;j(_FXI(uVE#ENjVjc@`Fl5ti zQ1hYNcM!ff+Xpl$UL?oFZL!LMn5;Hw{=@BpDTC1IUYT>ruy5tB%VrF_7FUAzGG}fC zT&kb5&cn#Ri&ULdTSIG)dZgQS<~1G~q3rh1zQd%AiDY(D z5C9I{&v{b18de47K>2M~r@n=GF7dQU_?@c^MIiy!xABfP8~_L`S>;w+S36;%M&u3@_<9~+j>N5WQfzb3^hg}o%)$^ACa(~|La8#UX z@bQ86_icPL?D1%@*URv`%IjW5Y6E4h-)Z(tuYFgq1|xoJlVWD3=E6X5I6& zP$}Lyk${2~(2ds9)IXF|0%5kynHy6pr}^D3b%o&%+=p7%N0&~dF1TUBRJr>bWqn=M{ki&YFbn4CRWC>QQMicd8RLVSXp zkOTM>X;&2Cm2r=N-PWF**A}KjZRhbg?{kHY?wP6XY$iS8rW-lY{D+52A>h`-$?-$| zGFHc(oqgHHK{6n|{EqBuez@e4y^{q5*P!`8+OHuu7xezANZ`GXI{JAcj3on(2A?@T z_{Xs7!Nk^FjoGxon{}Bt13~6Jsmym z^Y?Cb^X!rs;z)h#DVpOcrv2hkiTO|_eN5NI&YCoZ(sYWVK=nj2RQ421ZY>X z(dc!=4uV?}^!%Zp!1?mX0r{rFA*q6A%v`Aqxe&W#o3Sp+=$^*)T8^X|PL4#y;iQZr zw$OK~Iur>#5bb=Myu1Ci$#s0hvbLKm$PyAhdv^tPwPg2Mt6L0QHwjGJ0M6KZi03v0 zl-NZvvV?>*XerR==ra<3;me9V+JaO#|kW2Bg zJDTi1pBfX~QH;7Ws=7w`%EKN0_$JwYlw_e|BGAODWpZ)vSM#VJlxbMjZLW%9HFgIwcU02uSMvZR@5LW}N>C@reA`jCwt21_x5(P%N$^EmA@{FX$Zi)Ew?49f zBT3Y6?|IH8!oW1~LOm0vdW*h3U!6lnSPq0%L0ihp0evh8BE~PSb56TS3>9#+Qim_z zEIFucXwWJB)p@g+MU9)Ai@dQVJTI4;j_wIPi*+p$DJ3Z>c^H_PzB=nO5BJ>o>@@9} z-JCIv*gv2@FQC*-TfZwY1aL-?3Bp`hSD!}U2v5IHVaBYQxBTdz#3-WrDCF-u^iJ;W z-2=z`8C&iR>yihs`@d1-2YtTKHT=cQnFKE=PtOya22FTi?q{*mK34E4YufusoI`Z} zNVuxn)tyve|9)LWP5>06U_Ks<&iR<_2E-i&PCx}&a(495jV^(9QH#FbGQda^M&10K zhCh_B)`-j${&9cPJ;g#Z)O28ZR3qX2f|NzPT+)pz+gF8o)1mLu=Oef~*-ho;96v1! z@~e2PZ)NZ;Sk9_zipC{#I@`L*iho}@>b}mI#v7bnvrEuF`{%Ive&*vV>rxR)#~x#S zV|7&_35k}P8g=%R_1@8p15FzdAQCj!K!h)BMJf5&-7a#!eTz~9@aOftiFJkzZ70Z&gxIhG7R z!fl!A%MUV5SJplI*?OBM1uCY0gc^C363j1(A ztRvQ()TiaG4CGCixC_*VIj>g))(q!(mW6Q9@~RZ*>1eU1sz_yJvZs~Ez1FQVLIzx3 z<9*TdGA?FqD6M}?#c`TDrSEu0`f1U|_O>7>37TL=ePYfCV1wKD(gvO>(8@C*ZB6@4jm{z#QJV z>u)rV*6!ac#O3|s2hQ0nocDj+IWanWvLA_E7C&CbLNDkKle1Yhdu=)2s##|iZNx0f z$?*zzQ!n-PQd@kkxp-Bd;nz2&SrqiCKTa>sxh-q$O4+1;Vts27}`{@^0zE=QU*v-TGY`yUTBd&}6NYh|?`iXk1l zkQL%*hy{%otN~;^Fu#EmlBw<(E;iP$1?6ewcTq;_vlnFr%_kDL#c%egd|5T?LCgn2 zkF!yn0@_1o#`@=K-8P35vriuD?5ZI@+-Rhhc&W0VOs%SRI1^Wu7__gyuyK#UI8wA6 z#g&heOY}zex=~Hs~^`4WB z;3EdM)UIE3)AJ9>6}!3PNlmCPW&Oi&kV7_I647K0D=fd_gxi7+w!A z{Hrcgee=2ra3~9MQ!W@c7m90OaEKgjgz&8~XE%<;2tbFN{pbbtb$wjCJ#wg*c|sKn zn z=n=yc84BQ}Jhk4hoFK9OEAC?E4Em zoNw|dUoh;18#4E$@vCZ38nn)yG+K2g)wB7t*#!Fl?@z;Tr9ZxT`;)rYJ}fKx$-~nd zBeNg!v8;`%o^Wx!wrRNY)qDFsqnFlYL!2|e-DG3zqxb7snic||zN4_2psP>5K_b|$ zSwxQ!9Jl=FQDp3V7;(GQ-zqY>l$p2-(A0BtZsfIIBN&?#G9~|>*acr6*d6x?2&Y`1 z0J-ld!yUp|H9FQ1YV2*;)46%I;07Ofd{xEafB+-dgk71^o%d>iX8)-2!Dgd#AR7(&fx{yhmYBfxpfzW87$o&S`c)`8zk=n6dKkb(3{UBgN5p_NHeUYy3a^W^|IW#Q z0PkSE@ci&-G(GLKm&;sB4$r&7bL8c<=y@d|Cvq`rNz~a(*fuxW@+Pa|t>aQMh7t zu+YZ2qhjRQ`Sy$eREcs=lpXQ5(A`_V=33$L!dyXpy`Xs}>0AJ&?g1D$++%ace;-qLm(sCizH}t% zn$PU!>XeRD3=8p9C@hxH1z#uyrp}s5=4ParQ+{b$KhuZs*&yFT$sV__>|e$N&$I5#UlH2? zPS%ss7Z5cRRe#@Ih2QEr8f~4+R4pGDaqLF}dKoowQEZ^Vt_LKRL zUk{1imLFVCT~6o9GM)1$zLWyKA^JL6vN-0oi9T0ae_!KKe$5M79>DbEzi;xRpgBX@Ou?R3k#InGR*l!n3Q;bmSwK}%V zjKhijiQ2<#55CU?X1Gl+DHMCCzn!%8K*KBP24P~gebQelj$v3phK!q^ZDiJpp|Fe* zT%Vsf$fhXPbT?#k?~G8)R1Hpo{eI=LW^I6a4NT!KB22xZXCzzgcK_;hialykm56Kl zG1nBy9JRtKrumhyk^vj3k(L$7*Xl|Cl0{caK7^9=f1XyBkp$5O?;JN;91T8$t` zvqc_~*ot1`Lsm_blt9gyfxcN&WuyNaKB zM^h6UyuUg`)9r?mO^dIrqa2%{2Rh2wL#8L)k3QV2gZ6ha*>Ec6yzWgWTaM^7uX&mT zmh{-z%uqfM2nmY=BtCuma2fpIdf`)|R^*?T8_A>%WEVWn^IeIA05N<)F;Ra0c=@e< zj$*a6^{)H-SWo7*lKz%T?x4pbo%TwtGas7jb!sKGYu4sU^gUaDqw@Qy{KHY6aU4|Y zo_#*LRQ8ulBG?#x&Q~(;Hu~Xkc(EFEI0=+3A^P&=pA(y0Hk-c+0I^jnSC{1(kjytY z;ob@$bQ^8hUG5yaB6zAacX+l~RQ?(>y<|Ly<6}c*xvm6y>tfTPYalcm~ z8KG<7jf%I0qbl?7nR0n_y{OkaI%FFPnnLKM-F`R(atnFpcu4W`z8=UcZZ3cKVpw=^ z+=eoda6IuH-+&ySeC`*o*_RSFxFyn4L!pzKA3V~GJox4jMTri|kTg`Ripf);+n5>O zBL^`r>8D4QA5&#~V?|%P$0)CgLp`xoaJ>5+cirRXx~SnajoU`t7BF0M8G$n2suHlj z232SG2Vmq}QGf+*uAtt|(d%Mf(5Y0;tKeqI7p&7#kFQ(D+!x5OG^#gRY-&&ImsAs# zWr461y7TS$$MP2MT1s?^3jL(F>)?v>%#u3N&N%JezkTvW=NZ<_cG>T9V})-ByQcIx zIM>Jq0k#ABiFpOc7z;ka+^XD|FBc=<1G;IwIiz+pB-LThIMA~B;F%e1S4K4kQ^`!1 z6`)lvM!)7hIcUcPz_22o`ivk#SzBUY+l;@m82{XhC#46{^tl!3PCGdmU4CA+mGNJs3V1URku!cH= zl{tNytllu7Wkj8ssfvAUEMtxI*t@5^>Q{XHiG^8~OGe~(&Buk=R2tJ-)4G^HO^oIU zCX=>>SPv=cFVS_D6~gvxtmN6uAW5?=5d({GR|wBf=Af69lV03OoO)}5Yat!7vk=MX zUt=#l^V*It@UQdhd?n~jYi0yMT`BK*TenU}e*RF1_78?SzwFKjM7H;a?lA@IEl;dR znjbQe0WBuri`*iB8AmE}=rK1>>gn)>hF(NIRc5p4x& zHcg&pXf3VI%<$u(Mj!96Ig?yun^fzwGjv$DU;A$IakP>qse8zlz6NxxKF8)Rd<`{t z+?17Ogw}s=U=72v<4|7UT;og#-+nT*!Vu%^p2}sJVw2T`A77Fgv2&G1v`X!#wsREL zg7feX`N9*&4l^{A{HS7(uYj$zD(e8~hR_%N6}d*{^;mRCqpUCUZECOOx}qu}W8qgU z1t9ujqhN-JrKl`5S#6gPDDSPQewqvY!VKmB?5HNAnJASF!@C7nEXN5ra7}&YL%d*) zfS@^@nNPMerZO+mI7HMk#faW5kAYv1FaCs{+@AWJ@>bq&LBV3AuzqEYi2uNHhz2jT z@MLyM%xeL8CO?FQhMlc4kQ2r~AR@Rn;m|!fHs%3X`v;rMcl4+|swZrQ%?JPaB&Mlg z0bNV!w>tgZCt3`&c9?JAC^HBxt&RAnMdJ7W4=9%-tBd3V>o!T$8PN~M^?FsRS_k?Q zp>s!jpWV!eN(?fa8;&b#qg$Qz5bF_`g{`+B1pLL(qVc#Kp;A9)tUldG-1IZ?dZ>Z32%(n+N z>Zeq0r!opdqCh`7*X?Knn3HBzFaAI*LgaSG*!@LDch(V)qJ;KM^O64wH~$4~{_X9s z?&wq||6($XXsyuRb+ld>_Anu|d`M>=85EbU6dW8Zlr?C{rxi={h0;v4F-4^al*CTQ z*;Jh#!Qz!{H!vzU#kXF{2_i)0mt_uXyU9X`b=Iu!EhZ+MbLHJ__s?em2ds73MhH>3 z<&ox7W$D}6IshK!<#587%F0S@_OVE~W)dq^T56PfQg~iMd@Ls?HyOXu^CU1B951VF z1E?%`-(WZZw-qh+Un%#z{9@!FY$IReU)s6Jy2f#EUuN^8e5v@8&0>=|^ENaT5wv+c z8EhixPz6<1k)>=p8S2+!Mbjey0IJJ)qrje&QZnwK5Q`|(NJMN45%(yNPN;Xs@D=0#5u#wt z!;h?@O6SaWAwzBSy_uUbC`onAr9il1{b*BO7cnF(JDitAgh5qKPo`QfWCDqu&4^w; z34we3jiAeYnCp*B5W0O8;VwMbSIb0pB}eguc6Vlu(Tn^t{|5wq_1ZnvEBj-?x(7)A zO&O>Z3KS*;TjZ~LrUGdLOOMWrHy$2)<#X!WqWgt2;_-5<{I}44p+GCcfz{@RX1EjQ z^6sT_>zOh)p*;8BF{VDWNXmn4akg@7LHe%Q`r|!_2}1Sz_6#C+K&3#9cF+b{G=2L# zpyRPZ8RFIf&%GLE{e2r3L_2M`5@0a9pYmwXg=8d9?E|s89njoO+uGw)(N5dyI+?lQ z2tLi3E+~>L^}xGmKDD5#x^f!DvzkB+^a~?cF#Ufv3lyjV)f0+J`&?Au)T<~0fkbNl zvi&&2QQ}>$^3dTudG_Yh_4R5PHe9|H|78QQAd#r}04)b_C1%1V*T#y*1Xoi>z5<8% zB6%&<$v@L>3=-fj&fC5)`~Zwk@NiBqg4Wny);eT@STAFEg0?+2nTK}sYN8h1dWwt> z1&BksEb0o4LbUyMFO}&Z8Z+2s-|hAs4?xLm@zC6|Q7M`GTN$LnW8m6;qk?`f{5rwo zNrHZIk}Bzoer58t0WUDqweSZ&1VFmJg1YguX_Oc)NyF?S-EM(_nh)xTr{9X~!rt1U zxks*1KHmMyp2w_`_;Oq!j`*>uTQ3?2?P8yjlXh3$$N&U7@z(Eexl;Fj)Ez!+DR?p9 zXlL-o{`HND=9E{@7$ZDw6b+wgZgvrK<=bJc3~S`N?>q>-M(_=2L1EOm=$GC!`g3)k zh2f82m9>1}{IlYU`SJxkl)Zj8=9XZeyfP1lg(teQ|2fvrjBico60BXcu(~f-j#P$} zCHZXw{`J#wA@~8CfkTSQt_K=@R5bZu-EkIKsLd{O>M)+jlO9w zo0+a1*-BfSSBd@lHr&J6rf-&I+`1HL?*+pOwaOuwK9;T64mNs=6$?>;7(${S|7NUB ziV$53?F~?MQR)(8ma`)BhtujyKOK8pzeW7G2tm-A(=m{NDxqh||8i`KW#_$FYWD%q z!CCaC8qRRRqs@nA$E3&I7#Rj2;#2+8C*|d@~Dl*dEI@>(dsmPou99#NS;0rwQzpJpDf*H2}1{YOA?Uor9;$TVTpi8AZFIF44hf z($g112%Z;Cj!tKjRhOCRN+!BhRtBl1imkrRzXz6o`pza8bL#d5H|=hqC)vKS13z+8 z@5$S@`s^u@5~kVvz7jj1?dkh=>u}v15q8evut5;seXoSo{l! zF=nIV!y8Sa#ktDJEmHH*eF*^3)m&Lv&GzU9p}**2_96aKvAiaNamgCCnaRKp2 z*VV_p=otgF{&Mc~WieNbqW-t4#_IZYssCdEVRgP(OkD_flWuZLlLg$1f&8x>%t-R8 zRabURXr6-hP#!U(Cu0Ct*ODlBNu{hC8t^)g!w1dZRt3HoyX z;82nHHUd-tfLil6hFmY=_AwqSJt=Y{j@Iai&3N`D-u5>GEm-!oG@-bUY~b;qLtjhb zNY0I*Sv8ZKwwnn(>Jqe9soSdvz1{R_(@!jtUz&ERcS5@(23nrH_|7hB+*L5|W$Fg@ zkT4OIRVH`40UXGa={fDy4gX)Jpn#f5mPrA6q=7q(`x*b@DKz(OVX}u}G5X-9109y5 zj-&JDjVNTKl{}|Bmkc0a9v3)?JDZwecd!bdM`6TA6@=1P`LobK&#&yMpvb_PY5j%c zdfoELZ`u)R`;+CzFn%8rN)gFWoZmnaUXq>0B3zxvDulbmThI?618Z9$SNkN#XM8s9 zUE?|%VMH}Y&m2^o2+=G@+U}rTebIQ`*}s`!X9vZXfGyC+}7J} zr6!NVx1G9NNOL-pgua?@^}?Yl1AL69abjQ44y^Ptz&Zc<-Ei$cU_aS>b%O42lHbO% z&X^>n$R-qVp6^Au8>;mNxRpLm-lvM;*oU<7_beiB7g~~ELDJI-pvFK~6wG4s%3ov^ zZH_gq%G+*j3tdqgjmOJRB}DTB*al~F&I5hkTdjZGCn#@Rx&)v#;2V^Sjvd~QP1M`0 z-X%N&^BB6V_vRxeo_y(>M=pbP^@WRK=ztDeh4&;g76L`c%;wr%y54I$Fd>TWtlt8v z4UP7EIUe024Ez~;TtB{b?-`$)v|>||D|%|B;_v=*FSl2fp~w6x#U?$evAiIb$BdA< zg{3t0FYRATy45VJUx=&?(CbFjg)`1LGirZGg1PZ_=udQW-@1aFhMk$&oPVigOk!80 zH@iVWAZs4KZuY|%khYE451`P3G=ja*b?uCVrH$t#&yw+nx85bVbM4s`YDjRO8n8Eg z?lMfG z=(8n$P{Gm1lJn$7+?-n9lU`rZR+@T$5-+^TSQ;c@NA(#gg*(a!j_oy3<8JW6%YU{B ze|gf>D~hjtJN39I=oQh>P=srxR&R}bOb`!*g}C}vzK!rd~lk7CPtPNSRlSLRtwaH##KLaeZK#QC~n|A=im5Ol`Phuw&ZuV zwiSPONiX+bmIn1%q7&XO-2m?USZ*uL)6n!HQDFXy32;T zV=-FGIYstdp}m2i;J1yIr{2F`29?cpfP!xS6aOvofvVZ!Y3s8AF9kXuVEj2#7W(Mf``2ld!)lzAXw-Jjc zR%<38Fu3tAuKRC(|34Fj_p4@~#0g%}rKidVZvGP5Emc4w7w}rh!@4uGizZQj&hW6?-yg5lk5#=$T{d~Tu4T?I`WnSa|3UXvxAAR8ME-T2vk zKW8}g6Zrc5nA4T~=cp3G>Uh@z7wlbx*B$K$2AIMgqGV<@=d8R#tIiIWPa0sD8Nk<1 zo$|3h_!~o7$&w%Qlp1=q(=8PL2@_0GIlKDrRCE3QC-MQo7szlIfveoV9aaAqv|?C- z*d1v1DA&*5|BLXIEN!JKpuYzu>eVv}{N;eoBmWT8Wzzp05ceK&3LR_xwff7sGJK8C zme|%Vr$t}vtLTO;Lxl4khB*X>Nbm2ms5)sO+Jy%WxI-RE?B zFCANZ>r#-kVt31ylG*a-n*tTtm4vOfsiB_=bSp?hm7dyD0hDffA2^6g)`oO#z>?d;`S-nF;)G+I?Y z)79<2u8NtCD|cNEfBTm$*DmeK%FWT;_kR0F4Q}B-Tg~Ua zn-DAvxhx*y5EK{UNoL2@fcHO4;ru=!UV6da;|bmSxZm<`h&jLbd(!cD51j9QnsT$c z|H-1Mz$+v(k1tC~&(*bX){hdFiskSQbUcxNd)D?Ze=ZzL;`I8mYir5k)|_MRTi*!r zhkN&RKimAg{m$LoJyR4+Qm#g|w0~K2G%7}zZDaECzj`to&(2xEns2ql?ut75i!E=j z9lPB#K~Y3jQB(Waiu}eyIiYU4cME0a1m2cRNCb5vx2V5M+40t96X?J%Ab^B8q!NMT zRxBx)gQaofGl7o+ZHIO(LPy^5ixX{eo)m#R_wOHNO9NI9l9)=d-z$0)^*d zuk&tx)^7fB`y!SA?f#|-NByI!o_(}gUuvA6JW>AOO4oLuXDjb4T&rEKY>|G1canbW zb=6H5%8M#DCJQD!6cc;E!7V9ORXORkGpO-%P0m~2_xh2<#?2c zmrS^j^jm|&%AhtI&J2el0SSKx>lY`U-fEms_dVhupKaLjeDB-MpLQo2?c`SMD0!t= zzqRUVB{%<~X?evK`xwJkcgJoq49iG9*fs6koZ@@Cykv9tn91DE&Qj0c@;GwOipk76 zPvsU))0?SgvT75TXd6qFQzoE3k*m1kz*4WoVTjih2 zavgsqke%%O_DS-Q=^^(DlulX$54&77bF$~jtClZbW?Ag{xlKgtukC?<=dw*1r%m~^ zV&1buf7XRvziPE)HtWIz3!}Gxi+eNGbw1zAcXn&GJJ^IIiuqTSFt{C0e|6WlPS1%a zBao%=_4>~XkDQfucnfapK}!@A58%wmar-xPx<$|0 zyd$~$>X!1&C7<-HS5@0Qam&th`g}Ng&x)nlbrtFBcBrcf*K5z-_$BrAET!0X_drhd zJ7=taK5=+&v?R$sDXVD0ruFR$Dy_VzBnxpA+MY*+V!bCUVVy~__rpM6#lch%zg+!$-%U55J@ z849vqIpAz(X2@Ol<&FlmpC2&bYz`2YcCZw#$i+W#k%b(KC>e`@1WKI^sT8pkg#lmx a%QMW7&2}|%d~_U?r#)T$T-G@yGywpjKp!{& literal 41444 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 SM#6tdoOg9i?o{4(diGy-2H@@h From 17e8b302bc9babc9341a0af4731d54ab757c838e Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Tue, 22 Apr 2014 19:14:52 +0400 Subject: [PATCH 04/86] ctrl+delete/ctrl+backspace enhancements IDEA-100906 Ruby-Editor: CTRL+BACKSPACE Could Not Delete A String --- .../editor/actions/BackspaceAction.java | 16 ++++++++------ .../editor/actions/DeleteToWordEndAction.java | 21 ++++++++++++------- .../actions/DeleteToWordStartAction.java | 8 ++++--- .../EditorDeleteToWordEnd-after.txt | 4 ++-- ...eteToWordEndInDifferentHumpsMode-after.txt | 4 ++-- .../EditorDeleteToWordStart-after.txt | 4 ++-- ...eToWordStartInDifferentHumpsMode-after.txt | 4 ++-- 7 files changed, 36 insertions(+), 25 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java index ad5d0c2fb9b2..5a378d4981c0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java @@ -78,12 +78,7 @@ public class BackspaceAction extends EditorAction { private static void doBackSpaceAtCaret(@NotNull Editor editor) { if(editor.getSelectionModel().hasSelection()) { - int newOffset = editor.getSelectionModel().getSelectionStart(); - if (EditorActionUtil.canEditAtOffset(editor, newOffset)) { - editor.getCaretModel().moveToOffset(newOffset); - editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); - EditorModificationUtil.deleteSelectedText(editor); - } + doBackspaceAction(editor); return; } @@ -131,4 +126,13 @@ public class BackspaceAction extends EditorAction { } } } + + static void doBackspaceAction(@NotNull Editor editor) { + int newOffset = editor.getSelectionModel().getSelectionStart(); + if (EditorActionUtil.canEditAtOffset(editor, newOffset)) { + editor.getCaretModel().moveToOffset(newOffset); + editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + EditorModificationUtil.deleteSelectedText(editor); + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordEndAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordEndAction.java index c261c6c761ae..5785f01feb33 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordEndAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordEndAction.java @@ -14,23 +14,22 @@ * limitations under the License. */ -/* - * Created by IntelliJ IDEA. - * User: max - * Date: May 14, 2002 - * Time: 7:18:30 PM - * To change template for new class use - * Code Style | Class Templates options (Tools | IDE Options). - */ package com.intellij.openapi.editor.actions; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.EditorModificationUtil; import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; import com.intellij.openapi.ide.CopyPasteManager; +/* + * Created by IntelliJ IDEA. + * User: max + * Date: May 14, 2002 + * Time: 7:18:30 PM + */ public class DeleteToWordEndAction extends TextComponentEditorAction { public DeleteToWordEndAction() { super(new Handler(false)); @@ -60,6 +59,12 @@ public class DeleteToWordEndAction extends TextComponentEditorAction { if (myNegateCamelMode) { camelMode = !camelMode; } + + if (editor.getSelectionModel().hasSelection()) { + EditorModificationUtil.deleteSelectedText(editor); + return; + } + deleteToWordEnd(editor, camelMode); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordStartAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordStartAction.java index 76e251631864..b4839abc0266 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordStartAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordStartAction.java @@ -24,9 +24,7 @@ */ package com.intellij.openapi.editor.actions; -import com.intellij.openapi.editor.CaretModel; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.actionSystem.DataContext; @@ -81,6 +79,10 @@ public class DeleteToWordStartAction extends TextComponentEditorAction { @Override public void executeWriteAction(Editor editor, DataContext dataContext) { CommandProcessor.getInstance().setCurrentCommandGroupId(EditorActionUtil.DELETE_COMMAND_GROUP); + if (editor.getSelectionModel().hasSelection()) { + BackspaceAction.doBackspaceAction(editor); + return; + } deleteToWordStart(editor); } diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEnd-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEnd-after.txt index 59aa5d7e5b28..0e8f561530eb 100644 --- a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEnd-after.txt +++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEnd-after.txt @@ -1,2 +1,2 @@ -stextot text -an lyet anot line \ No newline at end of file +stextor text +aner lyet aher line \ No newline at end of file diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEndInDifferentHumpsMode-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEndInDifferentHumpsMode-after.txt index 74c13eafb852..1b3f82a9edf6 100644 --- a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEndInDifferentHumpsMode-after.txt +++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEndInDifferentHumpsMode-after.txt @@ -1,2 +1,2 @@ -AbDabraHumDump HumpDu -YetAnotHumpedWord \ No newline at end of file +AbDabraHumump Hump + \ No newline at end of file diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStart-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStart-after.txt index 7c5d3fcdc330..b66dd51f46f7 100644 --- a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStart-after.txt +++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStart-after.txt @@ -1,3 +1,3 @@ some t -ther t -other lineyet another line \ No newline at end of file +oer tt + lineyet another line \ No newline at end of file diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStartInDifferentHumpsMode-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStartInDifferentHumpsMode-after.txt index eefa20be21eb..33dc0f78161e 100644 --- a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStartInDifferentHumpsMode-after.txt +++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStartInDifferentHumpsMode-after.txt @@ -1,3 +1,3 @@ aCa -pDump Humpmp -YetherHumpedWord \ No newline at end of file +Humump Hump + \ No newline at end of file From f9d87042d5d17dff925492a8045d87bf00af16de Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Tue, 22 Apr 2014 19:18:30 +0400 Subject: [PATCH 05/86] PY-1194 Provide completion and navigation for url tag in django template PY-3591 Support {% url %} tag arguments completion Only PSI tree is created --- .../src/com/jetbrains/python/psi/PyUtil.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java index 7ea85fbea186..22eaea276e3d 100644 --- a/python/src/com/jetbrains/python/psi/PyUtil.java +++ b/python/src/com/jetbrains/python/psi/PyUtil.java @@ -81,6 +81,7 @@ import java.awt.*; import java.io.File; import java.io.FileFilter; import java.io.IOException; +import java.lang.reflect.Array; import java.util.*; import java.util.List; @@ -88,6 +89,9 @@ import static com.jetbrains.python.psi.PyFunction.Modifier.CLASSMETHOD; import static com.jetbrains.python.psi.PyFunction.Modifier.STATICMETHOD; public class PyUtil { + + private static final Object[] EMPTY_OBJECTS = new Object[0]; + private PyUtil() { } @@ -827,6 +831,21 @@ public class PyUtil { } + /** + * Returns empty array if null is provided. Returns provided array otherwise. + * @param expression array expression + * @param array type + * @return provided array or empty array if parameter is null + */ + @SuppressWarnings("unchecked") + @NotNull + public static T[] notNullArray(@Nullable final T[] expression) { + if (expression != null) { + return expression; + } + return (T[]) EMPTY_OBJECTS; + } + public static class KnownDecoratorProviderHolder { public static PyKnownDecoratorProvider[] KNOWN_DECORATOR_PROVIDERS = Extensions.getExtensions(PyKnownDecoratorProvider.EP_NAME); From 339dd236a70f607be428e0019a49f166259d9518 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Tue, 22 Apr 2014 19:34:16 +0400 Subject: [PATCH 06/86] beforeShown() & preselect laf-default editor scheme 2 --- .../ide/customize/CustomizeIDEWizardDialog.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java index be3519eedff3..986c533bcb75 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java @@ -54,7 +54,8 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis myNavigationLabel.setEnabled(false); myFooterLabel.setEnabled(false); init(); - initCurrentStep(); + initCurrentStep(true); + setSize(400, 300); System.setProperty(StartupActionScriptManager.STARTUP_WIZARD_MODE, "true"); } @@ -125,7 +126,7 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis } if (e.getSource() == myBackButton) { myIndex--; - initCurrentStep(); + initCurrentStep(false); return; } if (e.getSource() == myNextButton) { @@ -134,7 +135,7 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis return; } myIndex++; - initCurrentStep(); + initCurrentStep(true); } } @@ -148,8 +149,9 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis super.doOKAction(); } - private void initCurrentStep() { + private void initCurrentStep(boolean forward) { final AbstractCustomizeWizardStep myCurrentStep = mySteps.get(myIndex); + myCurrentStep.beforeShown(forward); myCardLayout.swipe(myContentPanel, myCurrentStep.getTitle(), JBCardLayout.SwipeDirection.AUTO, new Runnable() { @Override public void run() { From a39b28975be23b7c9202a330522adeafe8d81ca1 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 22 Apr 2014 19:53:31 +0400 Subject: [PATCH 07/86] [git log] IDEA-122305 Fix structure filter. Use --sparse only when requesting the whole history. Additionally use "--simplify-merge" in case of structure filter to avoid unrelated merges. --- plugins/git4idea/src/git4idea/history/GitHistoryUtils.java | 2 +- plugins/git4idea/src/git4idea/log/GitLogProvider.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java index 82f2cf79ad6d..3641c51f1627 100644 --- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java +++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java @@ -531,7 +531,7 @@ public class GitHistoryUtils { AUTHOR_NAME, AUTHOR_EMAIL); h.setStdoutSuppressed(true); h.addParameters(parser.getPretty(), "--encoding=UTF-8"); - h.addParameters("--full-history", "--sparse"); + h.addParameters("--full-history"); h.addParameters("--date-order"); h.addParameters(parameters); h.endOptions(); diff --git a/plugins/git4idea/src/git4idea/log/GitLogProvider.java b/plugins/git4idea/src/git4idea/log/GitLogProvider.java index 07afb4eeb09b..5f03de5b9c81 100644 --- a/plugins/git4idea/src/git4idea/log/GitLogProvider.java +++ b/plugins/git4idea/src/git4idea/log/GitLogProvider.java @@ -165,7 +165,9 @@ public class GitLogProvider implements VcsLogProvider { return Collections.emptyList(); } - return GitHistoryUtils.readCommits(myProject, root, userRegistry, GitHistoryUtils.LOG_ALL); + List parameters = new ArrayList(GitHistoryUtils.LOG_ALL); + parameters.add("--sparse"); + return GitHistoryUtils.readCommits(myProject, root, userRegistry, parameters); } @NotNull @@ -315,6 +317,7 @@ public class GitLogProvider implements VcsLogProvider { // note: structure filter must be the last parameter, because it uses "--" which separates parameters from paths if (filterCollection.getStructureFilter() != null) { + filterParameters.add("--simplify-merges"); filterParameters.add("--"); for (VirtualFile file : filterCollection.getStructureFilter().getFiles(root)) { filterParameters.add(file.getPath()); From da52f84cb90707288b0b12b28a557f2c06ebb547 Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Tue, 22 Apr 2014 20:07:08 +0400 Subject: [PATCH 08/86] IDEA-79312 text cursor gets lost - could bee disabled by focus.fix.lost.cursor key --- .../openapi/wm/impl/FocusManagerImpl.java | 27 ++++++++++--------- .../src/com/intellij/ui/FocusTrackback.java | 4 ++- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java index b66fcf46abb7..58f315f0246c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java @@ -363,21 +363,23 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable { return true; } - boolean doNotExecuteBecauseAppIsInactive = - !myApp.isActive() && !canExecuteOnInactiveApplication(cmd) && Registry.is("actionSystem.suspendFocusTransferIfApplicationInactive"); + if (!Registry.is("focus.fix.lost.cursor")) { + boolean doNotExecuteBecauseAppIsInactive = + !myApp.isActive() && !canExecuteOnInactiveApplication(cmd) && Registry.is("actionSystem.suspendFocusTransferIfApplicationInactive"); - if (doNotExecuteBecauseAppIsInactive) { - if (myCallbackOnActivation != null) { - myCallbackOnActivation.setRejected(); - if (myFocusCommandOnAppActivation != null) { - resetCommand(myFocusCommandOnAppActivation, true); + if (doNotExecuteBecauseAppIsInactive) { + if (myCallbackOnActivation != null) { + myCallbackOnActivation.setRejected(); + if (myFocusCommandOnAppActivation != null) { + resetCommand(myFocusCommandOnAppActivation, true); + } } + + myFocusCommandOnAppActivation = cmd; + myCallbackOnActivation = result; + + return true; } - - myFocusCommandOnAppActivation = cmd; - myCallbackOnActivation = result; - - return true; } return false; @@ -1152,6 +1154,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable { @Override public boolean isFocusTransferEnabled() { + if (Registry.is("focus.fix.lost.cursor")) return true; return myApp.isActive() || !Registry.is("actionSystem.suspendFocusTransferIfApplicationInactive"); } diff --git a/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java b/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java index d22fa1960c67..9ad0931c85b9 100644 --- a/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java +++ b/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java @@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.ExpirableRunnable; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.wm.FocusCommand; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ex.LayoutFocusTraversalPolicyExt; @@ -452,7 +453,8 @@ public class FocusTrackback { } public void cleanParentWindow() { - if (myParentWindow != null) { + if (!Registry.is("focus.fix.lost.cursor")) return; + if (myParentWindow != null) { try { Method tmpLost = Window.class.getDeclaredMethod("setTemporaryLostComponent", Component.class); tmpLost.setAccessible(true); From 37ed33ea2510be546ffd379f7569a5cd4d63b4f7 Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Tue, 22 Apr 2014 20:09:32 +0400 Subject: [PATCH 09/86] Missed commit for IDEA-79312 --- platform/platform-resources-en/src/misc/registry.properties | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index 491eeb48bdda..5b67947c5fcd 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -390,3 +390,6 @@ editor.richcopy.debug=false editor.richcopy.max.size.megabytes=10 allow.dialog.based.popups=false allow.dialog.based.popups.description=Allows to use a JDialog as popup toplevel + +focus.fix.lost.cursor=true +focus.fix.lost.cursor.description=See IDEA-79312 From 71cd276902434cf0838f2ff44cec62dae2bb1bd8 Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Tue, 22 Apr 2014 17:33:06 +0400 Subject: [PATCH 10/86] Fix scrolling in module aware configurables [r=ushakov] --- .../options/ModuleAwareProjectConfigurable.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/ModuleAwareProjectConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/ModuleAwareProjectConfigurable.java index 71b7dc7e7169..f7d8ab8e7df1 100644 --- a/platform/lang-impl/src/com/intellij/application/options/ModuleAwareProjectConfigurable.java +++ b/platform/lang-impl/src/com/intellij/application/options/ModuleAwareProjectConfigurable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.intellij.application.options; import com.intellij.openapi.module.Module; +import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.options.UnnamedConfigurable; @@ -34,6 +35,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.border.EmptyBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; @@ -44,7 +46,8 @@ import java.util.Map; /** * @author yole */ -public abstract class ModuleAwareProjectConfigurable implements SearchableConfigurable { +public abstract class ModuleAwareProjectConfigurable implements SearchableConfigurable, + Configurable.NoScroll { @NotNull private final Project myProject; private final String myDisplayName; @@ -113,7 +116,8 @@ public abstract class ModuleAwareProjectConfigurable Date: Tue, 22 Apr 2014 20:56:28 +0400 Subject: [PATCH 11/86] tip reference moved as a separated static constant to HgUtil --- .../hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java | 8 ++++---- .../org/zmlx/hg4idea/ui/HgCommonDialogWithChoices.java | 5 ++++- plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java index 84b070ea35c6..9554e9c59165 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java @@ -38,6 +38,8 @@ import org.zmlx.hg4idea.util.HgUtil; import java.text.SimpleDateFormat; import java.util.*; +import static org.zmlx.hg4idea.util.HgUtil.TIP_REFERENCE; + public class HgLogProvider implements VcsLogProvider { private static final Logger LOG = Logger.getInstance(HgLogProvider.class); @@ -47,8 +49,6 @@ public class HgLogProvider implements VcsLogProvider { @NotNull private final VcsLogRefManager myRefSorter; @NotNull private final VcsLogObjectsFactory myVcsObjectsFactory; - private static final String RECENT_HEAD = "tip"; - public HgLogProvider(@NotNull Project project, @NotNull HgRepositoryManager repositoryManager, @NotNull VcsLogObjectsFactory factory) { myProject = project; myRepositoryManager = repositoryManager; @@ -119,7 +119,7 @@ public class HgLogProvider implements VcsLogProvider { } String currentRevision = repository.getCurrentRevision(); if (currentRevision != null) { // null => fresh repository - refs.add(myVcsObjectsFactory.createRef(myVcsObjectsFactory.createHash(currentRevision), RECENT_HEAD, HgRefManager.HEAD, root)); + refs.add(myVcsObjectsFactory.createRef(myVcsObjectsFactory.createHash(currentRevision), TIP_REFERENCE, HgRefManager.HEAD, root)); } for (HgNameWithHashInfo tagInfo : tags) { refs.add(myVcsObjectsFactory.createRef(tagInfo.getHash(), tagInfo.getName(), HgRefManager.TAG, root)); @@ -172,7 +172,7 @@ public class HgLogProvider implements VcsLogProvider { boolean atLeastOneBranchExists = false; for (String branchName : filterCollection.getBranchFilter().getBranchNames()) { - if (branchName.equals(RECENT_HEAD) || branchExists(repository, branchName)) { + if (branchName.equals(TIP_REFERENCE) || branchExists(repository, branchName)) { filterParameters.add(prepareParameter("branch", branchName)); atLeastOneBranchExists = true; } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCommonDialogWithChoices.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCommonDialogWithChoices.java index 4c7ff6214e94..2c28d4c500ed 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCommonDialogWithChoices.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCommonDialogWithChoices.java @@ -31,6 +31,8 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Collection; +import static org.zmlx.hg4idea.util.HgUtil.TIP_REFERENCE; + public class HgCommonDialogWithChoices extends DialogWrapper { @@ -119,7 +121,8 @@ public class HgCommonDialogWithChoices extends DialogWrapper { HgRepository repo = hgRepositorySelectorComponent.getRepository(); branchSelector.setModel(new DefaultComboBoxModel(repo.getOpenedBranches().toArray())); DefaultComboBoxModel tagComboBoxModel = new DefaultComboBoxModel(HgUtil.getNamesWithoutHashes(repo.getTags()).toArray()); - tagComboBoxModel.addElement("tip"); //HgRepository does not store 'tip' tag because it is internal and not included in tags file + tagComboBoxModel + .addElement(TIP_REFERENCE); //HgRepository does not store 'tip' tag because it is internal and not included in tags file tagSelector.setModel(tagComboBoxModel); bookmarkSelector.setModel(new DefaultComboBoxModel(HgUtil.getNamesWithoutHashes(repo.getBookmarks()).toArray())); update(); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java index ad1ad6197ed7..0f3cc45cfd7d 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java @@ -72,6 +72,7 @@ public abstract class HgUtil { public static final int MANY_FILES = 100; private static final Logger LOG = Logger.getInstance(HgUtil.class); public static final String DOT_HG = ".hg"; + public static final String TIP_REFERENCE = "tip"; public static File copyResourceToTempFile(String basename, String extension) throws IOException { final InputStream in = HgUtil.class.getClassLoader().getResourceAsStream("python/" + basename + extension); From 72ae579262bf097766ad12d548330270dd66aca1 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Tue, 22 Apr 2014 21:29:25 +0400 Subject: [PATCH 12/86] IDEA-109187 new HgReference validator implemented *input validator added got user's input branch/tag and bookmark names; *document listener in appropriate dialogs changed to DocumentAdapter; *new parametrization test added for hg reference validation; *annotations added --- .../hg4idea/action/HgBranchPopupActions.java | 30 ++--- .../org/zmlx/hg4idea/ui/HgBookmarkDialog.java | 42 ++++--- .../src/org/zmlx/hg4idea/ui/HgTagDialog.java | 36 +++--- .../hg4idea/util/HgReferenceValidator.java | 82 +++++++++++++ .../src/org/zmlx/hg4idea/util/HgUtil.java | 19 +-- .../validator/HgReferenceValidatorTest.java | 116 ++++++++++++++++++ 6 files changed, 268 insertions(+), 57 deletions(-) create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/util/HgReferenceValidator.java create mode 100644 plugins/hg4idea/testSrc/hg4idea/test/validator/HgReferenceValidatorTest.java diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java index 62d5981e55f7..45dd12bd9c81 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java @@ -25,7 +25,6 @@ import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.PlatformIcons; @@ -48,7 +47,8 @@ import org.zmlx.hg4idea.util.HgErrorUtil; import java.util.*; -import static org.zmlx.hg4idea.util.HgUtil.*; +import static org.zmlx.hg4idea.util.HgUtil.getNamesWithoutHashes; +import static org.zmlx.hg4idea.util.HgUtil.getNewBranchNameFromUser; public class HgBranchPopupActions { @@ -62,8 +62,8 @@ public class HgBranchPopupActions { ActionGroup createActions(@Nullable DefaultActionGroup toInsert) { DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); - popupGroup.addAction(new HgNewBranchAction(myProject, Collections.singletonList(myRepository), myRepository.getRoot())); - popupGroup.addAction(new HgNewBookmarkAction(myProject, Collections.singletonList(myRepository), myRepository.getRoot())); + popupGroup.addAction(new HgNewBranchAction(myProject, Collections.singletonList(myRepository), myRepository)); + popupGroup.addAction(new HgNewBookmarkAction(myProject, Collections.singletonList(myRepository), myRepository)); popupGroup.addAction(new HgShowUnnamedHeadsForCurrentBranchAction(myProject, myRepository)); if (toInsert != null) { popupGroup.addAll(toInsert); @@ -92,24 +92,24 @@ public class HgBranchPopupActions { } private static class HgNewBranchAction extends NewBranchAction { - @NotNull final VirtualFile myPreselectedRepo; + @NotNull final HgRepository myPreselectedRepo; - HgNewBranchAction(@NotNull Project project, @NotNull List repositories, @NotNull VirtualFile preselectedRepo) { + HgNewBranchAction(@NotNull Project project, @NotNull List repositories, @NotNull HgRepository preselectedRepo) { super(project, repositories); myPreselectedRepo = preselectedRepo; } @Override public void actionPerformed(AnActionEvent e) { - final String name = getNewBranchNameFromUser(myProject, "Create New Branch"); + final String name = getNewBranchNameFromUser(myPreselectedRepo, "Create New Branch"); if (name == null) { return; } try { - new HgBranchCreateCommand(myProject, myPreselectedRepo, name).execute(new HgCommandResultHandler() { + new HgBranchCreateCommand(myProject, myPreselectedRepo.getRoot(), name).execute(new HgCommandResultHandler() { @Override public void process(@Nullable HgCommandResult result) { - getRepositoryManager(myProject).updateRepository(myPreselectedRepo); + myPreselectedRepo.update(); if (HgErrorUtil.hasErrorsInCommandExecution(result)) { new HgCommandResultNotifier(myProject) .notifyError(result, "Creation failed", "Branch creation [" + name + "] failed"); @@ -124,11 +124,11 @@ public class HgBranchPopupActions { } private static class HgNewBookmarkAction extends DumbAwareAction { - protected final List myRepositories; - protected Project myProject; - @NotNull final VirtualFile myPreselectedRepo; + @NotNull protected final List myRepositories; + @NotNull protected Project myProject; + @NotNull final HgRepository myPreselectedRepo; - HgNewBookmarkAction(@NotNull Project project, @NotNull List repositories, @NotNull VirtualFile preselectedRepo) { + HgNewBookmarkAction(@NotNull Project project, @NotNull List repositories, @NotNull HgRepository preselectedRepo) { super("New Bookmark", "Create new bookmark", null); myProject = project; myRepositories = repositories; @@ -146,12 +146,12 @@ public class HgBranchPopupActions { @Override public void actionPerformed(AnActionEvent e) { - final HgBookmarkDialog bookmarkDialog = new HgBookmarkDialog(myProject); + final HgBookmarkDialog bookmarkDialog = new HgBookmarkDialog(myPreselectedRepo); bookmarkDialog.show(); if (bookmarkDialog.isOK()) { try { final String name = bookmarkDialog.getName(); - new HgBookmarkCommand(myProject, myPreselectedRepo, name).createBookmark(bookmarkDialog.isActive()); + new HgBookmarkCommand(myProject, myPreselectedRepo.getRoot(), name).createBookmark(bookmarkDialog.isActive()); } catch (HgCommandException exception) { HgAbstractGlobalAction.handleException(myProject, exception); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgBookmarkDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgBookmarkDialog.java index 6c471f1af4fd..8addb557d301 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgBookmarkDialog.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgBookmarkDialog.java @@ -1,9 +1,7 @@ package org.zmlx.hg4idea.ui; -import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.ui.ValidationInfo; -import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.DocumentAdapter; import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.JBTextField; @@ -11,8 +9,11 @@ import com.intellij.util.ui.GridBag; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.util.HgReferenceValidator; import javax.swing.*; +import javax.swing.event.DocumentEvent; import java.awt.*; import static com.intellij.util.ui.UIUtil.DEFAULT_HGAP; @@ -22,11 +23,13 @@ import static com.intellij.util.ui.UIUtil.DEFAULT_VGAP; * @author Nadya Zabrodina */ public class HgBookmarkDialog extends DialogWrapper { + @NotNull private HgRepository myRepository; @NotNull private JBTextField myBookmarkName; @NotNull private JBCheckBox myActiveCheckbox; - public HgBookmarkDialog(@Nullable Project project) { - super(project, false); + public HgBookmarkDialog(@NotNull HgRepository repository) { + super(repository.getProject(), false); + myRepository = repository; setTitle("Create Bookmark"); setResizable(false); init(); @@ -62,6 +65,12 @@ public class HgBookmarkDialog extends DialogWrapper { JLabel icon = new JLabel(UIUtil.getQuestionIcon(), SwingConstants.LEFT); myBookmarkName = new JBTextField(13); + myBookmarkName.getDocument().addDocumentListener(new DocumentAdapter() { + @Override + public void textChanged(DocumentEvent e) { + validateFields(); + } + }); JBLabel bookmarkLabel = new JBLabel("Bookmark name:"); bookmarkLabel.setLabelFor(myBookmarkName); @@ -75,6 +84,19 @@ public class HgBookmarkDialog extends DialogWrapper { return contentPanel; } + private void validateFields() { + HgReferenceValidator validator = HgReferenceValidator.newInstance(myRepository); + String name = getName(); + if (!validator.checkInput(name)) { + String message = validator.getErrorText(name); + setErrorText(message == null ? "You have to specify bookmark name." : message); + setOKActionEnabled(false); + return; + } + setErrorText(null); + setOKActionEnabled(true); + } + public boolean isActive() { return !myActiveCheckbox.isSelected(); } @@ -83,14 +105,4 @@ public class HgBookmarkDialog extends DialogWrapper { public String getName() { return myBookmarkName.getText(); } - - @Override - @Nullable - protected ValidationInfo doValidate() { - String message = "You have to specify bookmark name."; - if (StringUtil.isEmptyOrSpaces(getName())) { - return new ValidationInfo(message, myBookmarkName); - } - return null; - } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java index df4bb6101829..3a986e519267 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java @@ -14,11 +14,12 @@ package org.zmlx.hg4idea.ui; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.DocumentAdapter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.util.HgReferenceValidator; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -34,17 +35,10 @@ public class HgTagDialog extends DialogWrapper { public HgTagDialog(@NotNull Project project, @NotNull Collection repos, @Nullable HgRepository selectedRepo) { super(project, false); hgRepositorySelectorComponent.setTitle("Select repository to tag"); - DocumentListener documentListener = new DocumentListener() { - public void insertUpdate(DocumentEvent e) { - update(); - } - - public void removeUpdate(DocumentEvent e) { - update(); - } - - public void changedUpdate(DocumentEvent e) { - update(); + DocumentListener documentListener = new DocumentAdapter() { + @Override + protected void textChanged(DocumentEvent e) { + validateFields(); } }; @@ -67,19 +61,23 @@ public class HgTagDialog extends DialogWrapper { private void setRoots(@NotNull Collection repos, @Nullable HgRepository selectedRepo) { hgRepositorySelectorComponent.setRoots(repos); hgRepositorySelectorComponent.setSelectedRoot(selectedRepo); - update(); } protected JComponent createCenterPanel() { return contentPanel; } - private void update() { - setOKActionEnabled(validateOptions()); - } - - private boolean validateOptions() { - return !StringUtil.isEmptyOrSpaces(tagTxt.getText()); + private void validateFields() { + HgReferenceValidator validator = HgReferenceValidator.newInstance(hgRepositorySelectorComponent.getRepository()); + String name = getTagName(); + if (!validator.checkInput(name)) { + String message = validator.getErrorText(name); + setErrorText(message == null ? "You have to specify tag name." : message); + setOKActionEnabled(false); + return; + } + setErrorText(null); + setOKActionEnabled(true); } @Override diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgReferenceValidator.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgReferenceValidator.java new file mode 100644 index 000000000000..27dadb5a05ae --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgReferenceValidator.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.zmlx.hg4idea.util; + +import com.intellij.openapi.ui.InputValidatorEx; +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.repo.HgRepository; + +import java.util.Collection; +import java.util.regex.Pattern; + +import static org.zmlx.hg4idea.util.HgUtil.TIP_REFERENCE; + +public class HgReferenceValidator implements InputValidatorEx { + + private final HgRepository myRepository; + private String myErrorText; + + private static final Pattern ILLEGAL = Pattern.compile( + ".*:.*|" + // colon character is not allowed + "[0-9]*" // reference name couldn't contain only digits + ); + + private HgReferenceValidator(@NotNull HgRepository repository) { + myRepository = repository; + } + + public static HgReferenceValidator newInstance(@NotNull HgRepository repository) { + return new HgReferenceValidator(repository); + } + + @Override + public boolean checkInput(@Nullable String name) { + if (StringUtil.isEmptyOrSpaces(name)) { + return false; + } + if (ILLEGAL.matcher(name).matches()) { + myErrorText = "Invalid name for branch/tag"; + return false; + } + return !isReservedWord(name) && !hasConflictsWithAnotherBranch(name); + } + + @Override + public boolean canClose(@Nullable String name) { + return checkInput(name); + } + + boolean isReservedWord(@Nullable String name) { + myErrorText = TIP_REFERENCE.equals(name) ? String.format("The name \'%s\' is reserved.", name) : null; + return myErrorText != null; + } + + boolean hasConflictsWithAnotherBranch(@Nullable String name) { + Collection branches = myRepository.getBranches().keySet(); + String currentBranch = myRepository.getCurrentBranch(); // branches set doesn't contain uncommitted branch -> need an addition check + myErrorText = currentBranch.equals(name) || branches.contains(name) + ? String.format("A branch with the \'%s\' name already exists", name) : null; + return myErrorText != null; + } + + @Nullable + @Override + public String getErrorText(@Nullable String inputString) { + return myErrorText; + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java index 0f3cc45cfd7d..d0c52d774d8b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java @@ -324,14 +324,17 @@ public abstract class HgUtil { } /** - * Shows a message dialog to enter the name of new branch. - * @return name of new branch or {@code null} if user has cancelled the dialog. - */ - @Nullable - public static String getNewBranchNameFromUser(@NotNull Project project, - @NotNull String dialogTitle) { - return Messages.showInputDialog(project, "Enter the name of new branch:", dialogTitle, Messages.getQuestionIcon()); - } + * Shows a message dialog to enter the name of new branch. + * + * @return name of new branch or {@code null} if user has cancelled the dialog. + */ + @Nullable + public static String getNewBranchNameFromUser(@NotNull HgRepository repository, + @NotNull String dialogTitle) { + return Messages.showInputDialog(repository.getProject(), "Enter the name of new branch:", dialogTitle, Messages.getQuestionIcon(), "", + HgReferenceValidator.newInstance(repository)); + } + /** * Checks is a merge operation is in progress on the given repository. * Actually gets the number of parents of the current revision. If there are 2 parents, then a merge is going on. Otherwise there is diff --git a/plugins/hg4idea/testSrc/hg4idea/test/validator/HgReferenceValidatorTest.java b/plugins/hg4idea/testSrc/hg4idea/test/validator/HgReferenceValidatorTest.java new file mode 100644 index 000000000000..3bec11a46585 --- /dev/null +++ b/plugins/hg4idea/testSrc/hg4idea/test/validator/HgReferenceValidatorTest.java @@ -0,0 +1,116 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hg4idea.test.validator; + +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.UIUtil; +import hg4idea.test.HgPlatformTest; +import hg4idea.test.HgTestUtil; +import org.jetbrains.annotations.NotNull; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.util.HgReferenceValidator; +import org.zmlx.hg4idea.util.HgUtil; + +import java.util.Collection; + +import static com.intellij.openapi.vcs.Executor.cd; +import static com.intellij.openapi.vcs.Executor.echo; +import static hg4idea.test.HgExecutor.hg; + +@RunWith(Parameterized.class) +public class HgReferenceValidatorTest extends HgPlatformTest { + + private HgReferenceValidator myValidator; + private static final String BRANCH_NAME = "Abranch"; + private static final String UNCOMMITTED_BRANCH = "uncommitted new branch"; + + @NotNull private final String myBranchName; + private final boolean myExpected; + + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + HgTestUtil.updateDirectoryMappings(myProject, myRepository); + HgRepository hgRepository = HgUtil.getRepositoryManager(myProject).getRepositoryForRoot(myRepository); + assertNotNull(hgRepository); + myValidator = HgReferenceValidator.newInstance(hgRepository); + cd(myRepository); + hg("branch '" + BRANCH_NAME + "'"); + String firstFile = "file.txt"; + echo(firstFile, BRANCH_NAME); + hg("commit -m 'createdBranch " + BRANCH_NAME + "' "); + hg("branch '" + UNCOMMITTED_BRANCH + "'"); + hgRepository.update(); + } + + @Override + @After + public void tearDown() throws Exception { + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + @Override + public void run() { + try { + HgReferenceValidatorTest.super.tearDown(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + } + + @SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors", "UnusedParameters"}) + public HgReferenceValidatorTest(@NotNull String name, @NotNull String branchName, boolean expected) { + myBranchName = branchName; + myExpected = expected; + } + + + @Parameterized.Parameters(name = "{0}") + public static Collection createData() { + return ContainerUtil.newArrayList(new Object[][]{ + {"WORD", "branch", true}, + {"UNDERSCORED_WORD", "new_branch", true}, + {"HIERARCHY", "user/branch", true}, + {"HIERARCHY_2", "user/branch/sub_branch", true}, + {"BEGINS_WITH_SLASH", "/branch", true}, + {"WITH_DOTS", "complex.branch.name", true}, + {"WITH_WHITESPACES", "branch with whitespaces", true}, + {"WITH_SPECIAL_CHARS", "bra~nch-^%$", true}, + {"NOT_RESERVED", "TIP", true}, + {"CONTAINS_COLON", "bra:nch", false}, + {"ONLY_DIGITS", "876876", false}, + {"START_WITH_COLON", ":branch", false}, + {"ENDS_WITH_COLON", "branch:", false}, + {"RESERVED_WORD", "tip", false}, + {"BRANCH_CONFLICT", BRANCH_NAME, false}, + {"UNCOMMITTED_BRANCH_CONFLICT", UNCOMMITTED_BRANCH, false}, + }); + } + + @Test + public void testValid() { + assertEquals(" Wrong validation for " + myBranchName, myExpected, myValidator.checkInput(myBranchName)); + assertEquals(" Should be valid " + myBranchName, myExpected, myValidator.canClose(myBranchName)); + } +} From 9914757d15cbbe3e41da8b202cddce1497fb9787 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 17 Apr 2014 10:35:09 +0200 Subject: [PATCH 13/86] warn about underscore identifier --- .../daemon/impl/analysis/HighlightUtil.java | 4 -- .../JavacQuirksInspectionVisitor.java | 12 +++++ .../lambda/advHighlighting/Underscore.java | 3 ++ .../lambda/highlighting/Underscores.java | 5 -- .../lambda/LightAdvHighlightingJdk8Test.java | 52 +++++++++++++++++++ 5 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/advHighlighting/Underscore.java create mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LightAdvHighlightingJdk8Test.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 66dfd93bd79c..db56e8be3dc8 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -684,10 +684,6 @@ public class HighlightUtil extends HighlightUtilBase { String message = JavaErrorMessages.message("underscore.lambda.identifier"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(message).create(); } - else { - String message = JavaErrorMessages.message("underscore.identifier"); - return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(identifier).descriptionAndTooltip(message).create(); - } } return null; diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/compiler/JavacQuirksInspectionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/compiler/JavacQuirksInspectionVisitor.java index 740a4101cf90..63d4c891d255 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/compiler/JavacQuirksInspectionVisitor.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/compiler/JavacQuirksInspectionVisitor.java @@ -15,9 +15,11 @@ */ package com.intellij.codeInspection.compiler; +import com.intellij.codeInsight.daemon.JavaErrorMessages; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.patterns.ElementPattern; +import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; @@ -63,4 +65,14 @@ public class JavacQuirksInspectionVisitor extends JavaElementVisitor { }); } } + + @Override + public void visitIdentifier(PsiIdentifier identifier) { + super.visitIdentifier(identifier); + if (PsiUtil.getLanguageLevel(identifier).isAtLeast(LanguageLevel.JDK_1_8)) { + if ("_".equals(identifier.getText())) { + myHolder.registerProblem(identifier, JavaErrorMessages.message("underscore.identifier")); + } + } + } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/advHighlighting/Underscore.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/advHighlighting/Underscore.java new file mode 100644 index 000000000000..50c8d6ce9116 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/advHighlighting/Underscore.java @@ -0,0 +1,3 @@ +class Test { + void _(){} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Underscores.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Underscores.java index 2d89ec317ed9..154a75af1b23 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Underscores.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Underscores.java @@ -1,10 +1,5 @@ class C { void test() { - { - I _ = new I() { public void f(int i) { } }; - accept(_); - } - { accept(_ -> System.out.println(_)); accept((int _) -> System.out.println(_)); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LightAdvHighlightingJdk8Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LightAdvHighlightingJdk8Test.java new file mode 100644 index 000000000000..630acb0404b7 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LightAdvHighlightingJdk8Test.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.daemon.lambda; + +import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; +import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.codeInspection.compiler.JavacQuirksInspection; +import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.testFramework.IdeaTestUtil; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class LightAdvHighlightingJdk8Test extends LightDaemonAnalyzerTestCase { + @NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/advHighlighting"; + + @NotNull + @Override + protected LocalInspectionTool[] configureLocalInspectionTools() { + return new LocalInspectionTool[]{ + new JavacQuirksInspection(), + }; + } + + public void testUnderscore() throws Exception { + doTest(); + } + + private void doTest() { + IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_8, getModule(), getTestRootDisposable()); + doTestNewInference(BASE_PATH + "/" + getTestName(false) + ".java", true, false); + } + + @Override + protected Sdk getProjectJDK() { + return IdeaTestUtil.getMockJdk18(); + } +} From bd9dbfc7d5ec01fa0889cb8efa90d8aa6eac9d0f Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 17 Apr 2014 11:16:42 +0200 Subject: [PATCH 14/86] testdata --- .../highlighting/FunctionalInterfaceAnnotation3.java | 8 ++++++++ .../codeInsight/daemon/lambda/LambdaHighlightingTest.java | 1 + 2 files changed, 9 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation3.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation3.java new file mode 100644 index 000000000000..6e392f2d74d6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation3.java @@ -0,0 +1,8 @@ +interface I { + void m(T t); + void m(K k); + } + +@FunctionalInterface +interface IEx extends I { } + diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java index aa18173074fa..4e971c52685f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java @@ -78,6 +78,7 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase { public void testAmbiguitySpecificReturn() { doTest(true); } public void testFunctionalInterfaceAnnotation() { doTest(); } public void testFunctionalInterfaceAnnotation2() { doTest(); } + public void testFunctionalInterfaceAnnotation3() { doTest(); } public void testAmbiguityReturnValueResolution() { doTest(); } public void testAmbiguityReturnValueResolution1() { doTest(); } public void testAmbiguityReturnValueResolution2() { doTest(true); } From 552dfe92a92ee587fbb4ada664e316e532ac536c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 17 Apr 2014 11:58:15 +0200 Subject: [PATCH 15/86] lambda: intersection type produces conjunction of abstract methods --- .../intellij/psi/LambdaHighlightingUtil.java | 13 +++++++++-- .../src/com/intellij/psi/LambdaUtil.java | 22 ++++++++++++++----- .../lambda/highlighting/Intersection.java | 20 +++++++++++++++++ .../daemon/lambda/LambdaHighlightingTest.java | 1 + 4 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Intersection.java diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java index 178001bc424c..1b22d9c4288f 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java @@ -97,8 +97,17 @@ public class LambdaHighlightingUtil { @Nullable public static String checkInterfaceFunctional(PsiType functionalInterfaceType) { if (functionalInterfaceType instanceof PsiIntersectionType) { - for (PsiType type : ((PsiIntersectionType)functionalInterfaceType).getConjuncts()) { - if (checkInterfaceFunctional(type) == null) return null; + if (!LambdaUtil.isFunctionalType(functionalInterfaceType)) { + int count = 0; + for (PsiType type : ((PsiIntersectionType)functionalInterfaceType).getConjuncts()) { + if (checkInterfaceFunctional(type) == null) { + count++; + } + } + + if (count > 1) { + return "Multiple non-overriding abstract methods found in " + functionalInterfaceType.getPresentableText(); + } } } final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index e56114029361..9206cd8d0802 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -103,9 +103,7 @@ public class LambdaUtil { public static boolean isFunctionalType(PsiType type) { if (type instanceof PsiIntersectionType) { - for (PsiType type1 : ((PsiIntersectionType)type).getConjuncts()) { - if (isFunctionalType(type1)) return true; - } + return extractFunctionalConjunct((PsiIntersectionType)type) != null; } return isFunctionalClass(PsiUtil.resolveGenericsClassInType(type).getElement()); } @@ -286,9 +284,8 @@ public class LambdaUtil { } else if (parent instanceof PsiTypeCastExpression) { final PsiType castType = ((PsiTypeCastExpression)parent).getType(); if (castType instanceof PsiIntersectionType) { - for (PsiType conjunctType : ((PsiIntersectionType)castType).getConjuncts()) { - if (getFunctionalInterfaceMethod(conjunctType) != null) return conjunctType; - } + final PsiType conjunct = extractFunctionalConjunct((PsiIntersectionType)castType); + if (conjunct != null) return conjunct; } return castType; } @@ -363,6 +360,19 @@ public class LambdaUtil { return null; } + @Nullable + private static PsiType extractFunctionalConjunct(PsiIntersectionType type) { + PsiType conjunct = null; + for (PsiType conjunctType : ((PsiIntersectionType)type).getConjuncts()) { + final PsiMethod interfaceMethod = getFunctionalInterfaceMethod(conjunctType); + if (interfaceMethod != null) { + if (conjunct != null && !conjunct.equals(conjunctType)) return null; + conjunct = conjunctType; + } + } + return conjunct; + } + private static PsiType getFunctionalInterfaceTypeByContainingLambda(@NotNull PsiLambdaExpression parentLambda) { final PsiType parentInterfaceType = parentLambda.getFunctionalInterfaceType(); return parentInterfaceType != null ? getFunctionalInterfaceReturnType(parentInterfaceType) : null; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Intersection.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Intersection.java new file mode 100644 index 000000000000..e470cf357b0b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Intersection.java @@ -0,0 +1,20 @@ +import java.io.Serializable; + +class Test { + + interface I { + void foo(); + } + + interface A { + void bar(int i); + } + + { + Object o1 = (Serializable & I) () -> {}; + Object o2 = (I & Serializable) () -> {}; + Object o3 = (I & Runnable) () -> {}; + Object o4 = (A & Runnable) () -> {}; + Object o5 = (Runnable & A) () -> {}; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java index 4e971c52685f..5968731e6d31 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java @@ -101,6 +101,7 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase { public void testBreakContinueInside() {doTest();} public void testSameLambdaParamNames() {doTest();} public void testIDEA123308() {doTest();} + public void testIntersection() {doTest();} private void doTest() { doTest(false); From 98ab76f0604e090e4d7dad44a2bf1c241f48b591 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 17 Apr 2014 12:25:58 +0200 Subject: [PATCH 16/86] new overload resolution: most specific check on invalid class exceptions fixed --- .../resolve/graphInference/InferenceSession.java | 4 ++-- .../mostSpecific/IncompleteMethodInInterface.java | 12 ++++++++++++ .../daemon/lambda/MostSpecificResolutionTest.java | 4 ++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/IncompleteMethodInInterface.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java index 361462430105..e681d2d5a31b 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java @@ -1070,7 +1070,7 @@ public class InferenceSession { session.addConstraint(new StrictSubtypingConstraint(tReturnType, sReturnType)); return true; } else { - return TypeConversionUtil.isAssignable(sReturnType, tReturnType); + return sReturnType != null && tReturnType != null && TypeConversionUtil.isAssignable(sReturnType, tReturnType); } } } @@ -1115,7 +1115,7 @@ public class InferenceSession { session.addConstraint(new StrictSubtypingConstraint(tReturnType, sReturnType)); return true; } else { - return TypeConversionUtil.isAssignable(sReturnType, tReturnType); + return sReturnType != null && tReturnType != null && TypeConversionUtil.isAssignable(sReturnType, tReturnType); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/IncompleteMethodInInterface.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/IncompleteMethodInInterface.java new file mode 100644 index 000000000000..8d71a82cc6b4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/IncompleteMethodInInterface.java @@ -0,0 +1,12 @@ +class Test { + interface I { Object in + voke(); } + interface IStr { String foo(); } + + public static void call(IStr str) {} + public static void call(I i) { } + + public static void main(String[] args) { + call(()-> null); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java index a46036cb98d4..004b52072a84 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java @@ -75,6 +75,10 @@ public class MostSpecificResolutionTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testIncompleteMethodInInterface() throws Exception { + doTest(false); + } + private void doTest() { doTest(true); } From 17b020f7c2d18df5b8f98e441147de3a9225d15e Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 17 Apr 2014 13:32:27 +0200 Subject: [PATCH 17/86] new overload resolution: covariant comparison of return types --- .../resolve/graphInference/InferenceSession.java | 4 ++-- .../JavaMethodsConflictResolver.java | 4 ++-- .../mostSpecific/MostSpecificByReturnType.java | 16 ++++++++++++++++ .../lambda/MostSpecificResolutionTest.java | 4 ++++ 4 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/MostSpecificByReturnType.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java index e681d2d5a31b..9d9c373159f9 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java @@ -1070,7 +1070,7 @@ public class InferenceSession { session.addConstraint(new StrictSubtypingConstraint(tReturnType, sReturnType)); return true; } else { - return sReturnType != null && tReturnType != null && TypeConversionUtil.isAssignable(sReturnType, tReturnType); + return sReturnType != null && tReturnType != null && TypeConversionUtil.isAssignable(tReturnType, sReturnType); } } } @@ -1115,7 +1115,7 @@ public class InferenceSession { session.addConstraint(new StrictSubtypingConstraint(tReturnType, sReturnType)); return true; } else { - return sReturnType != null && tReturnType != null && TypeConversionUtil.isAssignable(sReturnType, tReturnType); + return sReturnType != null && tReturnType != null && TypeConversionUtil.isAssignable(tReturnType, sReturnType); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java index 5f1e2f696961..93a444036bef 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java @@ -624,11 +624,11 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ } if (!applicable12ignoreFunctionalType && applicable21ignoreFunctionalType) { - return specifics == Specifics.SECOND ? Specifics.SECOND : Specifics.NEITHER; + return specifics == Specifics.FIRST ? Specifics.FIRST : Specifics.NEITHER; } if (!applicable21ignoreFunctionalType && applicable12ignoreFunctionalType) { - return specifics == Specifics.FIRST ? Specifics.FIRST : Specifics.NEITHER; + return specifics == Specifics.SECOND ? Specifics.SECOND : Specifics.NEITHER; } return specifics; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/MostSpecificByReturnType.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/MostSpecificByReturnType.java new file mode 100644 index 000000000000..5588c3e623a1 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/MostSpecificByReturnType.java @@ -0,0 +1,16 @@ +class Test { + interface I { Object invoke(); } + interface IStr { String foo(); } + + private static void call(IStr str) { + System.out.println(str); + } + + private static void call(I i) { + System.out.println(i); + } + + public static void main(String[] args) { + call(()-> null); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java index 004b52072a84..bea020bb9017 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java @@ -79,6 +79,10 @@ public class MostSpecificResolutionTest extends LightDaemonAnalyzerTestCase { doTest(false); } + public void testMostSpecificByReturnType() throws Exception { + doTest(); + } + private void doTest() { doTest(true); } From 76a92936098ebd9d5d4b53017aaf51705c646c4a Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 17 Apr 2014 13:44:20 +0200 Subject: [PATCH 18/86] testdata --- .../lambda/highlighting/NoBoxingInLambdaFormalParams.java | 8 ++++++++ .../codeInsight/daemon/lambda/LambdaHighlightingTest.java | 1 + 2 files changed, 9 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/NoBoxingInLambdaFormalParams.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/NoBoxingInLambdaFormalParams.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/NoBoxingInLambdaFormalParams.java new file mode 100644 index 000000000000..30e096ff8de1 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/NoBoxingInLambdaFormalParams.java @@ -0,0 +1,8 @@ +class LambdaConv10 { + + interface I { public R call( T t); } + + { + I in = (int i) -> 2 * i; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java index 5968731e6d31..7cccc155f5fd 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java @@ -102,6 +102,7 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase { public void testSameLambdaParamNames() {doTest();} public void testIDEA123308() {doTest();} public void testIntersection() {doTest();} + public void testNoBoxingInLambdaFormalParams() {doTest();} private void doTest() { doTest(false); From 4a34bd569b8474422ee46a7acb5e411d4ff574f4 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 17 Apr 2014 14:43:40 +0200 Subject: [PATCH 19/86] do not report unrelated return type error only for generics methods --- .../daemon/impl/analysis/HighlightMethodUtil.java | 2 +- .../UnrelatedReturnInTypeArgs.java | 13 +++++++++++++ .../daemon/GenericsHighlightingTest.java | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/UnrelatedReturnInTypeArgs.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index 975794d9419f..007fbdc98cf1 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -1181,7 +1181,7 @@ public class HighlightMethodUtil { continue; } } - if (JavaGenericsUtil.isRawToGeneric(currentType, otherSuperReturnType)) continue; + if (currentMethod.getTypeParameters().length > 0 && JavaGenericsUtil.isRawToGeneric(currentType, otherSuperReturnType)) continue; } return createIncompatibleReturnTypeMessage(currentMethod, otherSuperMethod, otherSuperReturnType, currentType, JavaErrorMessages.message("unrelated.overriding.methods.return.types"), diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/UnrelatedReturnInTypeArgs.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/UnrelatedReturnInTypeArgs.java new file mode 100644 index 000000000000..4e0fb23c7461 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/UnrelatedReturnInTypeArgs.java @@ -0,0 +1,13 @@ +import java.util.*; + +class Test { + interface A { + Iterable m(List ls); + } + + interface B { + Iterable m(List l); + } + + interface AB extends A, B {} +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index f4e40bde2970..c0ef03ce72b3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -341,6 +341,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIDEA120563() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } public void testIDEA121400() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } public void testIDEA123316() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } + public void testUnrelatedReturnInTypeArgs() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } public void testIDEA123352() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } public void testIDEA123518() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } public void testIDEA64103() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } From a55db180891cc78763b27c6988cc36d626d4a06b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 17 Apr 2014 14:59:06 +0200 Subject: [PATCH 20/86] lambda: accept intersection type when exactly one conjunct is functional --- .../intellij/psi/LambdaHighlightingUtil.java | 19 +++++++++---------- .../lambda/highlighting/Intersection.java | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java index 1b22d9c4288f..8dc811e6258d 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java @@ -97,18 +97,17 @@ public class LambdaHighlightingUtil { @Nullable public static String checkInterfaceFunctional(PsiType functionalInterfaceType) { if (functionalInterfaceType instanceof PsiIntersectionType) { - if (!LambdaUtil.isFunctionalType(functionalInterfaceType)) { - int count = 0; - for (PsiType type : ((PsiIntersectionType)functionalInterfaceType).getConjuncts()) { - if (checkInterfaceFunctional(type) == null) { - count++; - } - } - - if (count > 1) { - return "Multiple non-overriding abstract methods found in " + functionalInterfaceType.getPresentableText(); + int count = 0; + for (PsiType type : ((PsiIntersectionType)functionalInterfaceType).getConjuncts()) { + if (checkInterfaceFunctional(type) == null) { + count++; } } + + if (count > 1) { + return "Multiple non-overriding abstract methods found in " + functionalInterfaceType.getPresentableText(); + } + return null; } final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); final PsiClass aClass = resolveResult.getElement(); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Intersection.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Intersection.java index e470cf357b0b..767b54788948 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Intersection.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Intersection.java @@ -18,3 +18,18 @@ class Test { Object o5 = (Runnable & A) () -> {}; } } + +class Test1 { + + interface A { + void foo(); + } + + interface B { + void foo(); + } + + { + Object c0 = (A & B) ()->{}; + } +} From f1f6fcf53b610eb127b6e70f32646ec7bc0b208c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 17 Apr 2014 15:30:07 +0200 Subject: [PATCH 21/86] functional interfaces: ignore methods with type parameters during abstract method choosing --- .../src/com/intellij/psi/LambdaUtil.java | 3 ++- .../GenericNotGenericInterfaceMethod.java | 16 ++++++++++++++++ .../daemon/lambda/LambdaHighlightingTest.java | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/GenericNotGenericInterfaceMethod.java diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index 9206cd8d0802..09b9cdd48e64 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -181,7 +181,8 @@ public class LambdaUtil { boolean subsignature = true; for (MethodSignature methodSignature : signatures) { if (!signature.equals(methodSignature)) { - if (!MethodSignatureUtil.isSubsignature(signature, methodSignature)) { + if (!MethodSignatureUtil.isSubsignature(signature, methodSignature) && + methodSignature.getTypeParameters().length == 0) { subsignature = false; break; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/GenericNotGenericInterfaceMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/GenericNotGenericInterfaceMethod.java new file mode 100644 index 000000000000..9cb75abb0c80 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/GenericNotGenericInterfaceMethod.java @@ -0,0 +1,16 @@ +class Test { + + interface A { + void m(); + } + + interface B { + void m(); + } + + interface C extends A, B { } + + { + C c = ()-> {}; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java index 7cccc155f5fd..63684fa9c848 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java @@ -103,6 +103,7 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIDEA123308() {doTest();} public void testIntersection() {doTest();} public void testNoBoxingInLambdaFormalParams() {doTest();} + public void testGenericNotGenericInterfaceMethod() {doTest();} private void doTest() { doTest(false); From b49d8e753f555009318d5864f8d484d6e3f790bd Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 17 Apr 2014 15:48:31 +0200 Subject: [PATCH 22/86] testdata --- .../lambda/highlighting/InferredFromCast.java | 14 ++++++++++++++ .../lambda/highlighting/ReferencedFromSelf.java | 13 +++++++++++++ .../daemon/lambda/LambdaHighlightingTest.java | 2 ++ 3 files changed, 29 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/InferredFromCast.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReferencedFromSelf.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/InferredFromCast.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/InferredFromCast.java new file mode 100644 index 000000000000..e31cf5a86ffd --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/InferredFromCast.java @@ -0,0 +1,14 @@ +class Test { + + interface A { + int m(); + } + + interface B { + int m(int i); + } + + public static void main(String[] args) { + A a = ()-> ((B)i -> i).m(3); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReferencedFromSelf.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReferencedFromSelf.java new file mode 100644 index 000000000000..5b029df7ce4a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReferencedFromSelf.java @@ -0,0 +1,13 @@ +class Test { + + Runnable r; + { r = r::run; } + Runnable r1; + { r1 = () -> r1.run(); } + + + { + Runnable r = () -> r.run(); + Runnable r1 = r1::run; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java index 63684fa9c848..a3a326cfcf81 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java @@ -104,6 +104,8 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIntersection() {doTest();} public void testNoBoxingInLambdaFormalParams() {doTest();} public void testGenericNotGenericInterfaceMethod() {doTest();} + public void testInferredFromCast() {doTest();} + public void testReferencedFromSelf() {doTest();} private void doTest() { doTest(false); From 1698f7bb299c33b371ee35bb21093d97f73fa147 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 17 Apr 2014 16:22:36 +0200 Subject: [PATCH 23/86] testdata: ensure method ref qualified are checked over static problems --- .../lambda/methodRef/QualifiersInStaticContext.java | 11 +++++++++++ .../daemon/lambda/MethodRefHighlightingTest.java | 4 ++++ 2 files changed, 15 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/QualifiersInStaticContext.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/QualifiersInStaticContext.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/QualifiersInStaticContext.java new file mode 100644 index 000000000000..483237105eb2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/QualifiersInStaticContext.java @@ -0,0 +1,11 @@ +public class Test { + interface I { + void foo(); + } + + private Object o; + + public static void main(String[] args){ + I i = o::wait; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java index 1d09f51a07c9..b5c69c1358f9 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java @@ -99,6 +99,10 @@ public class MethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testQualifiersInStaticContext() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } From 9aa2f3aaac29c7d6d92bb3f6401fe40d8100afe1 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 22 Apr 2014 12:48:59 +0200 Subject: [PATCH 24/86] testdata: ensure correct parameters number in functional interface method --- .../mostSpecific/DifferentParamsLength.java | 29 +++++++++++++++++++ .../lambda/MostSpecificResolutionTest.java | 4 +++ 2 files changed, 33 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/DifferentParamsLength.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/DifferentParamsLength.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/DifferentParamsLength.java new file mode 100644 index 000000000000..951858bae638 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/DifferentParamsLength.java @@ -0,0 +1,29 @@ +class Test { + + interface I0 { + void m(); + } + + interface I1 { + void m(Object a); + } + + interface I2 { + void m(Object a1, Object a2); + } + + interface IVarargs { + void m(Object... as); + } + + void call(I0 p) { } + void call(I1 p) { } + void call(I2 p) { } + void call(IVarargs p) { } + + void test() { + call(() -> { }); + call(p1 -> { }); + call((p1, p2) -> {}); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java index bea020bb9017..20f634ac2eec 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java @@ -83,6 +83,10 @@ public class MostSpecificResolutionTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testDifferentParamsLength() throws Exception { + doTest(false); + } + private void doTest() { doTest(true); } From 5b910545646ee15450d2069314881735c4d454f9 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 22 Apr 2014 12:57:08 +0200 Subject: [PATCH 25/86] testdata: ensure overload resolution by return type should not take place for interrupted control flow --- .../NoReturnTypeResolutionForThrownException.java | 14 ++++++++++++++ .../daemon/lambda/MostSpecificResolutionTest.java | 4 ++++ 2 files changed, 18 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/NoReturnTypeResolutionForThrownException.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/NoReturnTypeResolutionForThrownException.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/NoReturnTypeResolutionForThrownException.java new file mode 100644 index 000000000000..81429131d099 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/NoReturnTypeResolutionForThrownException.java @@ -0,0 +1,14 @@ +class Test { + + interface I1 {String m();} + interface I2 {void m();} + + void call(I1 p) { } + void call(I2 p) { } + + void test() { + call(() -> { throw new RuntimeException(); }); + call(() -> { if (true) return ""; throw new RuntimeException(); }); + call(() -> { if (true) return; throw new RuntimeException(); }); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java index 20f634ac2eec..c66c0ad4a008 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java @@ -87,6 +87,10 @@ public class MostSpecificResolutionTest extends LightDaemonAnalyzerTestCase { doTest(false); } + public void testNoReturnTypeResolutionForThrownException() throws Exception { + doTest(false); + } + private void doTest() { doTest(true); } From 7898108ccdaf8f37282029839483492250ee3813 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 22 Apr 2014 13:05:30 +0200 Subject: [PATCH 26/86] testdata: ensure lambda can't be inferred from type parameter --- .../newLambda/OnlyLambdaAtTypeParameterPlace.java | 13 +++++++++++++ .../daemon/lambda/NewLambdaHighlightingTest.java | 4 ++++ 2 files changed, 17 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/OnlyLambdaAtTypeParameterPlace.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/OnlyLambdaAtTypeParameterPlace.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/OnlyLambdaAtTypeParameterPlace.java new file mode 100644 index 000000000000..aee4c8462cdf --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/OnlyLambdaAtTypeParameterPlace.java @@ -0,0 +1,13 @@ +class Test { + interface I { + void m(); + } + + void call(T t) {} + void call1(T t) {} + + { + call(() -> {}); + call1(() -> {}); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index 5e21a82fa200..3f4d1802e588 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -198,6 +198,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testOnlyLambdaAtTypeParameterPlace() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } From d5107d652fe5a758a834cd70ec782365a32729bb Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 22 Apr 2014 13:26:20 +0200 Subject: [PATCH 27/86] testdata: ensure intersection type is not missed during inference --- .../newLambda/LiftedIntersectionType.java | 22 +++++++++++++++++++ .../lambda/NewLambdaHighlightingTest.java | 4 ++++ 2 files changed, 26 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/LiftedIntersectionType.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/LiftedIntersectionType.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/LiftedIntersectionType.java new file mode 100644 index 000000000000..de9d517da449 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/LiftedIntersectionType.java @@ -0,0 +1,22 @@ +class Test { + + interface A { + A f(); + } + interface B {} + + static abstract class C implements A, B {} + static abstract class D implements A, B {} + + interface I { + T m(T arg); + } + + void bar(C c) { + foo(c, x -> x.f()); + foo(c, x -> x); + } + + void foo(T t1, I t3) {} + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index 3f4d1802e588..f5f286a17e31 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -202,6 +202,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testLiftedIntersectionType() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } From 2c49817e261dcaf39a8333321d38d425b8cd4609 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 22 Apr 2014 13:37:47 +0200 Subject: [PATCH 28/86] NPE --- .../InputOutputConstraintFormula.java | 5 +- ...edFunctionalInterfaceMethodReturnType.java | 22 ++++++++ ...lExpressionIncompleteHighlightingTest.java | 53 +++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/incomplete/MissedFunctionalInterfaceMethodReturnType.java create mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalExpressionIncompleteHighlightingTest.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java index 6ff17092dfd6..67097df574a0 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java @@ -65,7 +65,10 @@ public abstract class InputOutputConstraintFormula implements ConstraintFormula } } - collectReturnTypeVariables(session, psiExpression, substitutor.substitute(interfaceMethod.getReturnType()), result); + final PsiType returnType = interfaceMethod.getReturnType(); + if (returnType != null) { + collectReturnTypeVariables(session, psiExpression, substitutor.substitute(returnType), result); + } return result; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/incomplete/MissedFunctionalInterfaceMethodReturnType.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/incomplete/MissedFunctionalInterfaceMethodReturnType.java new file mode 100644 index 000000000000..ed1ab55f7fa2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/incomplete/MissedFunctionalInterfaceMethodReturnType.java @@ -0,0 +1,22 @@ +class Test { + + interface A { + A f(); + } + interface B {} + + static abstract class C implements A, B {} + static abstract class D implements A, B {} + + interface I { + m(T arg); + } + + void bar(C c) { + foo(c, x -> x.f()); + foo(c, x -> x); + } + + void foo(T t1, I t3) {} + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalExpressionIncompleteHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalExpressionIncompleteHighlightingTest.java new file mode 100644 index 000000000000..3d609159404a --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalExpressionIncompleteHighlightingTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.daemon.lambda; + +import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; +import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.testFramework.IdeaTestUtil; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class FunctionalExpressionIncompleteHighlightingTest extends LightDaemonAnalyzerTestCase { + @NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/incomplete"; + + @NotNull + @Override + protected LocalInspectionTool[] configureLocalInspectionTools() { + return new LocalInspectionTool[]{ + new UnusedSymbolLocalInspection(), + }; + } + + public void testMissedFunctionalInterfaceMethodReturnType() throws Exception { + doTest(); + } + + private void doTest() { + doTest(false); + } + + private void doTest(final boolean checkWarnings) { + doTestNewInference(BASE_PATH + "/" + getTestName(false) + ".java", checkWarnings, false); + } + + @Override + protected Sdk getProjectJDK() { + return IdeaTestUtil.getMockJdk18(); + } +} From 0da9f91eecdd7e63c8969f3bbdde336278412c14 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 22 Apr 2014 14:19:44 +0200 Subject: [PATCH 29/86] testdata: ensure overload resolution prefer correct one from methods with boxed types --- .../BoxingAndOverloadResolution.java | 33 +++++++++++++++++++ .../lambda/MostSpecificResolutionTest.java | 4 +++ 2 files changed, 37 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/BoxingAndOverloadResolution.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/BoxingAndOverloadResolution.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/BoxingAndOverloadResolution.java new file mode 100644 index 000000000000..36db3014c415 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/BoxingAndOverloadResolution.java @@ -0,0 +1,33 @@ +class Test { + private static void m(int i) {System.out.println(i);} + private static void m(Integer i) {System.out.println(i);} + + interface I { + void foo(int p); + } + + static { + I s = Test::m; + System.out.println(s); + } +} + +class Test2 { + + static void m(Integer i) { } + + interface I1 { + void m(int x); + } + + interface I2 { + void m(Integer x); + } + + static void call(I1 i1) { System.out.println(i1); } + static void call(I2 i2) { System.out.println(i2); } + + static { + call(Test2::m); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java index c66c0ad4a008..e2a14117d4f2 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MostSpecificResolutionTest.java @@ -91,6 +91,10 @@ public class MostSpecificResolutionTest extends LightDaemonAnalyzerTestCase { doTest(false); } + public void testBoxingAndOverloadResolution() throws Exception { + doTest(); + } + private void doTest() { doTest(true); } From 7d74b9dcf182efc1ad16636270ae38c2c16d761a Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 22 Apr 2014 15:20:33 +0200 Subject: [PATCH 30/86] NPE --- .../source/tree/java/MethodReferenceResolver.java | 2 +- .../tree/java/PsiMethodReferenceExpressionImpl.java | 4 +--- .../MissedFunctionalInterfaceMethodReturnType.java | 13 +++++++++++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java index cf25710008bc..fb6f831fe6b6 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java @@ -175,7 +175,7 @@ class MethodReferenceResolver implements ResolveCache.PolyVariantResolver void foo(T t1, I t3) {} } + +class Test2 { + + interface F { + m(); + } + + void g() {} + + { + F f = this::g; + } +} From 8bad8079f669d9457ecf9256f544fe9967814f73 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 22 Apr 2014 16:16:11 +0200 Subject: [PATCH 31/86] lambda: do not skip generic method when non-generic method exist in the same class --- .../intellij/psi/LambdaHighlightingUtil.java | 4 +-- .../src/com/intellij/psi/LambdaUtil.java | 30 ++++++++++++------- .../GenericNotGenericInterfaceMethod.java | 27 +++++++++++++++++ ...aceMayBeAnnotatedFunctionalInspection.java | 2 +- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java index 8dc811e6258d..503328ab46c5 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java @@ -36,7 +36,7 @@ public class LambdaHighlightingUtil { @Nullable public static String checkInterfaceFunctional(@NotNull PsiClass psiClass, String interfaceNonFunctionalMessage) { if (psiClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference - final List signatures = LambdaUtil.findFunctionCandidates(psiClass); + final List signatures = LambdaUtil.findFunctionCandidates(psiClass); if (signatures == null) return interfaceNonFunctionalMessage; if (signatures.isEmpty()) return "No target method found"; if (signatures.size() == 1) { @@ -113,7 +113,7 @@ public class LambdaHighlightingUtil { final PsiClass aClass = resolveResult.getElement(); if (aClass != null) { if (aClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference - final List signatures = LambdaUtil.findFunctionCandidates(aClass); + final List signatures = LambdaUtil.findFunctionCandidates(aClass); if (signatures != null && signatures.size() == 1) { final MethodSignature functionalMethod = signatures.get(0); if (functionalMethod.getTypeParameters().length > 0) return "Target method is generic"; diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index 09b9cdd48e64..fcf5e8945e7a 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -112,7 +112,7 @@ public class LambdaUtil { public static boolean isFunctionalClass(PsiClass aClass) { if (aClass != null) { if (aClass instanceof PsiTypeParameter) return false; - final List signatures = findFunctionCandidates(aClass); + final List signatures = findFunctionCandidates(aClass); return signatures != null && signatures.size() == 1; } return false; @@ -142,7 +142,7 @@ public class LambdaUtil { @Nullable static MethodSignature getFunction(PsiClass psiClass) { if (psiClass == null) return null; - final List functions = findFunctionCandidates(psiClass); + final List functions = findFunctionCandidates(psiClass); if (functions != null && functions.size() == 1) { return functions.get(0); } @@ -176,13 +176,13 @@ public class LambdaUtil { } @Nullable - private static List hasSubsignature(List signatures) { - for (MethodSignature signature : signatures) { + private static List hasSubsignature(List signatures) { + for (HierarchicalMethodSignature signature : signatures) { boolean subsignature = true; - for (MethodSignature methodSignature : signatures) { + for (HierarchicalMethodSignature methodSignature : signatures) { if (!signature.equals(methodSignature)) { - if (!MethodSignatureUtil.isSubsignature(signature, methodSignature) && - methodSignature.getTypeParameters().length == 0) { + if (!MethodSignatureUtil.isSubsignature(signature, methodSignature) && + !skipMethod(signature, methodSignature)) { subsignature = false; break; } @@ -193,10 +193,20 @@ public class LambdaUtil { return signatures; } + private static boolean skipMethod(HierarchicalMethodSignature signature, + HierarchicalMethodSignature methodSignature) { + //not generic + if (methodSignature.getTypeParameters().length == 0) { + return false; + } + //foreign class + return signature.getMethod().getContainingClass() != methodSignature.getMethod().getContainingClass(); + } + @Nullable - public static List findFunctionCandidates(PsiClass psiClass) { + public static List findFunctionCandidates(PsiClass psiClass) { if (psiClass != null && psiClass.isInterface() && !psiClass.isAnnotationType()) { - final List methods = new ArrayList(); + final List methods = new ArrayList(); final Collection visibleSignatures = psiClass.getVisibleSignatures(); for (HierarchicalMethodSignature signature : visibleSignatures) { final PsiMethod psiMethod = signature.getMethod(); @@ -364,7 +374,7 @@ public class LambdaUtil { @Nullable private static PsiType extractFunctionalConjunct(PsiIntersectionType type) { PsiType conjunct = null; - for (PsiType conjunctType : ((PsiIntersectionType)type).getConjuncts()) { + for (PsiType conjunctType : type.getConjuncts()) { final PsiMethod interfaceMethod = getFunctionalInterfaceMethod(conjunctType); if (interfaceMethod != null) { if (conjunct != null && !conjunct.equals(conjunctType)) return null; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/GenericNotGenericInterfaceMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/GenericNotGenericInterfaceMethod.java index 9cb75abb0c80..71b286a5268e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/GenericNotGenericInterfaceMethod.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/GenericNotGenericInterfaceMethod.java @@ -14,3 +14,30 @@ class Test { C c = ()-> {}; } } + +class Test1 { + + interface F { + void m(); + } + + { + F f = this::g; + } + + void g() {} +} + +class Test2 { + + interface F { + void m(); + void a(); + } + + { + F f = () -> g(); + } + + void g() {} +} diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java index e4f77e0fbea9..b9f43f708b77 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java @@ -75,7 +75,7 @@ public class InterfaceMayBeAnnotatedFunctionalInspection extends BaseInspection if (LambdaHighlightingUtil.checkInterfaceFunctional(aClass) != null) { return; } - final List candidates = LambdaUtil.findFunctionCandidates(aClass); + final List candidates = LambdaUtil.findFunctionCandidates(aClass); if (candidates == null || candidates.size() != 1) { return; } From 57e886f7a4841a50ed74be84d696b805ec1ffd69 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 22 Apr 2014 16:28:00 +0200 Subject: [PATCH 32/86] testdata: check that method ref on static interface method is accepted --- .../newMethodRef/RefOnStaticInterfaceMethod.java | 13 +++++++++++++ .../daemon/lambda/NewMethodRefHighlightingTest.java | 4 ++++ 2 files changed, 17 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/RefOnStaticInterfaceMethod.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/RefOnStaticInterfaceMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/RefOnStaticInterfaceMethod.java new file mode 100644 index 000000000000..6687f96d69a1 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/RefOnStaticInterfaceMethod.java @@ -0,0 +1,13 @@ +interface I { + static void a() {} +} + +interface J { + void foo(); +} + +class Test { + { + J j = I::a; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java index 54ee87c1af8b..9c79eb6dd2f0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java @@ -237,6 +237,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testRefOnStaticInterfaceMethod() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } From 2b8e2e885a0da58c16c0c9f5d93862cb2f44b4bd Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 22 Apr 2014 17:25:59 +0200 Subject: [PATCH 33/86] add unchecked warning calls also for method references --- .../UncheckedWarningLocalInspectionBase.java | 17 +++++++++++++++-- .../tree/java/MethodReferenceResolver.java | 6 +++++- .../lambda/newMethodRef/AfterDistinctOps.java | 2 +- .../newMethodRef/UncheckedMethodReference.java | 15 +++++++++++++++ .../lambda/NewMethodRefHighlightingTest.java | 4 ++++ 5 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/UncheckedMethodReference.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java index 83fd6c56f28d..fa2789880371 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java @@ -198,6 +198,18 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe } } + @Override + public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) { + super.visitMethodReferenceExpression(expression); + if (IGNORE_UNCHECKED_CALL) return; + final JavaResolveResult result = expression.advancedResolve(false); + final String description = getUncheckedCallDescription(result); + if (description != null) { + final PsiElement referenceNameElement = expression.getReferenceNameElement(); + registerProblem(description, referenceNameElement != null ? referenceNameElement : expression, myGenerifyFixes); + } + } + @Override public void visitCallExpression(PsiCallExpression callExpression) { super.visitCallExpression(callExpression); @@ -383,8 +395,9 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe @Nullable private String getUncheckedCallDescription(JavaResolveResult resolveResult) { - final PsiMethod method = (PsiMethod)resolveResult.getElement(); - if (method == null) return null; + final PsiElement element = resolveResult.getElement(); + if (!(element instanceof PsiMethod)) return null; + final PsiMethod method = (PsiMethod)element; final PsiSubstitutor substitutor = resolveResult.getSubstitutor(); if (!PsiUtil.isRawSubstitutor(method, substitutor)) return null; final PsiParameter[] parameters = method.getParameterList().getParameters(); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java index fb6f831fe6b6..62ddc0d97722 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java @@ -156,7 +156,11 @@ class MethodReferenceResolver implements ResolveCache.PolyVariantResolver void f() { - TerminalOp> reduceOp = BBB.>makeRef(LinkedHashSet::new, LinkedHashSet::add, LinkedHashSet::addAll); + TerminalOp> reduceOp = BBB.>makeRef(LinkedHashSet::new, LinkedHashSet::add, LinkedHashSet::addAll); } public static TerminalOp makeRef(U seed, BiFunction reducer, BinaryOperator combiner) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/UncheckedMethodReference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/UncheckedMethodReference.java new file mode 100644 index 000000000000..4b451f2eed9b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/UncheckedMethodReference.java @@ -0,0 +1,15 @@ +import java.util.*; + +class Test { + + interface I { + void m(List l, T el); + } + + { + I i1 = List::add; + System.out.println(i1); + I i2 = List::add; + System.out.println(i2); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java index 9c79eb6dd2f0..4dbe40750de2 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java @@ -241,6 +241,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testUncheckedMethodReference() throws Exception { + doTest(true); + } + private void doTest() { doTest(false); } From 5f295fe7017063aad06508bf7e0e66e58f445e6c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 22 Apr 2014 20:27:38 +0200 Subject: [PATCH 34/86] do not cancel offline inspections --- .../codeInspection/ex/GlobalInspectionContextImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java index 940f2dec3606..d8a3a82f9150 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -329,6 +329,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp tool.inspectionStarted(inspectionManager, this, getPresentation(toolWrapper)); } + final boolean headlessEnvironment = ApplicationManager.getApplication().isHeadlessEnvironment(); final Map map = getInspectionWrappersMap(localTools); scope.accept(new PsiElementVisitor() { @Override @@ -336,7 +337,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp final VirtualFile virtualFile = file.getVirtualFile(); if (virtualFile == null) return; - if (myView == null) { + if (myView == null && !headlessEnvironment) { throw new ProcessCanceledException(); } From c2067ff719b87f5b2cf378a7ff5d3e3095d6f45b Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Tue, 22 Apr 2014 23:13:13 +0400 Subject: [PATCH 35/86] PY-1194 Provide completion and navigation for url tag in django template PY-3591 Support {% url %} tag arguments completion Params to be supported --- .../jetbrains/python/FunctionParameter.java | 21 ++++++++++++++++ .../jetbrains/python/psi/PyArgumentList.java | 10 ++++++++ .../python/psi/impl/PyArgumentListImpl.java | 25 ++++++++++++++++--- 3 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 python/psi-api/src/com/jetbrains/python/FunctionParameter.java diff --git a/python/psi-api/src/com/jetbrains/python/FunctionParameter.java b/python/psi-api/src/com/jetbrains/python/FunctionParameter.java new file mode 100644 index 000000000000..bceba9efc24b --- /dev/null +++ b/python/psi-api/src/com/jetbrains/python/FunctionParameter.java @@ -0,0 +1,21 @@ +package com.jetbrains.python; + +import org.jetbrains.annotations.Nullable; + +/** + * This class (possibly enum) represents function parameter + * + * @author Ilya.Kazakevich + */ +public interface FunctionParameter { + /** + * @return parameter position + */ + int getPosition(); + + /** + * @return parameter name (if known) + */ + @Nullable + String getName(); +} diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java b/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java index f89f25fdf2d2..0a1a9c325f0a 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java @@ -16,6 +16,7 @@ package com.jetbrains.python.psi; import com.intellij.lang.ASTNode; +import com.jetbrains.python.FunctionParameter; import com.jetbrains.python.psi.resolve.PyResolveContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -78,4 +79,13 @@ public interface PyArgumentList extends PyElement { @Nullable ASTNode getClosingParen(); + + /** + * Searches parameter value and returns it if exists. + * + * @param parameter param to search + * @return function parameter value expression or null if does not exist + */ + @Nullable + PyExpression getValueExpressionForParam(@NotNull FunctionParameter parameter); } diff --git a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java index 2e6120a29303..d0c83cc65957 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java @@ -27,6 +27,7 @@ import com.jetbrains.NotNullPredicate; import com.jetbrains.python.PyElementTypes; import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.PythonDialectsTokenSetProvider; +import com.jetbrains.python.FunctionParameter; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.resolve.PyResolveContext; import org.jetbrains.annotations.NotNull; @@ -203,7 +204,6 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList catch (IncorrectOperationException e1) { throw new IllegalStateException(e1); } - } else { getNode().addChild(arg.getNode(), par); @@ -214,7 +214,7 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList public ASTNode getClosingParen() { ASTNode node = getNode(); final ASTNode[] children = node.getChildren(TokenSet.create(PyTokenTypes.RPAR)); - return children.length == 0 ? null : children[children.length-1]; + return children.length == 0 ? null : children[children.length - 1]; } private void addArgumentNode(PyExpression arg, ASTNode beforeThis, boolean commaFirst) { @@ -256,14 +256,12 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList // 1: Nothing, just add addArgumentNode(argument, node, true); break; - } else if (PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens().contains(type)) { // 2: After some argument followed by comma: after comma, add element, add comma // 3: After some argument not followed by comma: add comma, add element addArgumentNode(argument, node, true); break; - } else if (type == PyTokenTypes.COMMA) { ASTNode next = PyUtil.getNextNonWhitespace(node); @@ -333,4 +331,23 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList return (PsiTreeUtil.getParentOfType(input, PyKeywordArgument.class) == null) && !(input instanceof PyKeywordArgument); } } + + @Nullable + @Override + public PyExpression getValueExpressionForParam(@NotNull final FunctionParameter parameter) { + final String parameterName = parameter.getName(); + if (parameterName != null) { + final PyKeywordArgument kwarg = getKeywordArgument(parameterName); + if (kwarg != null) { + return kwarg.getValueExpression(); + } + } + + final PyExpression[] arguments = getArguments(); + if (arguments.length > parameter.getPosition()) { + return arguments[parameter.getPosition()]; + } + + return null; + } } From 4a12b1faf99d81b754286143e7b36b4f07e6a899 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 22 Apr 2014 21:17:54 +0200 Subject: [PATCH 36/86] junit: workaround for old junit versions (IDEA-124201) --- .../com/intellij/junit4/JUnit4TestRunnerUtil.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java index 565f6211dbf7..4862015d9df5 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java @@ -123,12 +123,13 @@ public class JUnit4TestRunnerUtil { final Class clazz = loadTestClass(suiteClassName.substring(0, index)); final String methodName = suiteClassName.substring(index + 1); final RunWith clazzAnnotation = (RunWith)clazz.getAnnotation(RunWith.class); + final Description testMethodDescription = Description.createTestDescription(clazz, methodName); if (clazzAnnotation == null) { //do not override external runners try { final Method method = clazz.getMethod(methodName, null); if (method != null && notForked && (method.getAnnotation(Ignore.class) != null || clazz.getAnnotation(Ignore.class) != null)) { //override ignored case only final Request classRequest = createIgnoreIgnoredClassRequest(clazz, true); - final Filter ignoredTestFilter = Filter.matchMethodDescription(Description.createTestDescription(clazz, methodName)); + final Filter ignoredTestFilter = Filter.matchMethodDescription(testMethodDescription); return classRequest.filterWith(new Filter() { public boolean shouldRun(Description description) { return ignoredTestFilter.shouldRun(description); @@ -151,13 +152,20 @@ public class JUnit4TestRunnerUtil { } try { if (clazz.getMethod("suite", new Class[0]) != null && !methodName.equals("suite")) { - return Request.classWithoutSuiteMethod(clazz).filterWith(Description.createTestDescription(clazz, methodName)); + return Request.classWithoutSuiteMethod(clazz).filterWith(testMethodDescription); } } catch (Throwable e) { //ignore } - final Filter methodFilter = Filter.matchMethodDescription(Description.createTestDescription(clazz, methodName)); + + final Filter methodFilter; + try { + methodFilter = Filter.matchMethodDescription(testMethodDescription); + } + catch (NoSuchMethodError e) { + return Request.method(clazz, methodName); + } return Request.aClass(clazz).filterWith(new Filter() { public boolean shouldRun(Description description) { if (description.isTest() && description.getDisplayName().startsWith("warning(junit.framework.TestSuite$")) { From 13bf7e11356a1bc582b8783b52ce04d30495a8a2 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Tue, 22 Apr 2014 22:49:22 +0400 Subject: [PATCH 37/86] cleanup --- .../src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java index 12cbd129f6c1..4c093211cfd6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java @@ -84,9 +84,9 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat RoamingType.PER_USER); Keymap[] keymaps = defaultKeymap.getKeymaps(); + String systemDefaultKeymap = defaultKeymap.getDefaultKeymapName(); for (Keymap keymap : keymaps) { addKeymap(keymap); - String systemDefaultKeymap = defaultKeymap.getDefaultKeymapName(); if (systemDefaultKeymap.equals(keymap.getName())) { setActiveKeymap(keymap); } From 3541938c9baa02cb82bf203f97330d9fb102bfd2 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Tue, 22 Apr 2014 22:50:00 +0400 Subject: [PATCH 38/86] introduce beforeOKAction() --- .../ide/customize/AbstractCustomizeWizardStep.java | 7 ++++++- .../intellij/ide/customize/CustomizeIDEWizardDialog.java | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/customize/AbstractCustomizeWizardStep.java b/platform/platform-impl/src/com/intellij/ide/customize/AbstractCustomizeWizardStep.java index 5b57ca8d4787..3df11563b30a 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/AbstractCustomizeWizardStep.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/AbstractCustomizeWizardStep.java @@ -35,7 +35,8 @@ public abstract class AbstractCustomizeWizardStep extends JPanel { protected abstract String getHTMLFooter(); - private static Color getSelectionBackground() { + @NotNull + protected static Color getSelectionBackground() { return ColorUtil.mix(UIUtil.getListSelectionBackground(), UIUtil.getLabelBackground(), .75); } @@ -75,4 +76,8 @@ public abstract class AbstractCustomizeWizardStep extends JPanel { public void beforeShown(boolean forward) { } + + public boolean beforeOkAction() { + return true; + } } diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java index 986c533bcb75..47eecc092162 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java @@ -141,6 +141,9 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis @Override protected void doOKAction() { + for (AbstractCustomizeWizardStep step : mySteps) { + if (!step.beforeOkAction()) return; + } try { PluginManager.saveDisabledPlugins(PluginGroups.getInstance().getDisabledPluginIds(), false); } From 97ade8df9d996a67b74b2c1be1174d0cee6635ac Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Tue, 22 Apr 2014 23:45:47 +0400 Subject: [PATCH 39/86] ability to enable only visible components --- platform/util/src/com/intellij/util/ui/UIUtil.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 59272d4d93c0..2195ede58d47 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -384,6 +384,10 @@ public class UIUtil { } public static void setEnabled(Component component, boolean enabled, boolean recursively) { + setEnabled(component, enabled, recursively, false); + } + + public static void setEnabled(Component component, boolean enabled, boolean recursively, boolean visibleOnly) { component.setEnabled(enabled); if (component instanceof JComboBox && isUnderAquaLookAndFeel()) { // On Mac JComboBox instances have children: com.apple.laf.AquaComboBoxButton and javax.swing.CellRendererPane. @@ -401,7 +405,9 @@ public class UIUtil { final Container container = (Container)component; final int subComponentCount = container.getComponentCount(); for (int i = 0; i < subComponentCount; i++) { - setEnabled(container.getComponent(i), enabled, recursively); + Component child = container.getComponent(i); + if (visibleOnly && !child.isVisible()) continue; + setEnabled(child, enabled, recursively, visibleOnly); } } } From ebe62cf7b56aca6e934d8b4f8188998836bc21c3 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Tue, 22 Apr 2014 23:46:24 +0400 Subject: [PATCH 40/86] customize password field labels --- .../providers/masterKey/PasswordComponentBase.form | 4 ++-- .../providers/masterKey/PasswordComponentBase.java | 3 +++ .../providers/masterKey/ResetPasswordComponent.java | 11 ++++++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordComponentBase.form b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordComponentBase.form index 05b66821b0f4..083237ad092d 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordComponentBase.form +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordComponentBase.form @@ -49,7 +49,7 @@ - + @@ -103,7 +103,7 @@ - + diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordComponentBase.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordComponentBase.java index 903811f53e72..2307fa9464f1 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordComponentBase.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordComponentBase.java @@ -41,6 +41,8 @@ public abstract class PasswordComponentBase { protected JPasswordField myNewPasswordField; protected JPasswordField myConfirmPasswordField; protected JCheckBox myEncryptCheckBox; + protected JLabel myPasswordLabel; + protected JLabel myNewPasswordLabel; public PasswordComponentBase(@NotNull MasterKeyPasswordSafe safe, @NotNull String title) { @@ -48,6 +50,7 @@ public abstract class PasswordComponentBase { myTitle = title; myIconLabel.setText(""); myIconLabel.setIcon(AllIcons.General.PasswordLock); + myIconLabel.setDisabledIcon(AllIcons.General.PasswordLock); //myPromptLabel.setUI(new MultiLineLabelUI()); myPromptLabel.setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL)); diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/ResetPasswordComponent.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/ResetPasswordComponent.java index b645f25894ef..ce75bdb2165a 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/ResetPasswordComponent.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/ResetPasswordComponent.java @@ -18,6 +18,7 @@ package com.intellij.ide.passwordSafe.impl.providers.masterKey; import com.intellij.ide.passwordSafe.HelpID; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.util.ui.DialogUtil; import com.intellij.util.ui.UIUtil; /** @@ -28,13 +29,17 @@ public class ResetPasswordComponent extends PasswordComponentBase { private final boolean myFirstTime; public ResetPasswordComponent(MasterKeyPasswordSafe safe, boolean firstTime) { - super(safe, "Reset"); + super(safe, firstTime ? "Setup" : "Reset"); myFirstTime = firstTime; UIUtil.setEnabled(myPasswordPanel, false, true); myPasswordPanel.setVisible(false); if (firstTime) { - myPromptLabel.setText("
    Specify the password for the password database.
    " + - "Leave blank to disable the master password."); + myNewPasswordLabel.setText(myPasswordLabel.getText()); + myNewPasswordLabel.setDisplayedMnemonic(myPasswordLabel.getDisplayedMnemonic()); + myNewPasswordLabel.setDisplayedMnemonicIndex(myPasswordLabel.getDisplayedMnemonicIndex()); + DialogUtil.registerMnemonic(myPasswordLabel, null); + myPromptLabel.setText("
    Specify the new password for the password database.
    " + + "Leave blank to disable the master password protection."); } else { myPromptLabel.setText("
    The password for the password database will be reset.
    " + From f5e72157d81e296f66f877082b3a6f828e1b6f63 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 23 Apr 2014 09:02:57 +0200 Subject: [PATCH 41/86] do not rely on memory index storage isBufferedFlag to process physical file contents --- .../src/com/intellij/util/indexing/FileBasedIndexImpl.java | 5 +++++ .../src/com/intellij/util/indexing/MapReduceIndex.java | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index f739815735d3..f3afcf241190 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -1792,6 +1792,9 @@ public class FileBasedIndexImpl extends FileBasedIndex { final UpdatableIndex index = getIndex(indexId); assert index != null; + if (currentFC != null && currentFC.getUserData(ourPhysicalContentKey) == null) { + currentFC.putUserData(ourPhysicalContentKey, Boolean.TRUE); + } // important: no hard referencing currentFC to avoid OOME, the methods introduced for this purpose! final Computable update = index.update(inputId, currentFC); @@ -1801,6 +1804,8 @@ public class FileBasedIndexImpl extends FileBasedIndex { ); } + static final Key ourPhysicalContentKey = Key.create("physical.content.flag"); + @NotNull private Runnable createIndexedStampUpdateRunnable(@NotNull final ID indexId, @NotNull final VirtualFile file, diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java index 77fded840d3d..ad21d381530f 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java @@ -286,7 +286,11 @@ public class MapReduceIndex implements UpdatableIndex> oldKeysGetter; final int savedInputId; - if (myHasSnapshotMapping && !((MemoryIndexStorage)getStorage()).isBufferingEnabled()) { + boolean weProcessPhysicalContent = content == null || + (content instanceof FileContent && + ((FileContent)content).getUserData(FileBasedIndexImpl.ourPhysicalContentKey) != null); + + if (myHasSnapshotMapping && weProcessPhysicalContent) { try { // optimistically (out of index update write section) read current snapshot keys for file final Integer hashId = myInputsSnapshotMapping.get(inputId); final Collection keys = hashId != null ? mySnapshotMapping.get(hashId): null; From 152c2307d6a6dc100fe78ee73022b452c649be08 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 23 Apr 2014 09:28:48 +0200 Subject: [PATCH 42/86] Platform: Local History can survive for more than 30 days now --- .../src/com/intellij/history/integration/LocalHistoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java index 632f549d5983..8660084a572b 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java @@ -128,7 +128,7 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone public void disposeComponent() { if (!isInitialized.getAndSet(false)) return; - int period = Registry.intValue("localHistory.daysToKeep") * 1000 * 60 * 60 * 24; + long period = Registry.intValue("localHistory.daysToKeep") * 1000 * 60 * 60 * 24; VirtualFileManager fm = VirtualFileManager.getInstance(); fm.removeVirtualFileListener(myEventDispatcher); From 9df7136b7c756d17e931f3042f90b2f2642f753f Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Wed, 23 Apr 2014 12:32:43 +0400 Subject: [PATCH 43/86] Gradle: installer build fix --- build/scripts/layouts.gant | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 10d8907de3fa..9f0485eb20af 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -344,10 +344,6 @@ public def layoutCommunityPlugins(String home) { jar("gradle-tooling-extension-impl.jar") { module("gradle-tooling-extension-impl") } - - jar("gradle-tooling-extension.jar") { - module("gradle-tooling-extension") - } fileset(dir: "$home/plugins/gradle/lib") { include(name: "*.jar") } } From d0c6ef5cc278ea603974ff023843447a81a955ea Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 23 Apr 2014 11:49:27 +0400 Subject: [PATCH 44/86] cleanup --- .../src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index 289b31e95e2b..5d301599395d 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -394,7 +394,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { public Void compute() { if (myManager.getProject().isDisposed()) throw new ProcessCanceledException(); List psiRoots = file.getViewProvider().getAllFiles(); - Set processed = new THashSet(psiRoots.size() * 2, (float)0.5); + Set processed = new THashSet(psiRoots.size() * 2, (float)0.5); for (final PsiFile psiRoot : psiRoots) { checkCanceled(progress); assert psiRoot != null : "One of the roots of file " + file + " is null. All roots: " + psiRoots + "; ViewProvider: " + From 7269bce662728b0c385b1c02933824b296d16528 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 23 Apr 2014 12:17:43 +0400 Subject: [PATCH 45/86] drain file type detection queue in tests --- .../fileTypes/impl/FileTypeManagerImpl.java | 5 ++- .../testFramework/LightPlatformTestCase.java | 34 +++++++++++++------ .../testFramework/PlatformTestCase.java | 4 ++- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java index ce9a004301b6..8e09e72cddb8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java @@ -58,6 +58,7 @@ import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import javax.swing.*; import java.io.*; @@ -264,7 +265,9 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME return true; } }); - void drainReDetectQueue() { + + @TestOnly + public void drainReDetectQueue() { reDetectQueue.drain(); } diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java index 5065b9d6df3a..42e7c7057962 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java @@ -50,6 +50,7 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl; import com.intellij.openapi.module.EmptyModuleType; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; @@ -337,18 +338,29 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da @Override protected void setUp() throws Exception { - super.setUp(); - initApplication(); - ourApplication.setDataProvider(this); - doSetup(new SimpleLightProjectDescriptor(getModuleType(), getProjectJDK()), configureLocalInspectionTools(), myAvailableInspectionTools); - InjectedLanguageManagerImpl.pushInjectors(getProject()); + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + @Override + public void run() { + try { + LightPlatformTestCase.super.setUp(); + initApplication(); + ourApplication.setDataProvider(LightPlatformTestCase.this); + doSetup(new SimpleLightProjectDescriptor(getModuleType(), getProjectJDK()), configureLocalInspectionTools(), + myAvailableInspectionTools); + InjectedLanguageManagerImpl.pushInjectors(getProject()); - storeSettings(); + storeSettings(); - myThreadTracker = new ThreadTracker(); - ModuleRootManager.getInstance(ourModule).orderEntries().getAllLibrariesAndSdkClassesRoots(); - VirtualFilePointerManagerImpl filePointerManager = (VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance(); - filePointerManager.storePointers(); + myThreadTracker = new ThreadTracker(); + ModuleRootManager.getInstance(ourModule).orderEntries().getAllLibrariesAndSdkClassesRoots(); + VirtualFilePointerManagerImpl filePointerManager = (VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance(); + filePointerManager.storePointers(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + }); } public static void doSetup(@NotNull LightProjectDescriptor descriptor, @@ -444,6 +456,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da assertEmpty("There are unsaved documents", Arrays.asList(unsavedDocuments)); } + ((FileTypeManagerImpl)FileTypeManager.getInstance()).drainReDetectQueue(); } // todo: use Class once on Java 7 @@ -521,6 +534,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da } public static void doTearDown(@NotNull final Project project, IdeaTestApplication application, boolean checkForEditors) throws Exception { + ((FileTypeManagerImpl)FileTypeManager.getInstance()).drainReDetectQueue(); DocumentCommitThread.getInstance().clearQueue(); CodeStyleSettingsManager.getInstance(project).dropTemporarySettings(); checkAllTimersAreDisposed(); diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java index 7f8e7438cc13..c72ff350db89 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java @@ -35,6 +35,8 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.event.DocumentListener; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl; import com.intellij.openapi.module.EmptyModuleType; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; @@ -68,7 +70,6 @@ import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.impl.DocumentCommitThread; import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl; -import com.intellij.util.PatchedWeakReference; import com.intellij.util.PlatformUtils; import com.intellij.util.indexing.IndexableSetContributor; import com.intellij.util.indexing.IndexedRootsProvider; @@ -228,6 +229,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro LightPlatformTestCase.clearUncommittedDocuments(getProject()); runStartupActivities(); + ((FileTypeManagerImpl)FileTypeManager.getInstance()).drainReDetectQueue(); } protected Project doCreateProject(File projectFile) throws Exception { From 46fea0f5d6b323fc31bec058614088cae84b7ae3 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 23 Apr 2014 12:22:30 +0400 Subject: [PATCH 46/86] fewer create/delete operations --- .../intellij/openapi/util/io/FileUtilRt.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java index ebf271c4bc8f..1ce5fb4bff9e 100644 --- a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java +++ b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java @@ -193,14 +193,11 @@ public class FileUtilRt { public static File createTempDirectory(@NotNull File dir, @NotNull @NonNls String prefix, @Nullable @NonNls String suffix, boolean deleteOnExit) throws IOException { - File file = doCreateTempFile(dir, prefix, suffix); + File file = doCreateTempFile(dir, prefix, suffix, true); if (deleteOnExit) { file.deleteOnExit(); } - if (!file.delete() && file.exists()) { - throw new IOException("Cannot delete file: " + file); - } - if (!file.mkdir() && !file.isDirectory()) { + if (!file.isDirectory()) { throw new IOException("Cannot create directory: " + file); } return file; @@ -235,7 +232,7 @@ public class FileUtilRt { public static File createTempFile(@NonNls File dir, @NotNull @NonNls String prefix, @Nullable @NonNls String suffix, boolean create, boolean deleteOnExit) throws IOException { - File file = doCreateTempFile(dir, prefix, suffix); + File file = doCreateTempFile(dir, prefix, suffix, false); if (deleteOnExit) { file.deleteOnExit(); } @@ -248,7 +245,10 @@ public class FileUtilRt { } @NotNull - private static File doCreateTempFile(@NotNull File dir, @NotNull @NonNls String prefix, @Nullable @NonNls String suffix) throws IOException { + private static File doCreateTempFile(@NotNull File dir, + @NotNull @NonNls String prefix, + @Nullable @NonNls String suffix, + boolean isDirectory) throws IOException { //noinspection ResultOfMethodCallIgnored dir.mkdirs(); @@ -262,7 +262,7 @@ public class FileUtilRt { int exceptionsCount = 0; while (true) { try { - final File temp = createTempFile(prefix, suffix, dir); + final File temp = createTemp(prefix, suffix, dir, isDirectory); return normalizeFile(temp); } catch (IOException e) { // Win32 createFileExclusively access denied @@ -274,7 +274,7 @@ public class FileUtilRt { } @NotNull - public static File createTempFile(@NotNull String prefix, @NotNull String suffix, @NotNull File directory) throws IOException { + private static File createTemp(@NotNull String prefix, @NotNull String suffix, @NotNull File directory, boolean isDirectory) throws IOException { // normalize and use only the file name from the prefix prefix = new File(prefix).getName(); File f; @@ -283,15 +283,15 @@ public class FileUtilRt { String name = prefix + (i==0?"":Integer.toString(i)) + suffix; f = new File(directory, name); if (!name.equals(f.getName())) { - throw new IOException("Unable to create temporary file, " + f); + throw new IOException("Unable to create temporary file, " + f+", "+name); } i++; } while (f.exists()); - if (!f.createNewFile()) { + boolean success = isDirectory ? f.mkdir() : f.createNewFile(); + if (!success) { throw new IOException("Unable to create temporary file " + f); } - return f; } From 60f2a36569667a46be611a7a03aaba5f1fa7b98e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 23 Apr 2014 12:23:09 +0400 Subject: [PATCH 47/86] perforce tests fixed --- .../impl/HeavyIdeaTestFixtureImpl.java | 12 ++++-- .../vcs/AbstractVcsTestCase.java | 9 +++-- .../vcs/impl/ProjectLevelVcsManagerImpl.java | 8 +++- .../openapi/vcs/impl/VcsInitialization.java | 40 +++++++++++++------ .../com/intellij/openapi/vcs/VcsTestUtil.java | 38 +++++++++++------- 5 files changed, 71 insertions(+), 36 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java index 3551da7fcd34..4adc2aa57cef 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,8 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; @@ -146,9 +148,9 @@ class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixtu new WriteCommandAction.Simple(null) { @Override protected void run() throws Throwable { - File projectFile = FileUtil.createTempFile(myName+"_", PROJECT_FILE_SUFFIX); - FileUtil.delete(projectFile); - myFilesToDelete.add(projectFile); + File tempDirectory = FileUtil.createTempDirectory(myName, ""); + File projectFile = new File(tempDirectory, myName + PROJECT_FILE_SUFFIX); + myFilesToDelete.add(tempDirectory); LocalFileSystem.getInstance().refreshAndFindFileByIoFile(projectFile); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); @@ -166,6 +168,7 @@ class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixtu ProjectManagerEx.getInstanceEx().openTestProject(myProject); LightPlatformTestCase.clearUncommittedDocuments(myProject); + ((FileTypeManagerImpl)FileTypeManager.getInstance()).drainReDetectQueue(); } }.execute().throwException(); } @@ -244,6 +247,7 @@ class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixtu } }.execute(); return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override public PsiFile compute() { return PsiManager.getInstance(getProject()).findFile(virtualFile[0]); } diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/AbstractVcsTestCase.java b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/AbstractVcsTestCase.java index 10a6bc58d9f3..4df8f9cdeb53 100644 --- a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/AbstractVcsTestCase.java +++ b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/AbstractVcsTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,7 @@ import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.annotate.AnnotationProvider; import com.intellij.openapi.vcs.annotate.FileAnnotation; import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.UsefulTestCase; @@ -95,7 +96,7 @@ public abstract class AbstractVcsTestCase { if (pluginName != null) { System.setProperty(key, pluginName); } - String name = getClass().getName() + "." + testName; + String name = testName; final TestFixtureBuilder testFixtureBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(name); myProjectFixture = testFixtureBuilder.getFixture(); testFixtureBuilder.addModule(EmptyModuleFixtureBuilder.class).addContentRoot(clientRoot.toString()); @@ -116,13 +117,15 @@ public abstract class AbstractVcsTestCase { assert myWorkingCopyDir != null; } }); - } finally { + } + finally { if (was != null) { System.setProperty(key, was); } else { System.clearProperty(key); } } + ((ProjectLevelVcsManagerImpl)ProjectLevelVcsManager.getInstance(myProject)).waitForInitialized(); } protected void projectCreated() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java index 87d7faab4523..904b070d2a57 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -72,6 +72,7 @@ import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import javax.swing.*; import java.awt.*; @@ -896,4 +897,9 @@ public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx impleme public ContentRevisionCache getContentRevisionCache() { return myContentRevisionCache; } + + @TestOnly + public void waitForInitialized() { + myInitialization.waitForInitialized(); + } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java index f0987ce8d228..498f3d1a5c28 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,32 +21,34 @@ import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.TestOnly; +import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.LinkedList; import java.util.List; +import java.util.concurrent.Future; public class VcsInitialization { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.impl.VcsInitialization"); - private final Project myProject; - private final List> myList; + private final List> myList = new ArrayList>(); private final Object myLock; private boolean myInitStarted; + private volatile Future myFuture; - public VcsInitialization(final Project project) { + public VcsInitialization(@NotNull final Project project) { myLock = new Object(); - myProject = project; - myList = new LinkedList>(); - StartupManager.getInstance(myProject).registerPostStartupActivity(new DumbAwareRunnable() { + StartupManager.getInstance(project).registerPostStartupActivity(new DumbAwareRunnable() { + @Override public void run() { - if (myProject.isDisposed()) return; - ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + if (project.isDisposed()) return; + myFuture = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { @Override public void run() { - if (!myProject.isDisposed()) { + if (!project.isDisposed()) { execute(); } } @@ -55,7 +57,7 @@ public class VcsInitialization { }); } - public void add(final VcsInitObject vcsInitObject, final Runnable runnable) { + public void add(@NotNull final VcsInitObject vcsInitObject, @NotNull final Runnable runnable) { synchronized (myLock) { if (myInitStarted) { if (! vcsInitObject.isCanBeLast()) { @@ -76,12 +78,24 @@ public class VcsInitialization { myInitStarted = true; // list would not be modified starting from this point } Collections.sort(list, new Comparator>() { + @Override public int compare(Pair o1, Pair o2) { - return new Integer(o1.getFirst().getOrder()).compareTo(new Integer(o2.getFirst().getOrder())); + return o1.getFirst().getOrder() - o2.getFirst().getOrder(); } }); for (Pair pair : list) { pair.getSecond().run(); } } + + @TestOnly + public void waitForInitialized() { + try { + myFuture.get(); + myFuture = null; + } + catch (Exception e) { + throw new RuntimeException(e); + } + } } diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/VcsTestUtil.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/VcsTestUtil.java index 51b6fdd1226e..63f54a8c15b5 100644 --- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/VcsTestUtil.java +++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/VcsTestUtil.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.openapi.vcs; import com.intellij.notification.Notification; @@ -54,24 +69,17 @@ public class VcsTestUtil { * @param name Name of the directory. * @return reference to the created or already existing directory. */ - public static VirtualFile createDir(@NotNull Project project, @NotNull final VirtualFile parent, @NotNull final String name) { - final Ref result = new Ref(); - new WriteCommandAction.Simple(project) { + public static VirtualFile createDir(@NotNull final Project project, @NotNull final VirtualFile parent, @NotNull final String name) { + return new WriteCommandAction(project) { @Override - protected void run() throws Throwable { - try { - VirtualFile dir = parent.findChild(name); - if (dir == null) { - dir = parent.createChildDirectory(this, name); - } - result.set(dir); - } - catch (IOException e) { - throw new RuntimeException(e); + protected void run(@NotNull Result result) throws Throwable { + VirtualFile dir = parent.findChild(name); + if (dir == null) { + dir = parent.createChildDirectory(this, name); } + result.setResult(dir); } - }.execute(); - return result.get(); + }.execute().throwException().getResultObject(); } public static void renameFileInCommand(@NotNull Project project, @NotNull final VirtualFile file, @NotNull final String newName) { From 06f574a1b2d8d5087b09c59400a5baaec9cbc65a Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 23 Apr 2014 12:32:44 +0400 Subject: [PATCH 48/86] readable toString() --- .../util/containers/ConcurrentBitSet.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentBitSet.java b/platform/util/src/com/intellij/util/containers/ConcurrentBitSet.java index cc134cd1be95..d7542a7c4289 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentBitSet.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentBitSet.java @@ -407,13 +407,21 @@ public class ConcurrentBitSet { StringBuilder b = new StringBuilder(); b.append('{'); - int i = nextSetBit(0); - if (i != -1) { - b.append(i); - for (i = nextSetBit(i + 1); i >= 0; i = nextSetBit(i + 1)) { - int endOfRun = nextClearBit(i); + for (int i = nextSetBit(0); i >= 0; i = nextSetBit(i + 1)) { + int endOfRun = nextClearBit(i); + if (endOfRun - i > 1) { + if (b.length() != 1) { + b.append(", "); + } + b.append(i).append("...").append(endOfRun-1); + i = endOfRun; + } + else { do { - b.append(", ").append(i); + if (b.length() != 1) { + b.append(", "); + } + b.append(i); } while (++i < endOfRun); } From 7cc124e5c2312ce0b526ef64540f431c390e58a6 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 23 Apr 2014 12:45:35 +0400 Subject: [PATCH 49/86] optimisation: avoid containingfile calculation --- .../completion/JavaCompletionContributor.java | 4 +- .../impl/source/codeStyle/ImportHelper.java | 6 +- .../codeStyle/JavaReferenceAdjuster.java | 3 +- .../impl/providers/JavaClassReference.java | 42 ++--- .../impl/source/tree/JavaTreeCopyHandler.java | 4 +- .../ClsJavaCodeReferenceElementImpl.java | 29 ++-- .../impl/source/PsiClassReferenceType.java | 7 +- .../PsiJavaCodeReferenceElementImpl.java | 164 +++++++++--------- .../impl/source/SourceJavaCodeReference.java | 6 +- .../resolve/ClassResolverProcessor.java | 10 +- .../impl/source/resolve/JavaResolveUtil.java | 4 +- .../source/resolve/PsiResolveHelperImpl.java | 5 +- .../impl/source/resolve/ResolveClassUtil.java | 9 +- .../resolve/VariableResolverProcessor.java | 14 +- .../psi/impl/source/tree/JavaSourceUtil.java | 5 +- .../impl/source/tree/JavaTreeGenerator.java | 2 +- .../tree/java/MethodReferenceResolver.java | 15 +- .../PsiMethodReferenceExpressionImpl.java | 10 +- .../tree/java/PsiNewExpressionImpl.java | 10 +- .../tree/java/PsiReferenceExpressionImpl.java | 30 ++-- .../processor/MethodCandidatesProcessor.java | 2 +- .../impl/providers/FileReference.java | 20 +-- .../psi/impl/source/resolve/ResolveCache.java | 39 ++++- .../impl/PsiPolyVariantCachingReference.java | 10 +- .../FileReferenceQuickFixProvider.java | 20 +-- .../TestDataReferenceContributor.java | 4 +- .../relaxNG/references/FileReferenceUtil.java | 12 -- 27 files changed, 264 insertions(+), 222 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index d64529008ca4..28767e6ce422 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -400,7 +400,7 @@ public class JavaCompletionContributor extends CompletionContributor { if (((PsiJavaCodeReferenceElement)parent).getQualifier() != null) return isSecondCompletion; if (parent instanceof PsiJavaCodeReferenceElementImpl && - ((PsiJavaCodeReferenceElementImpl)parent).getKind() == PsiJavaCodeReferenceElementImpl.PACKAGE_NAME_KIND) { + ((PsiJavaCodeReferenceElementImpl)parent).getKind(parent.getContainingFile()) == PsiJavaCodeReferenceElementImpl.PACKAGE_NAME_KIND) { return false; } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java index 9ade1c2a4495..0770a04f4dce 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -766,7 +766,7 @@ public class ImportHelper{ continue; } if (reference instanceof PsiJavaCodeReferenceElementImpl - && ((PsiJavaCodeReferenceElementImpl)reference).getKind() == PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND) { + && ((PsiJavaCodeReferenceElementImpl)reference).getKind(((PsiJavaCodeReferenceElementImpl)reference).getContainingFile()) == PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND) { continue; } } @@ -774,7 +774,7 @@ public class ImportHelper{ final JavaResolveResult resolveResult = javaReference.advancedResolve(true); PsiElement refElement = resolveResult.getElement(); if (refElement == null && referenceElement != null) { - refElement = ResolveClassUtil.resolveClass(referenceElement); // might be uncomplete code + refElement = ResolveClassUtil.resolveClass(referenceElement, referenceElement.getContainingFile()); // might be uncomplete code } if (refElement == null) continue; diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java index 42d3098b7b07..3d1e1c01c586 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java @@ -55,7 +55,8 @@ public class JavaReferenceAdjuster implements ReferenceAdjuster { boolean rightKind = true; if (elementType == JavaElementType.JAVA_CODE_REFERENCE) { - int kind = ((PsiJavaCodeReferenceElementImpl)element).getKind(); + PsiJavaCodeReferenceElementImpl impl = (PsiJavaCodeReferenceElementImpl)element; + int kind = impl.getKind(impl.getContainingFile()); rightKind = kind == PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND || kind == PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND; } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java index 71e40e5b0ac6..a0243dfc241a 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java @@ -268,10 +268,11 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer return JavaClassReferenceProvider.EXTEND_CLASS_NAMES.getValue(getOptions()); } - private LookupElement[] processPackage(final PsiPackage aPackage) { + @NotNull + private LookupElement[] processPackage(@NotNull PsiPackage aPackage) { final ArrayList list = ContainerUtil.newArrayList(); final int startOffset = StringUtil.isEmpty(aPackage.getName()) ? 0 : aPackage.getQualifiedName().length() + 1; - final GlobalSearchScope scope = getScope(); + final GlobalSearchScope scope = getScope(getElement().getContainingFile()); for (final PsiPackage subPackage : aPackage.getSubPackages(scope)) { final String shortName = subPackage.getQualifiedName().substring(startOffset); if (JavaPsiFacade.getInstance(subPackage.getProject()).getNameHelper().isIdentifier(shortName)) { @@ -355,7 +356,8 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer return (JavaResolveResult) resolveCache.resolveWithCaching(this, MyResolver.INSTANCE, false, false,file)[0]; } - private JavaResolveResult doAdvancedResolve() { + @NotNull + private JavaResolveResult doAdvancedResolve(@NotNull PsiFile containingFile) { final PsiElement psiElement = getElement(); if (!psiElement.isValid()) return JavaResolveResult.EMPTY; @@ -366,7 +368,9 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer if (context instanceof PsiClass) { if (isStaticClassReference(elementText, false)) { final PsiClass psiClass = ((PsiClass)context).findInnerClassByName(getCanonicalText(), false); - if (psiClass != null) return new ClassCandidateInfo(psiClass, PsiSubstitutor.EMPTY, false, psiElement); + if (psiClass != null) { + return new ClassCandidateInfo(psiClass, PsiSubstitutor.EMPTY, false, psiElement); + } PsiElement member = doResolveMember((PsiClass)context, myText); return member == null ? JavaResolveResult.EMPTY : new CandidateInfo(member, PsiSubstitutor.EMPTY, false, false, psiElement); } @@ -382,18 +386,18 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer if (!qName.contains(".")) { final String defaultPackage = JavaClassReferenceProvider.DEFAULT_PACKAGE.getValue(getOptions()); if (StringUtil.isNotEmpty(defaultPackage)) { - final JavaResolveResult resolveResult = advancedResolveInner(psiElement, defaultPackage + "." + qName); + final JavaResolveResult resolveResult = advancedResolveInner(psiElement, defaultPackage + "." + qName, containingFile); if (resolveResult != JavaResolveResult.EMPTY) { return resolveResult; } } } - return advancedResolveInner(psiElement, qName); + return advancedResolveInner(psiElement, qName, containingFile); } - private JavaResolveResult advancedResolveInner(final PsiElement psiElement, final String qName) { - final PsiManager manager = psiElement.getManager(); - final GlobalSearchScope scope = getScope(); + private JavaResolveResult advancedResolveInner(@NotNull PsiElement psiElement, @NotNull String qName, @NotNull PsiFile containingFile) { + final PsiManager manager = containingFile.getManager(); + final GlobalSearchScope scope = getScope(containingFile); if (myIndex == myJavaClassReferenceSet.getReferences().length - 1) { final PsiClass aClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, scope); if (aClass != null) { @@ -413,8 +417,6 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer resolveResult = resolveMember(qName, manager, getElement().getResolveScope()); } if (resolveResult == null) { - PsiFile containingFile = psiElement.getContainingFile(); - if (containingFile instanceof PsiJavaFile) { if (containingFile instanceof ServerPageFile) { containingFile = containingFile.getViewProvider().getPsi(JavaLanguage.INSTANCE); @@ -448,12 +450,12 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer : JavaResolveResult.EMPTY; } - private GlobalSearchScope getScope() { - Project project = getElement().getProject(); + private GlobalSearchScope getScope(@NotNull PsiFile containingFile) { + Project project = containingFile.getProject(); GlobalSearchScope scope = myJavaClassReferenceSet.getProvider().getScope(project); if (scope == null) { - Module module = ModuleUtilCore.findModuleForPsiElement(getElement()); - return module != null ? module.getModuleWithDependenciesAndLibrariesScope(true) : GlobalSearchScope.allScope(project); + Module module = ModuleUtilCore.findModuleForPsiElement(containingFile); + return module == null ? GlobalSearchScope.allScope(project) : module.getModuleWithDependenciesAndLibrariesScope(true); } return scope; } @@ -472,7 +474,7 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer } @Nullable - private List registerFixes(final HighlightInfo info) { + private List registerFixes(HighlightInfo info) { final List list = OrderEntryFix.registerFixes(new QuickFixActionRegistrarImpl(info), this); @@ -498,7 +500,7 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer final TextRange range = new TextRange(references[0].getRangeInElement().getStartOffset(), getRangeInElement().getEndOffset()); final String qualifiedName = range.substring(getElement().getText()); - final CreateClassOrPackageFix action = CreateClassOrPackageFix.createFix(qualifiedName, getScope(), getElement(), contextPackage, + final CreateClassOrPackageFix action = CreateClassOrPackageFix.createFix(qualifiedName, getScope(getElement().getContainingFile()), getElement(), contextPackage, kind, extendClass, templateName); if (action != null) { QuickFixAction.registerQuickFixAction(info, action); @@ -591,13 +593,13 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer return myJavaClassReferenceSet.getUnresolvedMessagePattern(myIndex); } - private static class MyResolver implements ResolveCache.PolyVariantResolver { + private static class MyResolver implements ResolveCache.PolyVariantContextResolver { private static final MyResolver INSTANCE = new MyResolver(); @NotNull @Override - public JavaResolveResult[] resolve(@NotNull JavaClassReference javaClassReference, boolean incompleteCode) { - return new JavaResolveResult[]{javaClassReference.doAdvancedResolve()}; + public ResolveResult[] resolve(@NotNull JavaClassReference ref, @NotNull PsiFile containingFile, boolean incompleteCode) { + return new JavaResolveResult[]{ref.doAdvancedResolve(containingFile)}; } } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeCopyHandler.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeCopyHandler.java index 283e8578e146..a0234777aa86 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeCopyHandler.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeCopyHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -200,7 +200,7 @@ public class JavaTreeCopyHandler implements TreeCopyHandler { } } else if (original.getElementType() == JavaElementType.JAVA_CODE_REFERENCE) { - switch (((PsiJavaCodeReferenceElementImpl)original).getKind()) { + switch (((PsiJavaCodeReferenceElementImpl)original).getKind(((PsiJavaCodeReferenceElementImpl)original).getContainingFile())) { case PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND: case PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND: case PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND: diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaCodeReferenceElementImpl.java index 7b44a496416c..a4fc56e0cf89 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaCodeReferenceElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaCodeReferenceElementImpl.java @@ -15,18 +15,21 @@ */ package com.intellij.psi.impl.compiled; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.PsiSubstitutorImpl; +import com.intellij.psi.impl.ResolveScopeManager; import com.intellij.psi.impl.cache.TypeInfo; import com.intellij.psi.impl.source.resolve.ResolveCache; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.scope.PsiScopeProcessor; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; @@ -44,7 +47,7 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P private final String myQualifiedName; private final PsiReferenceParameterList myRefParameterList; - public ClsJavaCodeReferenceElementImpl(PsiElement parent, String canonicalText) { + public ClsJavaCodeReferenceElementImpl(PsiElement parent, @NotNull String canonicalText) { myParent = parent; String canonical = TypeInfo.internFrequentType(canonicalText); @@ -88,20 +91,20 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P return myCanonicalText; } - private static class Resolver implements ResolveCache.PolyVariantResolver { + private static class Resolver implements ResolveCache.PolyVariantContextResolver { public static final Resolver INSTANCE = new Resolver(); @NotNull @Override - public JavaResolveResult[] resolve(@NotNull ClsJavaCodeReferenceElementImpl ref, boolean incompleteCode) { - final JavaResolveResult resolveResult = ref.advancedResolveImpl(); + public JavaResolveResult[] resolve(@NotNull ClsJavaCodeReferenceElementImpl ref, @NotNull PsiFile containingFile, boolean incompleteCode) { + final JavaResolveResult resolveResult = ref.advancedResolveImpl(containingFile); return resolveResult == null ? JavaResolveResult.EMPTY_ARRAY : new JavaResolveResult[] {resolveResult}; } } - private JavaResolveResult advancedResolveImpl() { + private JavaResolveResult advancedResolveImpl(@NotNull PsiFile containingFile) { PsiTypeElement[] typeElements = myRefParameterList == null ? PsiTypeElement.EMPTY_ARRAY : myRefParameterList.getTypeParameterElements(); - PsiElement resolve = resolveElement(); + PsiElement resolve = resolveElement(containingFile); if (resolve == null) return null; if (resolve instanceof PsiClass) { Map substitutionMap = new HashMap(); @@ -137,7 +140,7 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P } } - private void collectOuterClassTypeArgs(final PsiClass psiClass, + private void collectOuterClassTypeArgs(@NotNull PsiClass psiClass, final String canonicalText, final Map substitutionMap) { final PsiClass containingClass = psiClass.getContainingClass(); @@ -179,7 +182,7 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P } @Nullable - private PsiElement resolveElement() { + private PsiElement resolveElement(@NotNull PsiFile containingFile) { PsiElement element = getParent(); while(element != null && (!(element instanceof PsiClass) || element instanceof PsiTypeParameter)) { if(element instanceof PsiMethod){ @@ -199,16 +202,18 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable((PsiTypeParameterListOwner)element)) { if (myQualifiedName.equals(parameter.getName())) return parameter; } - return resolveClassPreferringMyJar(); + return resolveClassPreferringMyJar(containingFile); } @Nullable - private PsiClass resolveClassPreferringMyJar() { - PsiClass[] classes = JavaPsiFacade.getInstance(getProject()).findClasses(myQualifiedName, getResolveScope()); + private PsiClass resolveClassPreferringMyJar(@NotNull PsiFile containingFile) { + Project project = containingFile.getProject(); + GlobalSearchScope scope = ResolveScopeManager.getInstance(project).getResolveScope(this); + PsiClass[] classes = JavaPsiFacade.getInstance(project).findClasses(myQualifiedName, scope); if (classes.length == 0) return null; if (classes.length > 1) { - VirtualFile jarFile = PsiUtil.getJarFile(this); + VirtualFile jarFile = PsiUtil.getJarFile(containingFile); if (jarFile != null) { for (PsiClass aClass : classes) { if (Comparing.equal(PsiUtil.getJarFile(aClass), jarFile)) return aClass; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java index 361f2374b904..3508873df641 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java @@ -208,11 +208,10 @@ public class PsiClassReferenceType extends PsiClassType.Stub { if (myReference instanceof PsiJavaCodeReferenceElementImpl) { PsiAnnotation[] annotations = getAnnotations(); if (!annotated || annotations.length == 0) annotations = null; - return ((PsiJavaCodeReferenceElementImpl)myReference).getCanonicalText(annotated, annotations); - } - else { - return myReference.getCanonicalText(); + PsiJavaCodeReferenceElementImpl impl = (PsiJavaCodeReferenceElementImpl)myReference; + return impl.getCanonicalText(annotated, annotations, impl.getContainingFile()); } + return myReference.getCanonicalText(); } @NotNull diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java index 5ee1243b09ce..1b60c157e248 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java @@ -57,7 +57,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme private volatile String myCachedQName = null; private volatile String myCachedNormalizedText; - private int myKindWhenDummy = CLASS_NAME_KIND; + private volatile int myKindWhenDummy = CLASS_NAME_KIND; public static final int CLASS_NAME_KIND = 1; public static final int PACKAGE_NAME_KIND = 2; @@ -92,8 +92,8 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme return type == TokenType.DUMMY_HOLDER || type == JavaElementType.DUMMY_ELEMENT; } - public int getKind() { - PsiUtilCore.ensureValid(this); + public int getKind(@NotNull PsiFile containingFile) { + PsiUtilCore.ensureValid(containingFile); CompositeElement treeParent = getTreeParent(); IElementType i = treeParent.getElementType(); if (isDummy(i)) { @@ -142,7 +142,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme return CLASS_FQ_OR_PACKAGE_NAME_KIND; } if (i == JavaElementType.JAVA_CODE_REFERENCE) { - int parentKind = ((PsiJavaCodeReferenceElementImpl)treeParent).getKind(); + int parentKind = ((PsiJavaCodeReferenceElementImpl)treeParent).getKind(containingFile); if (parentKind == CLASS_NAME_KIND) { return CLASS_OR_PACKAGE_NAME_KIND; } @@ -256,16 +256,17 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme @Override @NotNull public String getCanonicalText() { - return getCanonicalText(false, null); + return getCanonicalText(false, null, getContainingFile()); } @NotNull - public String getCanonicalText(boolean annotated, @Nullable PsiAnnotation[] annotations) { - switch (getKind()) { + public String getCanonicalText(boolean annotated, @Nullable PsiAnnotation[] annotations, @NotNull PsiFile containingFile) { + switch (getKind(containingFile)) { case CLASS_NAME_KIND: case CLASS_OR_PACKAGE_NAME_KIND: case CLASS_IN_QUALIFIED_NEW_KIND: - final PsiElement target = resolve(); + JavaResolveResult[] results = multiResolve(false, containingFile, containingFile.getProject()); + final PsiElement target = results.length == 1 ? results[0].getElement() : null; if (target instanceof PsiClass) { PsiClass aClass = (PsiClass)target; StringBuilder buffer = new StringBuilder(); @@ -273,7 +274,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme PsiElement qualifier = getQualifier(); String prefix = null; if (qualifier instanceof PsiJavaCodeReferenceElementImpl) { - prefix = ((PsiJavaCodeReferenceElementImpl)qualifier).getCanonicalText(annotated, null); + prefix = ((PsiJavaCodeReferenceElementImpl)qualifier).getCanonicalText(annotated, null, containingFile); } else { String fqn = aClass.getQualifiedName(); @@ -327,15 +328,14 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme return advancedResolve(false).getElement(); } - private static final class OurGenericsResolver implements ResolveCache.PolyVariantResolver { + private static final class OurGenericsResolver implements ResolveCache.PolyVariantContextResolver { private static final OurGenericsResolver INSTANCE = new OurGenericsResolver(); @NotNull @Override - public JavaResolveResult[] resolve(@NotNull PsiJavaReference ref, boolean incompleteCode) { + public ResolveResult[] resolve(@NotNull PsiJavaReference ref, @NotNull PsiFile containingFile, boolean incompleteCode) { PsiJavaCodeReferenceElementImpl referenceElement = (PsiJavaCodeReferenceElementImpl)ref; - int kind = referenceElement.getKind(); - PsiFile containingFile = referenceElement.getContainingFile(); + int kind = referenceElement.getKind(containingFile); JavaResolveResult[] result = referenceElement.resolve(kind, containingFile); if (incompleteCode && result.length == 0 && kind != CLASS_FQ_NAME_KIND && kind != CLASS_FQ_OR_PACKAGE_NAME_KIND) { @@ -347,7 +347,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme } } - JavaResolveUtil.substituteResults((PsiJavaCodeReferenceElement)ref, result); + JavaResolveUtil.substituteResults(referenceElement, result); return result; } @@ -373,16 +373,21 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme LOG.error("getManager() == null!"); return JavaResolveResult.EMPTY_ARRAY; } - PsiFile file = SharedImplUtil.getContainingFile(fileElement); - boolean valid = file != null && file.isValid(); + PsiFile containingFile = SharedImplUtil.getContainingFile(fileElement); + boolean valid = containingFile != null && containingFile.isValid(); if (!valid) { LOG.error("invalid!"); return JavaResolveResult.EMPTY_ARRAY; } Project project = manager.getProject(); + return multiResolve(incompleteCode, containingFile, project); + } + + @NotNull + private JavaResolveResult[] multiResolve(boolean incompleteCode, @NotNull PsiFile containingFile, @NotNull Project project) { final ResolveCache resolveCache = ResolveCache.getInstance(project); - final ResolveResult[] results = resolveCache.resolveWithCaching(this, OurGenericsResolver.INSTANCE, true, incompleteCode, file); + final ResolveResult[] results = resolveCache.resolveWithCaching(this, OurGenericsResolver.INSTANCE, true, incompleteCode, containingFile); return results.length == 0 ? JavaResolveResult.EMPTY_ARRAY : (JavaResolveResult[])results; } @@ -394,14 +399,15 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme return subst; } - private JavaResolveResult[] resolve(final int kind, PsiFile containingFile) { + @NotNull + private JavaResolveResult[] resolve(final int kind, @NotNull PsiFile containingFile) { switch (kind) { case CLASS_FQ_NAME_KIND: { // TODO: support type parameters in FQ names String text = getNormalizedText(); if (StringUtil.isEmptyOrSpaces(text)) return JavaResolveResult.EMPTY_ARRAY; - PsiClass aClass = JavaPsiFacade.getInstance(getProject()).findClass(text, getResolveScope()); + PsiClass aClass = JavaPsiFacade.getInstance(containingFile.getProject()).findClass(text, getResolveScope()); if (aClass == null) return JavaResolveResult.EMPTY_ARRAY; if (!isQualified() && text.equals(aClass.getQualifiedName())) { @@ -503,16 +509,17 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme @Override public PsiElement bindToElement(@NotNull final PsiElement element) throws IncorrectOperationException { - CheckUtil.checkWritable(this); + PsiFile containingFile = getContainingFile(); + CheckUtil.checkWritable(containingFile); if (isReferenceTo(element)) return this; - switch (getKind()) { + switch (getKind(containingFile)) { case CLASS_NAME_KIND: case CLASS_FQ_NAME_KIND: if (!(element instanceof PsiClass)) { throw cannotBindError(element); } - return bindToClass((PsiClass)element); + return bindToClass((PsiClass)element, containingFile); case PACKAGE_NAME_KIND: if (!(element instanceof PsiPackage)) { @@ -523,7 +530,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme case CLASS_OR_PACKAGE_NAME_KIND: case CLASS_FQ_OR_PACKAGE_NAME_KIND: if (element instanceof PsiClass) { - return bindToClass((PsiClass)element); + return bindToClass((PsiClass)element, containingFile); } else if (element instanceof PsiPackage) { return bindToPackage((PsiPackage)element); @@ -538,7 +545,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme if (name == null) { throw new IncorrectOperationException(aClass.toString()); } - final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(getProject()).getParserFacade(); + final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(containingFile.getProject()).getParserFacade(); final PsiJavaCodeReferenceElement ref = parserFacade.createReferenceFromText(name, getParent()); getTreeParent().replaceChildInternal(this, (TreeElement)ref.getNode()); return ref; @@ -557,10 +564,11 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme return new IncorrectOperationException("Cannot bind to " + element); } - private PsiElement bindToClass(PsiClass aClass) throws IncorrectOperationException { + private PsiElement bindToClass(@NotNull PsiClass aClass, @NotNull PsiFile containingFile) throws IncorrectOperationException { String qName = aClass.getQualifiedName(); - boolean preserveQualification = JavaCodeStyleSettingsFacade.getInstance(getProject()).useFQClassNames() && isFullyQualified(); - JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); + Project project = containingFile.getProject(); + boolean preserveQualification = JavaCodeStyleSettingsFacade.getInstance(project).useFQClassNames() && isFullyQualified(containingFile); + JavaPsiFacade facade = JavaPsiFacade.getInstance(project); if (qName == null) { qName = aClass.getName(); PsiClass psiClass = facade.getResolveHelper().resolveReferencedClass(qName, this); @@ -583,7 +591,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme ((PsiJavaCodeReferenceElementImpl)ref).setAnnotations(annotations); if (!preserveQualification) { - JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(aClass.getProject()); + JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); ref = (PsiJavaCodeReferenceElement)codeStyleManager.shortenClassReferences(ref, JavaCodeStyleManager.UNCOMPLETE_CODE); } @@ -631,8 +639,8 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme } } - private boolean isFullyQualified() { - switch (getKind()) { + private boolean isFullyQualified(@NotNull PsiFile containingFile) { + switch (getKind(containingFile)) { case CLASS_OR_PACKAGE_NAME_KIND: if (resolve() instanceof PsiPackage) return true; //noinspection fallthrough @@ -656,10 +664,10 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme final PsiElement refElement = SourceTreeToPsiMap.treeToPsiNotNull(qualifier).resolve(); if (refElement instanceof PsiPackage) return true; - return SourceTreeToPsiMap.treeToPsiNotNull(qualifier).isFullyQualified(); + return SourceTreeToPsiMap.treeToPsiNotNull(qualifier).isFullyQualified(containingFile); } - private PsiElement bindToPackage(final PsiPackage aPackage) throws IncorrectOperationException { + private PsiElement bindToPackage(@NotNull PsiPackage aPackage) throws IncorrectOperationException { final String qName = aPackage.getQualifiedName(); if (qName.isEmpty()) { throw new IncorrectOperationException("Cannot bind to default package: "+aPackage); @@ -672,7 +680,12 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme @Override public boolean isReferenceTo(final PsiElement element) { - switch (getKind()) { + PsiFile containingFile = getContainingFile(); + return isReferenceTo(element, containingFile); + } + + private boolean isReferenceTo(PsiElement element, @NotNull PsiFile containingFile) { + switch (getKind(containingFile)) { case CLASS_NAME_KIND: case CLASS_IN_QUALIFIED_NEW_KIND: if (!(element instanceof PsiClass)) return false; @@ -681,44 +694,40 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme case CLASS_FQ_NAME_KIND: { if (!(element instanceof PsiClass)) return false; final String qName = ((PsiClass)element).getQualifiedName(); - return qName != null && qName.equals(getCanonicalText()); + return qName != null && qName.equals(getCanonicalText(false, null, containingFile)); } case PACKAGE_NAME_KIND: { if (!(element instanceof PsiPackage)) return false; final String qName = ((PsiPackage)element).getQualifiedName(); - return qName.equals(getCanonicalText()); + return qName.equals(getCanonicalText(false, null, containingFile)); } case CLASS_OR_PACKAGE_NAME_KIND: // if (lastChild.type != IDENTIFIER) return false; if (element instanceof PsiPackage) { final String qName = ((PsiPackage)element).getQualifiedName(); - return qName.equals(getCanonicalText()); + return qName.equals(getCanonicalText(false, null, containingFile)); } - else if (element instanceof PsiClass) { + if (element instanceof PsiClass) { final PsiIdentifier nameIdentifier = ((PsiClass)element).getNameIdentifier(); if (nameIdentifier == null) return false; PsiElement nameElement = getReferenceNameElement(); return nameElement != null && nameElement.textMatches(nameIdentifier) && - element.getManager().areElementsEquivalent(resolve(), element); - } - else { - return false; + containingFile.getManager().areElementsEquivalent(resolve(), element); } + return false; case CLASS_FQ_OR_PACKAGE_NAME_KIND: if (element instanceof PsiClass) { final String qName = ((PsiClass)element).getQualifiedName(); - return qName != null && qName.equals(getCanonicalText()); + return qName != null && qName.equals(getCanonicalText(false, null, containingFile)); } - else if (element instanceof PsiPackage) { + if (element instanceof PsiPackage) { final String qName = ((PsiPackage)element).getQualifiedName(); - return qName.equals(getCanonicalText()); - } - else { - return false; + return qName.equals(getCanonicalText(false, null, containingFile)); } + return false; default: LOG.assertTrue(false); return true; @@ -727,7 +736,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme final ASTNode referenceNameElement = getReferenceNameNode(); if (referenceNameElement == null || referenceNameElement.getElementType() != JavaTokenType.IDENTIFIER) return false; final String name = ((PsiClass)element).getName(); - return name != null && referenceNameElement.getText().equals(name) && element.getManager().areElementsEquivalent(resolve(), element); + return name != null && referenceNameElement.getText().equals(name) && containingFile.getManager().areElementsEquivalent(resolve(), element); } private String getNormalizedText() { @@ -748,8 +757,8 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme } @Override - public void fullyQualify(final PsiClass targetClass) { - final int kind = getKind(); + public void fullyQualify(@NotNull final PsiClass targetClass) { + final int kind = getKind(getContainingFile()); if (kind != CLASS_NAME_KIND && kind != CLASS_OR_PACKAGE_NAME_KIND && kind != CLASS_IN_QUALIFIED_NEW_KIND) { LOG.error("Wrong kind " + kind); return; @@ -778,32 +787,31 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme @NotNull public Object[] getVariants() { final ElementFilter filter; - switch (getKind()) { - - case CLASS_OR_PACKAGE_NAME_KIND: - filter = new OrFilter(); - ((OrFilter)filter).addFilter(ElementClassFilter.CLASS); - ((OrFilter)filter).addFilter(ElementClassFilter.PACKAGE_FILTER); - break; - case CLASS_NAME_KIND: - filter = ElementClassFilter.CLASS; - break; - case PACKAGE_NAME_KIND: - filter = ElementClassFilter.PACKAGE_FILTER; - break; - case CLASS_FQ_NAME_KIND: - case CLASS_FQ_OR_PACKAGE_NAME_KIND: - filter = new OrFilter(); - ((OrFilter)filter).addFilter(ElementClassFilter.PACKAGE_FILTER); - if (isQualified()) { - ((OrFilter)filter).addFilter(ElementClassFilter.CLASS); - } - break; - case CLASS_IN_QUALIFIED_NEW_KIND: - filter = ElementClassFilter.CLASS; - break; - default: - throw new RuntimeException("Unknown reference type"); + switch (getKind(getContainingFile())) { + case CLASS_OR_PACKAGE_NAME_KIND: + filter = new OrFilter(); + ((OrFilter)filter).addFilter(ElementClassFilter.CLASS); + ((OrFilter)filter).addFilter(ElementClassFilter.PACKAGE_FILTER); + break; + case CLASS_NAME_KIND: + filter = ElementClassFilter.CLASS; + break; + case PACKAGE_NAME_KIND: + filter = ElementClassFilter.PACKAGE_FILTER; + break; + case CLASS_FQ_NAME_KIND: + case CLASS_FQ_OR_PACKAGE_NAME_KIND: + filter = new OrFilter(); + ((OrFilter)filter).addFilter(ElementClassFilter.PACKAGE_FILTER); + if (isQualified()) { + ((OrFilter)filter).addFilter(ElementClassFilter.CLASS); + } + break; + case CLASS_IN_QUALIFIED_NEW_KIND: + filter = ElementClassFilter.CLASS; + break; + default: + throw new RuntimeException("Unknown reference type"); } return PsiImplUtil.getReferenceVariantsByFilter(this, filter); @@ -821,7 +829,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme filter.addFilter(new AndFilter(ElementClassFilter.METHOD, new NotFilter(new ConstructorFilter()))); filter.addFilter(ElementClassFilter.VARIABLE); } - switch (getKind()) { + switch (getKind(getContainingFile())) { case CLASS_OR_PACKAGE_NAME_KIND: filter.addFilter(ElementClassFilter.CLASS); filter.addFilter(ElementClassFilter.PACKAGE_FILTER); @@ -899,7 +907,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme @Override public String getQualifiedName() { - switch (getKind()) { + switch (getKind(getContainingFile())) { case CLASS_NAME_KIND: case CLASS_OR_PACKAGE_NAME_KIND: case CLASS_IN_QUALIFIED_NEW_KIND: diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/SourceJavaCodeReference.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/SourceJavaCodeReference.java index cd3d5e4bdf52..9680725c73fd 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/SourceJavaCodeReference.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/SourceJavaCodeReference.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package com.intellij.psi.impl.source; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; /** * This interface should be implemented by all PsiJavaCodeReference implementations @@ -35,9 +36,8 @@ public interface SourceJavaCodeReference { * Helper method for ReferenceAdjuster. Tries to qualify this reference as if * it references targetClass. Does not check that it indeed references * targetClass - * @param targetClass */ - void fullyQualify(PsiClass targetClass); + void fullyQualify(@NotNull PsiClass targetClass); boolean isQualified(); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ClassResolverProcessor.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ClassResolverProcessor.java index b109372cc882..a2e5593478eb 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ClassResolverProcessor.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ClassResolverProcessor.java @@ -35,6 +35,8 @@ public class ClassResolverProcessor extends BaseScopeProcessor implements NameHi private static final String[] DEFAULT_PACKAGES = {CommonClassNames.DEFAULT_PACKAGE}; private final String myClassName; + @NotNull + private final PsiFile myContainingFile; private final PsiElement myPlace; private PsiClass myAccessClass = null; private List myCandidates = null; @@ -43,8 +45,9 @@ public class ClassResolverProcessor extends BaseScopeProcessor implements NameHi private JavaResolveResult[] myResult = JavaResolveResult.EMPTY_ARRAY; private PsiElement myCurrentFileContext; - public ClassResolverProcessor(String className, @NotNull PsiElement startPlace, PsiFile containingFile) { + public ClassResolverProcessor(@NotNull String className, @NotNull PsiElement startPlace, @NotNull PsiFile containingFile) { myClassName = className; + myContainingFile = containingFile; PsiElement place = containingFile instanceof JavaCodeFragment && ((JavaCodeFragment)containingFile).getVisibilityChecker() != null ? null : startPlace; myPlace = place; if (place instanceof PsiJavaCodeReferenceElement) { @@ -111,7 +114,7 @@ public class ClassResolverProcessor extends BaseScopeProcessor implements NameHi String fqn = psiClass.getQualifiedName(); if (fqn == null) return false; - PsiFile file = myPlace == null ? null : FileContextUtil.getContextFile(myPlace); + PsiFile file = myPlace == null ? null : FileContextUtil.getContextFile(myContainingFile); String[] defaultPackages = file instanceof PsiJavaFile ? ((PsiJavaFile)file).getImplicitlyImportedPackages() : DEFAULT_PACKAGES; String packageName = StringUtil.getPackageName(fqn); @@ -123,9 +126,8 @@ public class ClassResolverProcessor extends BaseScopeProcessor implements NameHi return file instanceof PsiJavaFile && ((PsiJavaFile)file).getPackageName().equals(packageName); } - private Domination dominates(PsiClass aClass, boolean accessible, String fqName, ClassCandidateInfo info) { + private Domination dominates(@NotNull PsiClass aClass, boolean accessible, @NotNull String fqName, @NotNull ClassCandidateInfo info) { final PsiClass otherClass = info.getElement(); - assert otherClass != null; String otherQName = otherClass.getQualifiedName(); if (fqName.equals(otherQName)) { return Domination.DOMINATED_BY; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java index 20db589bef5c..ebeebe24b88d 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java @@ -225,7 +225,7 @@ public class JavaResolveUtil { return true; } - public static void substituteResults(final @NotNull PsiJavaCodeReferenceElement ref, @NotNull JavaResolveResult[] result) { + public static void substituteResults(@NotNull final PsiJavaCodeReferenceElement ref, @NotNull JavaResolveResult[] result) { if (result.length > 0 && result[0].getElement() instanceof PsiClass) { for (int i = 0; i < result.length; i++) { final CandidateInfo resolveResult = (CandidateInfo)result[i]; @@ -247,7 +247,7 @@ public class JavaResolveUtil { @NotNull public static JavaResolveResult[] resolveWithContainingFile(@NotNull T ref, - @NotNull ResolveCache.PolyVariantResolver resolver, + @NotNull ResolveCache.PolyVariantContextResolver resolver, boolean needToPreventRecursion, boolean incompleteCode, @NotNull PsiFile containingFile) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java index 59c8d7f386a1..556bf7152b68 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java @@ -80,8 +80,9 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(myManager.getProject()).getParserFacade(); try { final PsiJavaCodeReferenceElement ref = parserFacade.createReferenceFromText(referenceText, context); - LOG.assertTrue(ref.isValid(), referenceText); - return ResolveClassUtil.resolveClass(ref); + PsiFile containingFile = ref.getContainingFile(); + LOG.assertTrue(containingFile.isValid(), referenceText); + return ResolveClassUtil.resolveClass(ref, containingFile); } catch (IncorrectOperationException e) { return null; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ResolveClassUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ResolveClassUtil.java index 9c3505c160d3..2bedff69ed04 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ResolveClassUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ResolveClassUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,15 +20,16 @@ import com.intellij.psi.*; import com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl; import com.intellij.psi.scope.util.PsiScopesUtil; import com.intellij.psi.util.PsiUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class ResolveClassUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.resolve.ResolveClassUtil"); @Nullable - public static PsiClass resolveClass(PsiJavaCodeReferenceElement ref) { + public static PsiClass resolveClass(@NotNull PsiJavaCodeReferenceElement ref, @NotNull PsiFile containingFile) { if (ref instanceof PsiJavaCodeReferenceElementImpl && - ((PsiJavaCodeReferenceElementImpl)ref).getKind() == PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND) { + ((PsiJavaCodeReferenceElementImpl)ref).getKind(containingFile) == PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND) { PsiElement parent = ref.getParent(); if (parent instanceof PsiAnonymousClass){ parent = parent.getParent(); @@ -63,7 +64,7 @@ public class ResolveClassUtil { long time1 = System.currentTimeMillis(); */ - ClassResolverProcessor processor = new ClassResolverProcessor(className, ref, ref.getContainingFile()); + ClassResolverProcessor processor = new ClassResolverProcessor(className, ref, containingFile); PsiScopesUtil.resolveAndWalk(processor, ref, null); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/VariableResolverProcessor.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/VariableResolverProcessor.java index ead814a8ef63..123e750e0a1a 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/VariableResolverProcessor.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/VariableResolverProcessor.java @@ -41,7 +41,7 @@ public class VariableResolverProcessor extends ConflictFilterProcessor implement private final PsiClass myAccessClass; private PsiElement myCurrentFileContext = null; - public VariableResolverProcessor(@NotNull PsiJavaCodeReferenceElement place, PsiFile placeFile) { + public VariableResolverProcessor(@NotNull PsiJavaCodeReferenceElement place, @NotNull PsiFile placeFile) { super(place.getText(), ourFilter, new PsiConflictResolver[]{new JavaVariableConflictResolver()}, new SmartList(), place, placeFile); PsiElement referenceName = place.getReferenceNameElement(); @@ -54,16 +54,20 @@ public class VariableResolverProcessor extends ConflictFilterProcessor implement final JavaResolveResult accessClass = PsiUtil.getAccessObjectClass((PsiExpression)qualifier); final PsiElement element = accessClass.getElement(); if (element instanceof PsiTypeParameter) { - PsiElementFactory factory = JavaPsiFacade.getInstance(element.getProject()).getElementFactory(); + PsiElementFactory factory = JavaPsiFacade.getInstance(placeFile.getProject()).getElementFactory(); final PsiClassType type = factory.createType((PsiTypeParameter)element); final PsiType accessType = accessClass.getSubstitutor().substitute(type); if (accessType instanceof PsiArrayType) { - LanguageLevel languageLevel = PsiUtil.getLanguageLevel(qualifier); + LanguageLevel languageLevel = PsiUtil.getLanguageLevel(placeFile); access = factory.getArrayClass(languageLevel); } - else if (accessType instanceof PsiClassType) access = ((PsiClassType)accessType).resolve(); + else if (accessType instanceof PsiClassType) { + access = ((PsiClassType)accessType).resolve(); + } + } + else if (element instanceof PsiClass) { + access = (PsiClass)element; } - else if (element instanceof PsiClass) access = (PsiClass)element; } myAccessClass = access; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java index f163624c1778..8cf5b5bfbdd2 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,12 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.*; import com.intellij.psi.impl.source.SourceJavaCodeReference; import com.intellij.util.CharTable; +import org.jetbrains.annotations.NotNull; public class JavaSourceUtil { private JavaSourceUtil() { } - public static void fullyQualifyReference(final CompositeElement reference, final PsiClass targetClass) { + public static void fullyQualifyReference(@NotNull CompositeElement reference, @NotNull PsiClass targetClass) { if (((SourceJavaCodeReference)reference).isQualified()) { // qualified reference final PsiClass parentClass = targetClass.getContainingClass(); if (parentClass == null) return; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java index 918d7fed7237..c310f5effc08 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java @@ -85,7 +85,7 @@ public class JavaTreeGenerator implements TreeGenerator { boolean isFQ = false; if (original instanceof PsiJavaCodeReferenceElementImpl) { - int kind = ((PsiJavaCodeReferenceElementImpl)original).getKind(); + int kind = ((PsiJavaCodeReferenceElementImpl)original).getKind(original.getContainingFile()); switch (kind) { case PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND: case PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND: diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java index 62ddc0d97722..503cbf48ddd3 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java @@ -41,14 +41,13 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -class MethodReferenceResolver implements ResolveCache.PolyVariantResolver { +class MethodReferenceResolver implements ResolveCache.PolyVariantContextResolver { private static final Logger LOG = Logger.getInstance("#" + MethodReferenceResolver.class.getName()); @NotNull @Override - public ResolveResult[] resolve(@NotNull final PsiMethodReferenceExpression reference, boolean incompleteCode) { - final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult( - reference); + public JavaResolveResult[] resolve(@NotNull final PsiMethodReferenceExpressionImpl reference, @NotNull final PsiFile containingFile, boolean incompleteCode) { + final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(reference); final PsiClass containingClass = qualifierResolveResult.getContainingClass(); PsiSubstitutor substitutor = qualifierResolveResult.getSubstitutor(); @@ -87,7 +86,7 @@ class MethodReferenceResolver implements ResolveCache.PolyVariantResolver()) { + new MethodCandidatesProcessor(reference, containingFile, new PsiConflictResolver[] {conflictResolver}, new SmartList()) { @Override protected boolean acceptVarargs() { return true; @@ -245,7 +244,7 @@ class MethodReferenceResolver implements ResolveCache.PolyVariantResolver map = PsiMethodReferenceUtil.ourRefs.get(); if (map != null && map.containsKey(this)) { - return (JavaResolveResult[])resolver.resolve(this, incompleteCode); + return RESOLVER.resolve(this, file, incompleteCode); } - ResolveResult[] results = ResolveCache.getInstance(getProject()).resolveWithCaching(this, resolver, true, incompleteCode,file); + ResolveResult[] results = ResolveCache.getInstance(getProject()).resolveWithCaching(this, RESOLVER, true, incompleteCode, file); return results.length == 0 ? JavaResolveResult.EMPTY_ARRAY : (JavaResolveResult[])results; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java index dc8f0bb75f6e..7862a7381011 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -136,12 +136,12 @@ public class PsiNewExpressionImpl extends ExpressionPsiElement implements PsiNew return new PsiPolyVariantCachingReference() { @Override @NotNull - public JavaResolveResult[] resolveInner(boolean incompleteCode) { + public JavaResolveResult[] resolveInner(boolean incompleteCode, @NotNull PsiFile containingFile) { ASTNode classRef = findChildByRole(ChildRole.TYPE_REFERENCE); if (classRef != null) { ASTNode argumentList = PsiImplUtil.skipWhitespaceAndComments(classRef.getTreeNext()); if (argumentList != null && argumentList.getElementType() == JavaElementType.EXPRESSION_LIST) { - final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(containingFile.getProject()); PsiType aClass = facade.getElementFactory().createType((PsiJavaCodeReferenceElement)SourceTreeToPsiMap.treeElementToPsi(classRef)); return facade.getResolveHelper().multiResolveConstructor((PsiClassType)aClass, (PsiExpressionList)SourceTreeToPsiMap.treeElementToPsi(argumentList), @@ -151,7 +151,7 @@ public class PsiNewExpressionImpl extends ExpressionPsiElement implements PsiNew else{ ASTNode anonymousClassElement = findChildByType(JavaElementType.ANONYMOUS_CLASS); if (anonymousClassElement != null) { - final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(containingFile.getProject()); final PsiAnonymousClass anonymousClass = (PsiAnonymousClass)SourceTreeToPsiMap.treeElementToPsi(anonymousClassElement); PsiType aClass = anonymousClass.getBaseClassType(); ASTNode argumentList = anonymousClassElement.findChildByType(JavaElementType.EXPRESSION_LIST); @@ -176,7 +176,7 @@ public class PsiNewExpressionImpl extends ExpressionPsiElement implements PsiNew @Override @NotNull public String getCanonicalText() { - return null; + throw new UnsupportedOperationException(); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java index f91f01c3195c..02ffaa6f3c20 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java @@ -181,23 +181,22 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple super.clearCaches(); } - public static final class OurGenericsResolver implements ResolveCache.PolyVariantResolver { + public static final class OurGenericsResolver implements ResolveCache.PolyVariantContextResolver { public static final OurGenericsResolver INSTANCE = new OurGenericsResolver(); - @Override @NotNull - public JavaResolveResult[] resolve(@NotNull PsiJavaReference ref, boolean incompleteCode) { + @Override + public ResolveResult[] resolve(@NotNull PsiJavaReference ref, @NotNull PsiFile containingFile, boolean incompleteCode) { PsiReferenceExpressionImpl expression = (PsiReferenceExpressionImpl)ref; CompositeElement treeParent = expression.getTreeParent(); IElementType parentType = treeParent == null ? null : treeParent.getElementType(); - PsiFile file = expression.getContainingFile(); - List qualifiers = resolveAllQualifiers(expression, file); + List qualifiers = resolveAllQualifiers(expression, containingFile); try { - JavaResolveResult[] result = expression.resolve(parentType, file); + JavaResolveResult[] result = expression.resolve(parentType, containingFile); if (result.length == 0 && incompleteCode && parentType != JavaElementType.REFERENCE_EXPRESSION) { - result = expression.resolve(JavaElementType.REFERENCE_EXPRESSION, file); + result = expression.resolve(JavaElementType.REFERENCE_EXPRESSION, containingFile); } JavaResolveUtil.substituteResults(expression, result); @@ -213,6 +212,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple } } + @NotNull private static List resolveAllQualifiers(@NotNull PsiReferenceExpressionImpl expression, @NotNull final PsiFile containingFile) { // to avoid SOE, resolve all qualifiers starting from the innermost PsiElement qualifier = expression.getQualifier(); @@ -246,9 +246,9 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple } @NotNull - private JavaResolveResult[] resolve(IElementType parentType, PsiFile containingFile) { + private JavaResolveResult[] resolve(IElementType parentType, @NotNull PsiFile containingFile) { if (parentType == JavaElementType.REFERENCE_EXPRESSION) { - JavaResolveResult[] result = resolveToVariable(); + JavaResolveResult[] result = resolveToVariable(containingFile); if (result.length > 0) { return result; } @@ -280,7 +280,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple return resolve(JavaElementType.REFERENCE_EXPRESSION, containingFile); } - return resolveToVariable(); + return resolveToVariable(containingFile); } @NotNull @@ -297,7 +297,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple } @NotNull - private JavaResolveResult[] resolveToPackage(PsiFile containingFile) { + private JavaResolveResult[] resolveToPackage(@NotNull PsiFile containingFile) { final String packageName = getCachedNormalizedText(); Project project = containingFile.getProject(); JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); @@ -316,7 +316,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple } @NotNull - private JavaResolveResult[] resolveToClass(@NotNull PsiElement classNameElement, PsiFile containingFile) { + private JavaResolveResult[] resolveToClass(@NotNull PsiElement classNameElement, @NotNull PsiFile containingFile) { final String className = classNameElement.getText(); final ClassResolverProcessor processor = new ClassResolverProcessor(className, this, containingFile); @@ -325,8 +325,8 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple } @NotNull - private JavaResolveResult[] resolveToVariable() { - final VariableResolverProcessor processor = new VariableResolverProcessor(this, getContainingFile()); + private JavaResolveResult[] resolveToVariable(@NotNull PsiFile containingFile) { + final VariableResolverProcessor processor = new VariableResolverProcessor(this, containingFile); PsiScopesUtil.resolveAndWalk(processor, this, null); return processor.getResult(); } @@ -730,7 +730,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple } @Override - public void fullyQualify(PsiClass targetClass) { + public void fullyQualify(@NotNull PsiClass targetClass) { JavaSourceUtil.fullyQualifyReference(this, targetClass); } diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java index 7c83f1065318..7106063217b5 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java @@ -94,7 +94,7 @@ public class MethodCandidatesProcessor extends MethodsProcessor{ }; } - protected PsiType[] getExpressionTypes(PsiExpressionList argumentList) { + protected static PsiType[] getExpressionTypes(PsiExpressionList argumentList) { return argumentList != null ? argumentList.getExpressionTypes() : null; } diff --git a/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java index b15ecb7c6c8f..1ab2466ebb04 100644 --- a/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java +++ b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java @@ -128,15 +128,11 @@ public class FileReference implements PsiFileReference, FileReferenceOwner, PsiP return ResolveCache.getInstance(file.getProject()).resolveWithCaching(this, MyResolver.INSTANCE, false, false, file); } - protected ResolveResult[] innerResolve() { - return innerResolve(getFileReferenceSet().isCaseSensitive()); - } - @NotNull - protected ResolveResult[] innerResolve(boolean caseSensitive) { + protected ResolveResult[] innerResolve(boolean caseSensitive, @NotNull PsiFile containingFile) { final String referenceText = getText(); if (referenceText.isEmpty() && myIndex == 0) { - return new ResolveResult[]{new PsiElementResolveResult(getElement().getContainingFile())}; + return new ResolveResult[]{new PsiElementResolveResult(containingFile)}; } final Collection contexts = getContexts(); final Collection result = new THashSet(); @@ -144,7 +140,7 @@ public class FileReference implements PsiFileReference, FileReferenceOwner, PsiP innerResolveInContext(referenceText, context, result, caseSensitive); } if (contexts.isEmpty() && isAllowedEmptyPath(referenceText)) { - result.add(new PsiElementResolveResult(getElement().getContainingFile())); + result.add(new PsiElementResolveResult(containingFile)); } final int resultCount = result.size(); return resultCount > 0 ? result.toArray(new ResolveResult[resultCount]) : ResolveResult.EMPTY_ARRAY; @@ -330,8 +326,8 @@ public class FileReference implements PsiFileReference, FileReferenceOwner, PsiP } @Nullable - public PsiFileSystemItem innerSingleResolve(final boolean caseSensitive) { - final ResolveResult[] resolveResults = innerResolve(caseSensitive); + public PsiFileSystemItem innerSingleResolve(final boolean caseSensitive, @NotNull PsiFile containingFile) { + final ResolveResult[] resolveResults = innerResolve(caseSensitive, containingFile); return resolveResults.length == 1 ? (PsiFileSystemItem)resolveResults[0].getElement() : null; } @@ -553,13 +549,13 @@ public class FileReference implements PsiFileReference, FileReferenceOwner, PsiP return myFileReferenceSet.getLastReference(); } - static class MyResolver implements ResolveCache.PolyVariantResolver { + static class MyResolver implements ResolveCache.PolyVariantContextResolver { static final MyResolver INSTANCE = new MyResolver(); @NotNull @Override - public ResolveResult[] resolve(@NotNull FileReference ref, boolean incompleteCode) { - return ref.innerResolve(ref.getFileReferenceSet().isCaseSensitive()); + public ResolveResult[] resolve(@NotNull FileReference ref, @NotNull PsiFile containingFile, boolean incompleteCode) { + return ref.innerResolve(ref.getFileReferenceSet().isCaseSensitive(), containingFile); } } } diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/resolve/ResolveCache.java b/platform/core-impl/src/com/intellij/psi/impl/source/resolve/ResolveCache.java index b6fd267da4e8..859a6046957f 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/resolve/ResolveCache.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/resolve/ResolveCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,6 +53,10 @@ public class ResolveCache { @NotNull ResolveResult[] resolve(@NotNull T t, boolean incompleteCode); } + public interface PolyVariantContextResolver { + @NotNull + ResolveResult[] resolve(@NotNull T ref, @NotNull PsiFile containingFile, boolean incompleteCode); + } public interface Resolver extends AbstractResolver{ } @@ -132,6 +136,36 @@ public class ResolveCache { return result == null ? ResolveResult.EMPTY_ARRAY : result; } + @NotNull + public ResolveResult[] resolveWithCaching(@NotNull final T ref, + @NotNull final PolyVariantContextResolver resolver, + boolean needToPreventRecursion, + final boolean incompleteCode, + @NotNull final PsiFile containingFile) { + ProgressIndicatorProvider.checkCanceled(); + ApplicationManager.getApplication().assertReadAccessAllowed(); + + ConcurrentMap> map = getMap(containingFile.isPhysical(), incompleteCode, true); + Getter reference = map.get(ref); + ResolveResult[] result = reference == null ? null : reference.get(); + if (result != null) { + return result; + } + + RecursionGuard.StackStamp stamp = myGuard.markStack(); + result = needToPreventRecursion ? myGuard.doPreventingRecursion(Pair.create(ref, incompleteCode), true, new Computable() { + @Override + public ResolveResult[] compute() { + return resolver.resolve(ref, containingFile, incompleteCode); + } + }) : resolver.resolve(ref, containingFile, incompleteCode); + + if (stamp.mayCacheNow()) { + cache(ref, map, result, true); + } + return result == null ? ResolveResult.EMPTY_ARRAY : result; + } + @Nullable public ResolveResult[] getCachedResults(@NotNull T ref, boolean physical, boolean incompleteCode, boolean isPoly) { Map> map = getMap(physical, incompleteCode, isPoly); @@ -148,13 +182,14 @@ public class ResolveCache { return resolve(ref, resolver, needToPreventRecursion, incompleteCode, false, ref.getElement().isPhysical()); } + @NotNull private ConcurrentMap> getMap(boolean physical, boolean incompleteCode, boolean isPoly) { //noinspection unchecked return myMaps[(physical ? 0 : 1)*4 + (incompleteCode ? 0 : 1)*2 + (isPoly ? 0 : 1)]; } private static class SoftGetter extends SoftReference implements Getter { - public SoftGetter(T referent) { + public SoftGetter(@NotNull T referent) { super(referent); } } diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/PsiPolyVariantCachingReference.java b/platform/core-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/PsiPolyVariantCachingReference.java index f55958d22258..fb5439010491 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/PsiPolyVariantCachingReference.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/PsiPolyVariantCachingReference.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,7 +39,7 @@ public abstract class PsiPolyVariantCachingReference implements PsiPolyVariantRe } @NotNull - protected abstract ResolveResult[] resolveInner(boolean incompleteCode); + protected abstract ResolveResult[] resolveInner(boolean incompleteCode, @NotNull PsiFile containingFile); @Override public boolean isReferenceTo(final PsiElement element) { @@ -56,13 +56,13 @@ public abstract class PsiPolyVariantCachingReference implements PsiPolyVariantRe return ElementManipulators.getManipulator(currentElement); } - private static class MyResolver implements ResolveCache.PolyVariantResolver { + private static class MyResolver implements ResolveCache.PolyVariantContextResolver { private static final MyResolver INSTANCE = new MyResolver(); @NotNull @Override - public ResolveResult[] resolve(@NotNull PsiPolyVariantReference reference, boolean incompleteCode) { - return ((PsiPolyVariantCachingReference)reference).resolveInner(incompleteCode); + public ResolveResult[] resolve(@NotNull PsiPolyVariantReference ref, @NotNull PsiFile containingFile, boolean incompleteCode) { + return ((PsiPolyVariantCachingReference)ref).resolveInner(incompleteCode, containingFile); } } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/FileReferenceQuickFixProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/FileReferenceQuickFixProvider.java index 5ccc3fe51985..a2c695404748 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/FileReferenceQuickFixProvider.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/FileReferenceQuickFixProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,10 +28,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiDirectory; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFileSystemItem; -import com.intellij.psi.PsiNamedElement; +import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference; import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet; import com.intellij.util.IncorrectOperationException; @@ -51,7 +48,7 @@ public class FileReferenceQuickFixProvider { private FileReferenceQuickFixProvider() {} @NotNull - public static List registerQuickFix(final FileReference reference) { + public static List registerQuickFix(@NotNull FileReference reference) { final FileReferenceSet fileReferenceSet = reference.getFileReferenceSet(); int index = reference.getIndex(); @@ -68,16 +65,19 @@ public class FileReferenceQuickFixProvider { } PsiFileSystemItem context = null; + PsiElement element = reference.getElement(); + PsiFile containingFile = element == null ? null : element.getContainingFile(); + if(index > 0) { context = fileReferenceSet.getReference(index - 1).resolve(); - } else { // index == 0 + } + else { // index == 0 final Collection defaultContexts = fileReferenceSet.getDefaultContexts(); if (defaultContexts.isEmpty()) { return Collections.emptyList(); } - PsiElement element = reference.getElement(); - Module module = element != null ? ModuleUtilCore.findModuleForPsiElement(element) : null; + Module module = containingFile == null ? null : ModuleUtilCore.findModuleForPsiElement(containingFile); for (PsiFileSystemItem defaultContext : defaultContexts) { if (defaultContext != null) { @@ -108,7 +108,7 @@ public class FileReferenceQuickFixProvider { if (directory == null) return Collections.emptyList(); if (fileReferenceSet.isCaseSensitive()) { - final PsiElement psiElement = reference.innerSingleResolve(false); + final PsiElement psiElement = containingFile == null ? null : reference.innerSingleResolve(false, containingFile); if (psiElement != null) { final String existingElementName = ((PsiNamedElement)psiElement).getName(); diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataReferenceContributor.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataReferenceContributor.java index dbe3cf2910e5..6211357f75dc 100644 --- a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataReferenceContributor.java +++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataReferenceContributor.java @@ -120,7 +120,7 @@ public class TestDataReferenceContributor extends PsiReferenceContributor { @NotNull @Override - protected ResolveResult[] innerResolve(boolean caseSensitive) { + protected ResolveResult[] innerResolve(boolean caseSensitive, @NotNull PsiFile containingFile) { if (getIndex() == 0 && StringUtil.startsWithChar(getText(), '$')) { if (PROJECT_ROOT_VARIABLE.equals(getText())) { final PsiDirectory projectPsiRoot = getProjectPsiRoot(); @@ -135,7 +135,7 @@ public class TestDataReferenceContributor extends PsiReferenceContributor { } } } - return super.innerResolve(caseSensitive); + return super.innerResolve(caseSensitive, containingFile); } @Nullable diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/references/FileReferenceUtil.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/references/FileReferenceUtil.java index a5295ed4e32d..aefcd3f9004f 100644 --- a/xml/relaxng/src/org/intellij/plugins/relaxNG/references/FileReferenceUtil.java +++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/references/FileReferenceUtil.java @@ -112,18 +112,6 @@ public class FileReferenceUtil { return result; } - @Override - protected ResolveResult[] innerResolve() { - final ResolveResult[] results = super.innerResolve(); - return ContainerUtil.findAll(results, new Condition() { - @Override - public boolean value(ResolveResult resolveResult) { - final PsiElement e = resolveResult.getElement(); - return match(e, myCond); - } - }).toArray(ResolveResult.EMPTY_ARRAY); - } - @NotNull @Override public Object[] getVariants() { From 3a294e97b06ff9e18ad374c7973853563a9dc09c Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 23 Apr 2014 12:46:24 +0400 Subject: [PATCH 50/86] removed unused component methods --- .../quickfix/CreateMethodFromUsageFix.java | 8 +-- .../projectRoots/impl/JavaSdkImpl.java | 15 +----- .../execution/impl/RunConfigurableTest.java | 16 +++++- .../openapi/projectRoots/JavaSdk.java | 5 +- .../problems/WolfTheProblemSolver.java | 5 +- .../openapi/vfs/ex/http/HttpFileSystem.java | 5 +- .../psi/impl/PsiDocumentManagerBase.java | 25 +--------- .../openapi/editor/EditorFactory.java | 5 +- .../highlighting/HighlightManagerImpl.java | 30 ++---------- .../problems/MockWolfTheProblemSolver.java | 30 +----------- .../problems/WolfTheProblemSolverImpl.java | 28 +---------- .../template/impl/TemplateManagerImpl.java | 34 +++---------- .../template/impl/TemplateState.java | 22 ++++----- .../execution/impl/RunManagerImpl.java | 29 ++++------- .../intellij/formatting/FormatterImpl.java | 23 ++------- .../ChangeSignatureGestureDetector.java | 49 ++++++------------- .../intellij/ide/FrameStateManagerImpl.java | 21 +------- .../intellij/ide/impl/DataManagerImpl.java | 19 +------ .../UsageStatisticsPersistenceComponent.java | 12 +---- .../editor/impl/EditorFactoryImpl.java | 5 +- .../editor/impl/VisibleEditorsTracker.java | 20 +------- .../impl/FileDocumentManagerImpl.java | 21 ++------ .../vfs/impl/http/HttpFileSystemBase.java | 11 ++--- .../vfs/impl/http/HttpFileSystemImpl.java | 8 +-- .../vfs/impl/http/HttpsFileSystem.java | 8 +-- .../openapi/wm/impl/TestWindowManager.java | 15 +----- .../openapi/wm/impl/WindowManagerImpl.java | 9 +--- .../application/options/PathMacrosImpl.java | 14 ++---- .../com/intellij/mock/MockEditorFactory.java | 14 +----- .../xdebugger/impl/XDebuggerManagerImpl.java | 20 +------- 30 files changed, 104 insertions(+), 422 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java index 3ce012705c0f..b7cd8af73084 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,14 +17,14 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.CodeInsightUtilCore; import com.intellij.codeInsight.ExpectedTypeInfo; -import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx; import com.intellij.codeInsight.daemon.QuickFixBundle; +import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.template.Template; import com.intellij.codeInsight.template.TemplateBuilderImpl; import com.intellij.codeInsight.template.TemplateEditingAdapter; import com.intellij.lang.annotation.HighlightSeverity; -import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -259,7 +259,7 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix { startTemplate(newEditor, template, project, new TemplateEditingAdapter() { @Override public void templateFinished(Template template, boolean brokenOff) { - ApplicationManager.getApplication().runWriteAction(new Runnable() { + WriteCommandAction.runWriteCommandAction(project, new Runnable() { @Override public void run() { PsiDocumentManager.getInstance(project).commitDocument(newEditor.getDocument()); diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java index 2aa495c42694..b52da3c571b6 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -415,19 +415,6 @@ public class JavaSdkImpl extends JavaSdk { return versionString; } - @Override - @NotNull - public String getComponentName() { - return getName(); - } - - @Override - public void initComponent() { } - - @Override - public void disposeComponent() { - } - @Override public int compareTo(@NotNull String versionString, @NotNull String versionNumber) { return getVersionNumber(versionString).compareTo(versionNumber); diff --git a/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.java b/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.java index 0591489afc9c..6d1b6b1dc9b1 100644 --- a/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.java +++ b/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.execution.impl; import com.intellij.execution.application.ApplicationConfigurationType; @@ -179,7 +194,6 @@ public class RunConfigurableTest extends LightIdeaTestCase { RunManagerImpl runManager = new RunManagerImpl(getProject(), PropertiesComponent.getInstance()); runManager.initializeConfigurationTypes(new ConfigurationType[]{ApplicationConfigurationType.getInstance(), JUnitConfigurationType.getInstance(), UnknownConfigurationType.INSTANCE}); - runManager.initComponent(); runManager.readExternal(element); return runManager; } diff --git a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdk.java b/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdk.java index 51ae01f5c1b9..8221324356f5 100644 --- a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdk.java +++ b/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdk.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package com.intellij.openapi.projectRoots; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.projectRoots.impl.SdkVersionUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -24,7 +23,7 @@ import org.jetbrains.annotations.Nullable; import java.io.File; -public abstract class JavaSdk extends SdkType implements JavaSdkType, ApplicationComponent { +public abstract class JavaSdk extends SdkType implements JavaSdkType { public JavaSdk(@NotNull @NonNls String name) { super(name); } diff --git a/platform/analysis-api/src/com/intellij/problems/WolfTheProblemSolver.java b/platform/analysis-api/src/com/intellij/problems/WolfTheProblemSolver.java index d57e62ed9339..c4580e082fb4 100644 --- a/platform/analysis-api/src/com/intellij/problems/WolfTheProblemSolver.java +++ b/platform/analysis-api/src/com/intellij/problems/WolfTheProblemSolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package com.intellij.problems; import com.intellij.openapi.Disposable; -import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; @@ -31,7 +30,7 @@ import java.util.List; /** * @author cdr */ -public abstract class WolfTheProblemSolver implements ProjectComponent { +public abstract class WolfTheProblemSolver { public static final ExtensionPointName> FILTER_EP_NAME = ExtensionPointName.create("com.intellij.problemFileHighlightFilter"); public static WolfTheProblemSolver getInstance(Project project) { diff --git a/platform/core-api/src/com/intellij/openapi/vfs/ex/http/HttpFileSystem.java b/platform/core-api/src/com/intellij/openapi/vfs/ex/http/HttpFileSystem.java index 9f8982fc2901..9ab4fd341e87 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/ex/http/HttpFileSystem.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/ex/http/HttpFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +16,13 @@ package com.intellij.openapi.vfs.ex.http; import com.intellij.openapi.Disposable; -import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.vfs.DeprecatedVirtualFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.io.URLUtil; import org.jetbrains.annotations.NotNull; -public abstract class HttpFileSystem extends DeprecatedVirtualFileSystem implements ApplicationComponent { +public abstract class HttpFileSystem extends DeprecatedVirtualFileSystem { @Deprecated @SuppressWarnings("UnusedDeclaration") /** diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java index 364c9d783799..c580f65ebfc2 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java @@ -20,7 +20,6 @@ import com.intellij.injected.editor.DocumentWindow; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.event.DocumentEvent; @@ -56,7 +55,7 @@ import org.jetbrains.annotations.TestOnly; import javax.swing.*; import java.util.*; -public abstract class PsiDocumentManagerBase extends PsiDocumentManager implements ProjectComponent, DocumentListener { +public abstract class PsiDocumentManagerBase extends PsiDocumentManager implements DocumentListener { protected static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiDocumentManagerImpl"); private static final Key HARD_REF_TO_PSI = new Key("HARD_REFERENCE_TO_PSI"); private static final Key> ACTION_AFTER_COMMIT = Key.create("ACTION_AFTER_COMMIT"); @@ -86,28 +85,6 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen myPsiManager.addPsiTreeChangeListener(mySynchronizer); } - @Override - public void projectOpened() { - } - - @Override - public void projectClosed() { - } - - @Override - @NotNull - public String getComponentName() { - return "PsiDocumentManager"; - } - - @Override - public void initComponent() { - } - - @Override - public void disposeComponent() { - } - @Override @Nullable public PsiFile getPsiFile(@NotNull Document document) { diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/EditorFactory.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/EditorFactory.java index de3fc9beb902..730ff5f54996 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/editor/EditorFactory.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/EditorFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ package com.intellij.openapi.editor; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.editor.event.EditorEventMulticaster; import com.intellij.openapi.editor.event.EditorFactoryListener; import com.intellij.openapi.fileTypes.FileType; @@ -30,7 +29,7 @@ import org.jetbrains.annotations.Nullable; /** * Provides services for creating document and editor instances. */ -public abstract class EditorFactory implements ApplicationComponent { +public abstract class EditorFactory { /** * Returns the editor factory instance. * diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightManagerImpl.java index 1b02e32e236c..8299f59d69e1 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,6 @@ import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.ex.ActionManagerEx; import com.intellij.openapi.actionSystem.ex.AnActionListener; -import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; @@ -49,31 +48,12 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.*; -public class HighlightManagerImpl extends HighlightManager implements ProjectComponent { +public class HighlightManagerImpl extends HighlightManager { private final Project myProject; public HighlightManagerImpl(Project project) { myProject = project; - } - - @Override - @NotNull - public String getComponentName() { - return "HighlightManager"; - } - - @Override - public void initComponent() { - } - - @Override - public void disposeComponent() { - } - - @Override - public void projectOpened() { - AnActionListener anActionListener = new MyAnActionListener(); - ActionManagerEx.getInstanceEx().addAnActionListener(anActionListener, myProject); + ActionManagerEx.getInstanceEx().addAnActionListener(new MyAnActionListener(), myProject); DocumentListener documentListener = new DocumentAdapter() { @Override @@ -102,10 +82,6 @@ public class HighlightManagerImpl extends HighlightManager implements ProjectCom EditorFactory.getInstance().getEventMulticaster().addDocumentListener(documentListener, myProject); } - @Override - public void projectClosed() { - } - @Nullable public Map getHighlightInfoMap(@NotNull Editor editor, boolean toCreate) { if (editor instanceof EditorWindow) return getHighlightInfoMap(((EditorWindow)editor).getDelegate(), toCreate); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java b/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java index 75ad56ed5497..eeb5e04b8aab 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,6 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.problems.Problem; import com.intellij.problems.WolfTheProblemSolver; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -83,33 +82,6 @@ public class MockWolfTheProblemSolver extends WolfTheProblemSolver { if (myDelegate != null) myDelegate.queue(suspiciousFile); } - @Override - public void projectOpened() { - if (myDelegate != null) myDelegate.projectOpened(); - } - - @Override - public void projectClosed() { - if (myDelegate != null) myDelegate.projectClosed(); - } - - @Override - @NonNls - @NotNull - public String getComponentName() { - return "mockwolf"; - } - - @Override - public void initComponent() { - - } - - @Override - public void disposeComponent() { - - } - @Override public void clearProblems(@NotNull VirtualFile virtualFile) { if (myDelegate != null) myDelegate.clearProblems(virtualFile); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java index 6cfbe08635d5..45b4532713c4 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,7 +44,6 @@ import com.intellij.psi.*; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -218,31 +217,6 @@ public class WolfTheProblemSolverImpl extends WolfTheProblemSolver { } } - @Override - public void projectOpened() { - } - - @Override - public void projectClosed() { - } - - @Override - @NotNull - @NonNls - public String getComponentName() { - return "Problems"; - } - - @Override - public void initComponent() { - - } - - @Override - public void disposeComponent() { - - } - public void startCheckingIfVincentSolvedProblemsYet(@NotNull ProgressIndicator progress, @NotNull ProgressableTextEditorHighlightingPass pass) throws ProcessCanceledException { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java index 366fe62d97f2..6a11b5897dda 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java @@ -24,7 +24,6 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.event.EditorFactoryAdapter; import com.intellij.openapi.editor.event.EditorFactoryEvent; @@ -47,7 +46,7 @@ import org.jetbrains.annotations.TestOnly; import java.util.*; -public class TemplateManagerImpl extends TemplateManager implements ProjectComponent, Disposable { +public class TemplateManagerImpl extends TemplateManager implements Disposable { protected Project myProject; private boolean myTemplateTesting; @@ -55,26 +54,6 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo public TemplateManagerImpl(Project project) { myProject = project; - } - - @Override - public void disposeComponent() { - } - - @Override - public void dispose() { - } - - @Override - public void initComponent() { - } - - @Override - public void projectClosed() { - } - - @Override - public void projectOpened() { final EditorFactoryListener myEditorFactoryListener = new EditorFactoryAdapter() { @Override public void editorReleased(@NotNull EditorFactoryEvent event) { @@ -91,6 +70,11 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo EditorFactory.getInstance().addEditorFactoryListener(myEditorFactoryListener, myProject); } + @Override + public void dispose() { + + } + @TestOnly @Deprecated public void setTemplateTesting(final boolean templateTesting) { @@ -540,12 +524,6 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo return Extensions.getExtensions(TemplateContextType.EP_NAME); } - @Override - @NotNull - public String getComponentName() { - return "TemplateManager"; - } - @Override @Nullable public Template getActiveTemplate(@NotNull Editor editor) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java index 165e2be8b320..548264e4676b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java @@ -26,6 +26,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandAdapter; import com.intellij.openapi.command.CommandEvent; import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.command.undo.BasicUndoableAction; import com.intellij.openapi.command.undo.DocumentReference; import com.intellij.openapi.command.undo.DocumentReferenceManager; @@ -116,9 +117,9 @@ public class TemplateState implements Disposable { public void commandStarted(CommandEvent event) { if (myEditor != null) { final int offset = myEditor.getCaretModel().getOffset(); - myDocumentChangesTerminateTemplate = (myCurrentSegmentNumber >= 0 && + myDocumentChangesTerminateTemplate = myCurrentSegmentNumber >= 0 && (offset < mySegments.getSegmentStart(myCurrentSegmentNumber) || - offset > mySegments.getSegmentEnd(myCurrentSegmentNumber))); + offset > mySegments.getSegmentEnd(myCurrentSegmentNumber)); } started = true; } @@ -393,13 +394,8 @@ public class TemplateState implements Disposable { } private String getRangesDebugInfo() { - return myTemplateRange.toString() + - "\ntemplateKey: " + - myTemplate.getKey() + - "\ntemplateText: " + - myTemplate.getTemplateText() + - "\ntemplateString: " + - myTemplate.getString(); + return myTemplateRange + "\ntemplateKey: " + myTemplate.getKey() + "\ntemplateText: " + myTemplate.getTemplateText() + + "\ntemplateString: " + myTemplate; } private void doReformat(final TextRange range) { @@ -479,7 +475,7 @@ public class TemplateState implements Disposable { } String message = template.getKey(); - if (message == null || message.length() == 0) { + if (message == null || message.isEmpty()) { message = template.getString(); if (message == null) { message = template.getTemplateText(); @@ -633,7 +629,7 @@ public class TemplateState implements Disposable { if (myProcessor != null && myCurrentVariableNumber >= 0) { final String variableName = myTemplate.getVariableNameAt(myCurrentVariableNumber); final TextResult value = getVariableValue(variableName); - if (value != null && value.getText().length() > 0) { + if (value != null && !value.getText().isEmpty()) { if (!myProcessor.process(variableName, value.getText())) { finishTemplateEditing(false); // nextTab(); ? return; @@ -643,7 +639,7 @@ public class TemplateState implements Disposable { fixOverlappedSegments(myCurrentSegmentNumber); - ApplicationManager.getApplication().runWriteAction(new Runnable() { + WriteCommandAction.runWriteCommandAction(myProject, new Runnable() { @Override public void run() { BitSet calcedSegments = new BitSet(); @@ -1146,7 +1142,7 @@ public class TemplateState implements Disposable { final int offset = mySegments.getSegmentStart(endSegmentNumber); final int lineStart = myDocument.getLineStartOffset(myDocument.getLineNumber(offset)); // if $END$ is at line start, put it at correct indentation - if (myDocument.getCharsSequence().subSequence(lineStart, offset).toString().trim().length() == 0) { + if (myDocument.getCharsSequence().subSequence(lineStart, offset).toString().trim().isEmpty()) { final int adjustedOffset = style.adjustLineIndent(file, offset); mySegments.replaceSegmentAt(endSegmentNumber, adjustedOffset, adjustedOffset); } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java index d33cf8dcb298..d3a1e1cb0574 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,8 @@ import com.intellij.ProjectTopics; import com.intellij.execution.*; import com.intellij.execution.configurations.*; import com.intellij.ide.util.PropertiesComponent; -import com.intellij.openapi.components.ProjectComponent; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.components.NamedComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; @@ -43,7 +44,7 @@ import javax.swing.*; import java.util.*; -public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, ProjectComponent { +public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, NamedComponent, Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.execution.impl.RunManagerImpl"); private final Project myProject; @@ -61,9 +62,9 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, @Nullable private String myLoadedSelectedConfigurationUniqueName = null; @Nullable private String mySelectedConfigurationId = null; - private Map myIdToIcon = new HashMap(); - private Map myIconCheckTimes = new HashMap(); - private Map myIconCalcTime = Collections.synchronizedMap(new HashMap()); + private final Map myIdToIcon = new HashMap(); + private final Map myIconCheckTimes = new HashMap(); + private final Map myIconCalcTime = Collections.synchronizedMap(new HashMap()); @NonNls protected static final String CONFIGURATION = "configuration"; @@ -78,7 +79,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, @NonNls private static final String OPTION = "option"; private List myUnknownElements = null; - private JDOMExternalizableStringList myOrder = new JDOMExternalizableStringList(); + private final JDOMExternalizableStringList myOrder = new JDOMExternalizableStringList(); private final ArrayList myRecentlyUsedTemporaries = new ArrayList(); private boolean myOrdered = true; @@ -127,18 +128,6 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, initializeConfigurationTypes(configurationTypes); } - @Override - public void disposeComponent() { - } - - @Override - public void initComponent() { - } - - @Override - public void projectOpened() { - } - @Override @NotNull public RunnerAndConfigurationSettings createConfiguration(@NotNull final String name, @NotNull final ConfigurationFactory factory) { @@ -171,7 +160,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, } @Override - public void projectClosed() { + public void dispose() { myTemplateConfigurationsMap.clear(); } diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java index 7d78cf10e2cc..e1366431efd0 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ package com.intellij.formatting; import com.intellij.lang.ASTNode; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileTypes.FileType; @@ -47,13 +46,11 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; public class FormatterImpl extends FormatterEx - implements ApplicationComponent, - IndentFactory, + implements IndentFactory, WrapFactory, AlignmentFactory, SpacingFactory, - FormattingModelFactory -{ + FormattingModelFactory { private static final Logger LOG = Logger.getInstance("#com.intellij.formatting.FormatterImpl"); private final AtomicReference myProgressTask = new AtomicReference(); @@ -797,20 +794,6 @@ public class FormatterImpl extends FormatterEx } } - @Override - @NotNull - public String getComponentName() { - return "FormatterEx"; - } - - @Override - public void initComponent() { - } - - @Override - public void disposeComponent() { - } - @Override public Indent getAbsoluteNoneIndent() { return myAbsoluteNoneIndent; diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureDetector.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureDetector.java index 5693e3ad363b..503537873808 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureDetector.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureDetector.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ package com.intellij.refactoring.changeSignature; import com.intellij.codeInsight.template.TemplateManager; import com.intellij.openapi.Disposable; import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -56,7 +55,7 @@ import java.util.Map; * User: anna * Date: Sep 6, 2010 */ -public class ChangeSignatureGestureDetector extends PsiTreeChangeAdapter implements ProjectComponent, EditorFactoryListener { +public class ChangeSignatureGestureDetector extends PsiTreeChangeAdapter implements EditorFactoryListener, Disposable { private final Map myListenerMap = new HashMap(); private static final Logger LOG = Logger.getInstance("#" + ChangeSignatureGestureDetector.class.getName()); private boolean myDeaf = false; @@ -79,6 +78,14 @@ public class ChangeSignatureGestureDetector extends PsiTreeChangeAdapter impleme myFileEditorManager = fileEditorManager; myProject = project; myTemplateManager = templateManager; + myPsiManager.addPsiTreeChangeListener(this, this); + EditorFactory.getInstance().addEditorFactoryListener(this, this); + Disposer.register(this, new Disposable() { + @Override + public void dispose() { + LOG.assertTrue(myListenerMap.isEmpty(), myListenerMap); + } + }); } public static ChangeSignatureGestureDetector getInstance(Project project){ @@ -137,37 +144,6 @@ public class ChangeSignatureGestureDetector extends PsiTreeChangeAdapter impleme } } - @Override - public void projectOpened() { - myPsiManager.addPsiTreeChangeListener(this); - EditorFactory.getInstance().addEditorFactoryListener(this, myProject); - Disposer.register(myProject, new Disposable() { - @Override - public void dispose() { - myPsiManager.removePsiTreeChangeListener(ChangeSignatureGestureDetector.this); - LOG.assertTrue(myListenerMap.isEmpty(), myListenerMap); - } - }); - } - - @Override - public void projectClosed() { - } - - @NotNull - @Override - public String getComponentName() { - return "ChangeSignatureGestureDetector"; - } - - @Override - public void initComponent() { - } - - @Override - public void disposeComponent() { - } - @Override public void beforeChildRemoval(@NotNull PsiTreeChangeEvent event) { final PsiElement child = event.getChild(); @@ -396,4 +372,9 @@ public class ChangeSignatureGestureDetector extends PsiTreeChangeAdapter impleme myCurrentInfo = null; } } + + @Override + public void dispose() { + + } } diff --git a/platform/platform-impl/src/com/intellij/ide/FrameStateManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/FrameStateManagerImpl.java index 06c419a4ff15..726c8e5e1fb5 100644 --- a/platform/platform-impl/src/com/intellij/ide/FrameStateManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/FrameStateManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,20 +18,18 @@ package com.intellij.ide; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationActivationListener; import com.intellij.openapi.application.impl.ApplicationImpl; -import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.BusyObject; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.wm.IdeFrame; import com.intellij.util.Alarm; import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; -public class FrameStateManagerImpl extends FrameStateManager implements ApplicationComponent { +public class FrameStateManagerImpl extends FrameStateManager { private final List myListeners = ContainerUtil.createLockFreeCopyOnWriteList(); private boolean myShouldSynchronize; @@ -84,21 +82,6 @@ public class FrameStateManagerImpl extends FrameStateManager implements Applicat return myActive.getReady(this); } - @Override - @NotNull - @NonNls - public String getComponentName() { - return "FrameStateManager"; - } - - @Override - public void initComponent() { - } - - @Override - public void disposeComponent() { - } - private void fireDeactivationEvent() { for (FrameStateListener listener : myListeners) { listener.onFrameDeactivated(); diff --git a/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java index aeb9e6577dd9..bea92c9626b9 100644 --- a/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,6 @@ import com.intellij.ide.IdeEventQueue; import com.intellij.ide.impl.dataRules.*; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.extensions.Extensions; @@ -48,7 +47,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -public class DataManagerImpl extends DataManager implements ApplicationComponent { +public class DataManagerImpl extends DataManager { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.impl.DataManagerImpl"); private final Map myDataConstantToRuleMap = new THashMap(); private WindowManagerEx myWindowManager; @@ -57,14 +56,6 @@ public class DataManagerImpl extends DataManager implements ApplicationComponent registerRules(); } - @Override - public void initComponent() { - } - - @Override - public void disposeComponent() { - } - @Nullable private Object getData(@NotNull String dataId, final Component focusedComponent) { for (Component c = focusedComponent; c != null; c = c.getParent()) { @@ -284,12 +275,6 @@ public class DataManagerImpl extends DataManager implements ApplicationComponent myDataConstantToRuleMap.put(CommonDataKeys.EDITOR_EVEN_IF_INACTIVE.getName(), new InactiveEditorRule()); } - @Override - @NotNull - public String getComponentName() { - return "DataManager"; - } - @Override public void saveInDataContext(DataContext dataContext, @NotNull Key dataKey, @Nullable T data) { if (dataContext instanceof UserDataHolder) { diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/persistence/UsageStatisticsPersistenceComponent.java b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/UsageStatisticsPersistenceComponent.java index 273e5803426e..65298387a902 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/persistence/UsageStatisticsPersistenceComponent.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/UsageStatisticsPersistenceComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,7 +42,7 @@ import java.util.Set; )} ) public class UsageStatisticsPersistenceComponent extends BasicSentUsagesPersistenceComponent - implements ApplicationComponent, PersistentStateComponent { + implements NamedComponent, PersistentStateComponent { @NonNls private boolean isAllowed = false; @NonNls private boolean isShowNotification = true; @@ -171,12 +171,4 @@ public class UsageStatisticsPersistenceComponent extends BasicSentUsagesPersiste public String getComponentName() { return "SentUsagesPersistenceComponent"; } - - @Override - public void initComponent() { - } - - @Override - public void disposeComponent() { - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java index 611a7c21260d..42abddccfc6b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityStateListener; import com.intellij.openapi.application.impl.LaterInvocator; +import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -45,7 +46,7 @@ import org.jetbrains.annotations.NotNull; import java.util.List; -public class EditorFactoryImpl extends EditorFactory { +public class EditorFactoryImpl extends EditorFactory implements ApplicationComponent { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.EditorFactoryImpl"); private final EditorEventMulticasterImpl myEditorEventMulticaster = new EditorEventMulticasterImpl(); private final EventDispatcher myEditorFactoryEventDispatcher = EventDispatcher.create(EditorFactoryListener.class); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/VisibleEditorsTracker.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/VisibleEditorsTracker.java index 1c380a0f07df..bacbf42ec614 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/VisibleEditorsTracker.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/VisibleEditorsTracker.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,15 +19,13 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandAdapter; import com.intellij.openapi.command.CommandEvent; import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; -import org.jetbrains.annotations.NotNull; import java.util.HashSet; import java.util.Set; -public class VisibleEditorsTracker extends CommandAdapter implements ApplicationComponent{ +public class VisibleEditorsTracker extends CommandAdapter { private final Set myEditorsVisibleOnCommandStart = new HashSet(); private long myCurrentCommandStart; private long myLastCommandFinish; @@ -41,20 +39,6 @@ public class VisibleEditorsTracker extends CommandAdapter implements Application commandProcessor.addCommandListener(this); } - @Override - @NotNull - public String getComponentName() { - return "VisibleEditorsTracker"; - } - - @Override - public void initComponent() { - } - - @Override - public void disposeComponent() { - } - public boolean wasEditorVisibleOnCommandStart(Editor editor){ return myEditorsVisibleOnCommandStart.contains(editor); } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java index 1a3159f200a0..89521379cc29 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java @@ -23,7 +23,6 @@ import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.UndoConfirmationPolicy; -import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.DiffManager; import com.intellij.openapi.diff.DocumentContent; @@ -41,7 +40,9 @@ import com.intellij.openapi.editor.impl.EditorFactoryImpl; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.*; import com.intellij.openapi.fileEditor.impl.text.TextEditorImpl; -import com.intellij.openapi.fileTypes.*; +import com.intellij.openapi.fileTypes.BinaryFileTypeDecompilers; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.UnknownFileType; import com.intellij.openapi.project.*; import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.ui.DialogBuilder; @@ -84,7 +85,7 @@ import java.lang.reflect.Proxy; import java.util.*; import java.util.List; -public class FileDocumentManagerImpl extends FileDocumentManager implements ApplicationComponent, VirtualFileListener, +public class FileDocumentManagerImpl extends FileDocumentManager implements VirtualFileListener, ProjectManagerListener, SafeWriteRequestor { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl"); @@ -152,20 +153,6 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl } } - @Override - @NotNull - public String getComponentName() { - return "FileDocumentManager"; - } - - @Override - public void initComponent() { - } - - @Override - public void disposeComponent() { - } - @Override @Nullable public Document getDocument(@NotNull final VirtualFile file) { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java index 7665e9496a99..752442007413 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -69,19 +69,13 @@ public abstract class HttpFileSystemBase extends HttpFileSystem { return file instanceof HttpVirtualFile && ((HttpVirtualFile)file).getFileInfo().getState() == RemoteFileState.DOWNLOADED; } - @Override - public void disposeComponent() { - } - - @Override - public void initComponent() { } - @Override @NotNull public VirtualFile createChildDirectory(Object requestor, @NotNull VirtualFile vDir, @NotNull String dirName) throws IOException { throw new UnsupportedOperationException(); } + @NotNull @Override public VirtualFile createChildFile(Object requestor, @NotNull VirtualFile vDir, @NotNull String fileName) throws IOException { throw new UnsupportedOperationException(); @@ -97,6 +91,7 @@ public abstract class HttpFileSystemBase extends HttpFileSystem { throw new UnsupportedOperationException(); } + @NotNull @Override public VirtualFile copyFile(Object requestor, @NotNull VirtualFile vFile, @NotNull VirtualFile newParent, @NotNull final String copyName) throws IOException { throw new UnsupportedOperationException(); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemImpl.java index 02a102c4f71b..9f36af3ce928 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package com.intellij.openapi.vfs.impl.http; import com.intellij.util.io.URLUtil; -import org.jetbrains.annotations.NotNull; /** * @author nik @@ -30,9 +29,4 @@ public class HttpFileSystemImpl extends HttpFileSystemBase { return (HttpFileSystemImpl)getInstance(); } - @Override - @NotNull - public String getComponentName() { - return "HttpFileSystem"; - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpsFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpsFileSystem.java index e9e53fa1fac5..e1068db3eebd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpsFileSystem.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpsFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package com.intellij.openapi.vfs.impl.http; import com.intellij.openapi.vfs.VirtualFileManager; import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; /** * @author nik @@ -33,9 +32,4 @@ public class HttpsFileSystem extends HttpFileSystemBase { return (HttpsFileSystem)VirtualFileManager.getInstance().getFileSystem(HTTPS_PROTOCOL); } - @Override - @NotNull - public String getComponentName() { - return "HttpsFileSystem"; - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java index 413386bb9daa..b2fc056d0a71 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java @@ -16,7 +16,6 @@ package com.intellij.openapi.wm.impl; import com.intellij.openapi.Disposable; -import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.TaskInfo; import com.intellij.openapi.project.Project; @@ -45,7 +44,7 @@ import java.util.List; * @author Anton Katilin * @author Vladimir Kondratyev */ -public final class TestWindowManager extends WindowManagerEx implements ApplicationComponent{ +public final class TestWindowManager extends WindowManagerEx { private static final StatusBarEx ourStatusBar = new DummyStatusBar(); public final void doNotSuggestAsParent(final Window window) { } @@ -338,18 +337,6 @@ public final class TestWindowManager extends WindowManagerEx implements Applicat @Override public void adjustContainerWindow(Component c, Dimension oldSize, Dimension newSize) { } - @Override - @NotNull - public final String getComponentName() { - return "TestWindowManager"; - } - - @Override - public final void initComponent() { } - - @Override - public final void disposeComponent() { } - @Override public void addListener(final WindowManagerListener listener) { } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java index 36012ed2c66a..19131753b5ba 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java @@ -69,7 +69,7 @@ import java.util.Set; name = "WindowManager", roamingType = RoamingType.GLOBAL, storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/window.manager.xml")}) -public final class WindowManagerImpl extends WindowManagerEx implements ApplicationComponent, PersistentStateComponent { +public final class WindowManagerImpl extends WindowManagerEx implements NamedComponent, PersistentStateComponent { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.WindowManagerImpl"); @NonNls public static final String FULL_SCREEN = "ide.frame.full.screen"; @@ -404,13 +404,6 @@ public final class WindowManagerImpl extends WindowManagerEx implements Applicat } } - @Override - public final void disposeComponent() {} - - @Override - public final void initComponent() { - } - @Override public final void doNotSuggestAsParent(final Window window) { myWindowWatcher.doNotSuggestAsParent(window); diff --git a/platform/projectModel-impl/src/com/intellij/application/options/PathMacrosImpl.java b/platform/projectModel-impl/src/com/intellij/application/options/PathMacrosImpl.java index 493b21d85306..cce7a68526bd 100644 --- a/platform/projectModel-impl/src/com/intellij/application/options/PathMacrosImpl.java +++ b/platform/projectModel-impl/src/com/intellij/application/options/PathMacrosImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,8 @@ package com.intellij.application.options; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathMacros; -import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.components.ExpandMacroToPathMap; +import com.intellij.openapi.components.NamedComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.NamedJDOMExternalizable; @@ -39,7 +39,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author dsl */ -public class PathMacrosImpl extends PathMacros implements ApplicationComponent, NamedJDOMExternalizable, RoamingTypeDisabled { +public class PathMacrosImpl extends PathMacros implements NamedComponent, NamedJDOMExternalizable, RoamingTypeDisabled { private static final Logger LOG = Logger.getInstance("#com.intellij.application.options.PathMacrosImpl"); private final Map myLegacyMacros = new HashMap(); private final Map myMacros = new HashMap(); @@ -147,14 +147,6 @@ public class PathMacrosImpl extends PathMacros implements ApplicationComponent, return "PathMacrosImpl"; } - @Override - public void initComponent() { - } - - @Override - public void disposeComponent() { - } - @Override public String getExternalFileName() { return EXT_FILE_NAME; diff --git a/platform/testFramework/src/com/intellij/mock/MockEditorFactory.java b/platform/testFramework/src/com/intellij/mock/MockEditorFactory.java index fa9a832be149..37d365e27baa 100644 --- a/platform/testFramework/src/com/intellij/mock/MockEditorFactory.java +++ b/platform/testFramework/src/com/intellij/mock/MockEditorFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -119,16 +119,4 @@ public class MockEditorFactory extends EditorFactory { public void refreshAllEditors() { } - @Override - @NotNull - public String getComponentName() { - return "mockeditorfactory"; - } - - @Override - public void initComponent() { } - - @Override - public void disposeComponent() { - } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java index 3191f1936887..04ab04f10600 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -64,7 +64,7 @@ import java.util.*; storages = {@Storage( file = StoragePathMacros.WORKSPACE_FILE)}) public class XDebuggerManagerImpl extends XDebuggerManager - implements ProjectComponent, PersistentStateComponent { + implements NamedComponent, PersistentStateComponent { @NonNls public static final String COMPONENT_NAME = "XDebuggerManager"; private final Project myProject; private final XBreakpointManagerImpl myBreakpointManager; @@ -148,28 +148,12 @@ public class XDebuggerManagerImpl extends XDebuggerManager return myProject; } - @Override - public void projectOpened() { - } - - @Override - public void projectClosed() { - } - @NotNull @Override public String getComponentName() { return COMPONENT_NAME; } - @Override - public void initComponent() { - } - - @Override - public void disposeComponent() { - } - @Override @NotNull public XDebugSession startSession(@NotNull final ProgramRunner runner, From a0125dc5cc57ed05d0b9804221f68662016363ba Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 23 Apr 2014 10:52:20 +0200 Subject: [PATCH 51/86] Platform: always allow writing module files (IDEA-123899) --- .../NonProjectFileWritingAccessProvider.java | 9 +++- .../fileEditor/NonProjectFileAccessTest.java | 42 ++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java index d83caa3c0c84..2c781984fb76 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java @@ -19,6 +19,8 @@ import com.intellij.ProjectTopics; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.StorageScheme; import com.intellij.openapi.components.impl.stores.IProjectStore; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.roots.ModuleRootAdapter; @@ -105,6 +107,8 @@ public class NonProjectFileWritingAccessProvider extends WritingAccessProvider { } private boolean isProjectFile(@NotNull VirtualFile file) { + if (ProjectFileIndex.SERVICE.getInstance(myProject).isInContent(file)) return true; + if (myProject instanceof ProjectEx) { IProjectStore store = ((ProjectEx)myProject).getStateStore(); @@ -115,9 +119,12 @@ public class NonProjectFileWritingAccessProvider extends WritingAccessProvider { } if (file.equals(store.getWorkspaceFile()) || file.equals(store.getProjectFile())) return true; + for (Module each : ModuleManager.getInstance(myProject).getModules()) { + if (file.equals(each.getModuleFile())) return true; + } } - return ProjectFileIndex.SERVICE.getInstance(myProject).isInContent(file); + return false; } @TestOnly diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java index 2c5106353696..fd6dd2edb0a9 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java @@ -21,6 +21,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.application.impl.ApplicationImpl; +import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.components.impl.ComponentManagerImpl; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.actionSystem.EditorActionManager; @@ -29,6 +30,10 @@ import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl; import com.intellij.openapi.fileEditor.impl.NonProjectFileNotificationPanel; import com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessProvider; import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider; +import com.intellij.openapi.module.EmptyModuleType; +import com.intellij.openapi.module.ModifiableModuleModel; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ProjectFileIndex; @@ -84,7 +89,7 @@ public class NonProjectFileAccessTest extends HeavyFileEditorManagerTestCase { assertNull(getNotificationPanel(nonProjectFile)); } - public void testAccessToFilesUnderProjectRootAndDotIdea() throws Exception { + public void testAccessToProjectSystemFiles() throws Exception { saveProject(); VirtualFile fileUnderProjectDir = new WriteAction() { @Override @@ -100,6 +105,41 @@ public class NonProjectFileAccessTest extends HeavyFileEditorManagerTestCase { typeAndCheck(fileUnderProjectDir, false); } + public void testAccessToModuleSystemFiles() throws Exception { + final Module moduleWithoutContentRoot = new WriteCommandAction(getProject()) { + @Override + protected void run(@NotNull Result result) throws Throwable { + String moduleName; + ModifiableModuleModel moduleModel = ModuleManager.getInstance(getProject()).getModifiableModel(); + try { + VirtualFile moduleDir = getProject().getBaseDir().createChildDirectory(this, "moduleWithoutContentRoot"); + moduleName = moduleModel.newModule(moduleDir + "/moduleWithoutContentRoot.iml", EmptyModuleType.EMPTY_MODULE).getName(); + moduleModel.commit(); + } + catch (Throwable t) { + moduleModel.dispose(); + throw t; + } + + result.setResult(ModuleManager.getInstance(getProject()).findModuleByName(moduleName)); + } + }.execute().getResultObject(); + saveProject(); + + VirtualFile fileUnderModuleDir = new WriteAction() { + @Override + protected void run(@NotNull Result result) throws Throwable { + result.setResult(moduleWithoutContentRoot.getModuleFile().getParent().createChildData(this, "fileUnderModuleDir.txt")); + } + }.execute().getResultObject(); + + assertFalse(ProjectFileIndex.SERVICE.getInstance(getProject()).isInContent(fileUnderModuleDir)); + + typeAndCheck(moduleWithoutContentRoot.getModuleFile(), true); + typeAndCheck(myModule.getModuleFile(), true); + typeAndCheck(fileUnderModuleDir, false); + } + private void saveProject() { ApplicationImpl app = (ApplicationImpl)ApplicationManager.getApplication(); boolean save = app.isDoNotSave(); From 482491a8f7224925709f4412851a9dd1cad0964b Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 23 Apr 2014 11:03:59 +0200 Subject: [PATCH 52/86] Platform: Local History can survive for more than 30 days now (int overflow fixed) --- .../src/com/intellij/history/integration/LocalHistoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java index 8660084a572b..5d3d7e2b397c 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java @@ -128,7 +128,7 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone public void disposeComponent() { if (!isInitialized.getAndSet(false)) return; - long period = Registry.intValue("localHistory.daysToKeep") * 1000 * 60 * 60 * 24; + long period = Registry.intValue("localHistory.daysToKeep") * 1000L * 60L * 60L * 24L; VirtualFileManager fm = VirtualFileManager.getInstance(); fm.removeVirtualFileListener(myEventDispatcher); From c1d9f5f1ba50a85849f3547a3bc514406ac23b05 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 23 Apr 2014 13:24:58 +0400 Subject: [PATCH 53/86] fixed PY-12696 Create VirtualEnv: when adding first base interpreter it is not selected right away --- python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java | 1 + 1 file changed, 1 insertion(+) diff --git a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java index 9236e4e2c4f4..6ffcd0f1240d 100644 --- a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java +++ b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java @@ -366,6 +366,7 @@ public class CreateVirtualEnvDialog extends IdeaDialog { private void updateSdkList(final List allSdks, @Nullable Sdk initialSelection) { mySdkCombo.setRenderer(new PySdkListCellRenderer()); mySdkCombo.setModel(new CollectionComboBoxModel(allSdks, initialSelection)); + checkValid(); } @Override From 5651ab584e2bafba635784226cc2449432795fa3 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 23 Apr 2014 11:50:30 +0200 Subject: [PATCH 54/86] IDEA-123775 (String.equals("") inspection fixes code incorrectly) --- .../StringEqualsEmptyStringInspection.java | 86 ++++++++++++++----- .../NullCheckAlreadyPresent.after.java | 12 +++ .../NullCheckAlreadyPresent.java | 12 +++ .../StringEqualsEmptyStringFixTest.java | 3 +- 4 files changed, 92 insertions(+), 21 deletions(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_isempty/NullCheckAlreadyPresent.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_isempty/NullCheckAlreadyPresent.java diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringEqualsEmptyStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringEqualsEmptyStringInspection.java index ebd8449909e6..69c2bad8242b 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringEqualsEmptyStringInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringEqualsEmptyStringInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ package com.siyeh.ig.performance; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; import com.siyeh.HardcodedMethodConstants; @@ -27,6 +29,7 @@ import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.PsiReplacementUtil; import com.siyeh.ig.psiutils.BoolUtils; +import com.siyeh.ig.psiutils.EquivalenceChecker; import com.siyeh.ig.psiutils.ExpressionUtils; import com.siyeh.ig.psiutils.TypeUtils; import org.jetbrains.annotations.NonNls; @@ -97,19 +100,19 @@ public class StringEqualsEmptyStringInspection extends BaseInspection { } final PsiExpression qualifier = expression.getQualifierExpression(); final PsiExpression argument = arguments[0]; - final String variableText; + final PsiExpression checkedExpression; final boolean addNullCheck; if (ExpressionUtils.isEmptyStringLiteral(argument)) { - variableText = getRemainingText(qualifier); + checkedExpression = getCheckedExpression(qualifier); addNullCheck = false; } else { - variableText = getRemainingText(argument); - addNullCheck = true; + checkedExpression = getCheckedExpression(argument); + addNullCheck = !isCheckedForNull(checkedExpression); } - StringBuilder newExpression; + final StringBuilder newExpression; if (addNullCheck) { - newExpression = new StringBuilder(variableText); + newExpression = new StringBuilder(checkedExpression.getText()); newExpression.append("!=null&&"); } else { newExpression = new StringBuilder(""); @@ -121,38 +124,81 @@ public class StringEqualsEmptyStringInspection extends BaseInspection { if (BoolUtils.isNegation(parentExpression)) { expressionToReplace = parentExpression; if (useIsEmpty) { - newExpression.append('!').append(variableText).append(".isEmpty()"); + newExpression.append('!').append(checkedExpression.getText()).append(".isEmpty()"); } else { - newExpression.append(variableText).append(".length()!=0"); + newExpression.append(checkedExpression.getText()).append(".length()!=0"); } } else { expressionToReplace = call; if (useIsEmpty) { - newExpression.append(variableText).append(".isEmpty()"); + newExpression.append(checkedExpression.getText()).append(".isEmpty()"); } else { - newExpression.append(variableText).append(".length()==0"); + newExpression.append(checkedExpression.getText()).append(".length()==0"); } } } else { expressionToReplace = call; if (useIsEmpty) { - newExpression.append(variableText).append(".isEmpty()"); + newExpression.append(checkedExpression.getText()).append(".isEmpty()"); } else { - newExpression.append(variableText).append(".length()==0"); + newExpression.append(checkedExpression.getText()).append(".length()==0"); } } PsiReplacementUtil.replaceExpression(expressionToReplace, newExpression.toString()); } - private String getRemainingText(PsiExpression expression) { - if (useIsEmpty || - !(expression instanceof PsiMethodCallExpression)) { - return expression.getText(); + private static boolean isCheckedForNull(PsiExpression expression) { + final PsiPolyadicExpression polyadicExpression = + PsiTreeUtil.getParentOfType(expression, PsiPolyadicExpression.class, true, PsiStatement.class, PsiVariable.class); + if (polyadicExpression == null) { + return false; + } + final IElementType tokenType = polyadicExpression.getOperationTokenType(); + for (PsiExpression operand : polyadicExpression.getOperands()) { + if (PsiTreeUtil.isAncestor(operand, expression, true)) { + return false; + } + if (!(operand instanceof PsiBinaryExpression)) { + continue; + } + final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)operand; + final IElementType operationTokenType = binaryExpression.getOperationTokenType(); + if (JavaTokenType.ANDAND.equals(tokenType)) { + if (!JavaTokenType.NE.equals(operationTokenType)) { + continue; + } + } + else if (JavaTokenType.OROR.equals(tokenType)) { + if (!JavaTokenType.EQEQ.equals(operationTokenType)) { + continue; + } + } + else { + continue; + } + final PsiExpression lhs = binaryExpression.getLOperand(); + final PsiExpression rhs = binaryExpression.getROperand(); + if (rhs == null) { + continue; + } + if (PsiType.NULL.equals(lhs.getType()) && EquivalenceChecker.expressionsAreEquivalent(expression, rhs)) { + return true; + } + else if (PsiType.NULL.equals(rhs.getType()) && EquivalenceChecker.expressionsAreEquivalent(expression, lhs)) { + return true; + } + } + return false; + } + + private PsiExpression getCheckedExpression(PsiExpression expression) { + if (useIsEmpty || !(expression instanceof PsiMethodCallExpression)) { + return expression; } // to replace stringBuffer.toString().equals("") with // stringBuffer.length() == 0 @@ -161,15 +207,15 @@ public class StringEqualsEmptyStringInspection extends BaseInspection { final String referenceName = methodExpression.getReferenceName(); final PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); if (qualifierExpression == null) { - return expression.getText(); + return expression; } final PsiType type = qualifierExpression.getType(); if (HardcodedMethodConstants.TO_STRING.equals(referenceName) && type != null && (type.equalsToText( CommonClassNames.JAVA_LANG_STRING_BUFFER) || type.equalsToText(CommonClassNames.JAVA_LANG_STRING_BUILDER))) { - return qualifierExpression.getText(); + return qualifierExpression; } else { - return expression.getText(); + return expression; } } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_isempty/NullCheckAlreadyPresent.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_isempty/NullCheckAlreadyPresent.after.java new file mode 100644 index 000000000000..7277bd021670 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_isempty/NullCheckAlreadyPresent.after.java @@ -0,0 +1,12 @@ +package com.siyeh.igfixes.performance.replace_with_isempty; + +public class NullCheckAlreadyPresent { + + String[] splitProperties = {"1","2"}; + + public void someAction() { + if (splitProperties[1] != null && splitProperties[1].isEmpty()) { + System.out.println(""); + } + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_isempty/NullCheckAlreadyPresent.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_isempty/NullCheckAlreadyPresent.java new file mode 100644 index 000000000000..e91b650758e2 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_isempty/NullCheckAlreadyPresent.java @@ -0,0 +1,12 @@ +package com.siyeh.igfixes.performance.replace_with_isempty; + +public class NullCheckAlreadyPresent { + + String[] splitProperties = {"1","2"}; + + public void someAction() { + if (splitProperties[1] != null && "".equals(splitProperties[1])) { + System.out.println(""); + } + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/performance/StringEqualsEmptyStringFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/performance/StringEqualsEmptyStringFixTest.java index a42fccbda5a6..6bd1cefe6320 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/performance/StringEqualsEmptyStringFixTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/performance/StringEqualsEmptyStringFixTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 Bas Leijdekkers + * Copyright 2012-2014 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,4 +31,5 @@ public class StringEqualsEmptyStringFixTest extends IGQuickFixesTestCase { public void testSimple() { doTest(); } public void testNullCheck() { doTest(); } + public void testNullCheckAlreadyPresent() { doTest(); } } From aa6fb9f094502b9f37021f20b45997d25a9d8f93 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Wed, 23 Apr 2014 12:25:09 +0400 Subject: [PATCH 55/86] remove 'Strip common indent' setting from UI (IDEA-67767) --- .../options/editor/EditorOptionsPanel.form | 13 ++----------- .../options/editor/EditorOptionsPanel.java | 5 ----- .../editor/richcopy/TextWithMarkupProcessor.java | 2 +- .../editor/richcopy/settings/RichCopySettings.java | 9 --------- .../src/messages/ApplicationBundle.properties | 1 - .../src/misc/registry.properties | 1 + 6 files changed, 4 insertions(+), 27 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form index 2d795f480513..3e5c8a0f1d88 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form @@ -446,7 +446,7 @@
    - + @@ -455,17 +455,8 @@ - + - - - - - - - - - diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.java b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.java index dbedfc02fffa..9e5d8558b4d1 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.java @@ -97,7 +97,6 @@ public class EditorOptionsPanel { private JBLabel myQuickDocDelayLabel; private JTextField myQuickDocDelayTextField; private JComboBox myRichCopyColorSchemeComboBox; - private JCheckBox myRichCopyStripWhitespaceCheckBox; private static final String ACTIVE_COLOR_SCHEME = ApplicationBundle.message("combobox.richcopy.color.scheme.active"); @@ -224,8 +223,6 @@ public class EditorOptionsPanel { if (!StringUtil.isEmpty(toSelect)) { myRichCopyColorSchemeComboBox.setSelectedItem(toSelect); } - - myRichCopyStripWhitespaceCheckBox.setSelected(settings.isStripIndents()); } public void apply() throws ConfigurationException { @@ -332,7 +329,6 @@ public class EditorOptionsPanel { if (item instanceof String) { settings.setSchemeName(item.toString()); } - settings.setStripIndents(myRichCopyStripWhitespaceCheckBox.isSelected()); restartDaemons(); } @@ -454,7 +450,6 @@ public class EditorOptionsPanel { RichCopySettings settings = RichCopySettings.getInstance(); isModified |= !Comparing.equal(settings.getSchemeName(), myRichCopyColorSchemeComboBox.getSelectedItem()); - isModified |= isModified(myRichCopyStripWhitespaceCheckBox, settings.isStripIndents()); return isModified; } diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java index af2309daf4a5..da8c1f0cb0e4 100644 --- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java +++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java @@ -84,7 +84,7 @@ public class TextWithMarkupProcessor implements CopyPastePostProcessor p = calcIndentSymbolsToStrip(editor.getDocument(), firstCaret.getSelectionStart(), firstCaret.getSelectionEnd()); firstLineStartOffset = p.first; indentSymbolsToStrip = p.second; diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/settings/RichCopySettings.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/settings/RichCopySettings.java index ec99560b9753..c2a58bcdc109 100644 --- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/settings/RichCopySettings.java +++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/settings/RichCopySettings.java @@ -36,7 +36,6 @@ public class RichCopySettings implements PersistentStateComponent Date: Wed, 23 Apr 2014 12:55:02 +0400 Subject: [PATCH 56/86] use service instead of application component (IDEA-67767) --- .../richcopy/settings/RichCopySettings.java | 19 ++----------------- .../src/META-INF/LangExtensions.xml | 1 + .../src/componentSets/Lang.xml | 4 ---- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/settings/RichCopySettings.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/settings/RichCopySettings.java index c2a58bcdc109..77c2687b4955 100644 --- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/settings/RichCopySettings.java +++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/settings/RichCopySettings.java @@ -15,7 +15,6 @@ */ package com.intellij.openapi.editor.richcopy.settings; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.*; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; @@ -31,7 +30,7 @@ import org.jetbrains.annotations.Nullable; name = "EditorRichCopySettings", storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/editor.rich.copy.xml")} ) -public class RichCopySettings implements PersistentStateComponent, ApplicationComponent { +public class RichCopySettings implements PersistentStateComponent { @NotNull public static final String ACTIVE_GLOBAL_SCHEME_MARKER = "__ACTIVE_GLOBAL_SCHEME__"; @@ -39,7 +38,7 @@ public class RichCopySettings implements PersistentStateComponent + diff --git a/platform/platform-resources/src/componentSets/Lang.xml b/platform/platform-resources/src/componentSets/Lang.xml index 403a2197e950..dc2fabfbeb07 100644 --- a/platform/platform-resources/src/componentSets/Lang.xml +++ b/platform/platform-resources/src/componentSets/Lang.xml @@ -37,10 +37,6 @@ com.intellij.codeInsight.preview.ImageOrColorPreviewManager - - - com.intellij.openapi.editor.richcopy.settings.RichCopySettings - From 43b861b75d3e4505fdade6abe656a08d8afc4da9 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Wed, 23 Apr 2014 13:52:21 +0400 Subject: [PATCH 57/86] don't use borders and insets in output html/rtf (IDEA-67767) --- .../openapi/editor/richcopy/view/HtmlTransferableData.java | 6 ++---- .../openapi/editor/richcopy/view/RtfTransferableData.java | 4 +--- .../testData/editor/richcopy/BlockSelection.html | 4 ++-- .../testData/editor/richcopy/BlockSelection.rtf | 4 ++-- .../testData/editor/richcopy/NormalSelection.html | 4 ++-- .../testData/editor/richcopy/NormalSelection.rtf | 4 ++-- 6 files changed, 11 insertions(+), 15 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/view/HtmlTransferableData.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/view/HtmlTransferableData.java index c6224026bc11..ea200c201b6f 100644 --- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/view/HtmlTransferableData.java +++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/view/HtmlTransferableData.java @@ -58,9 +58,7 @@ public class HtmlTransferableData extends AbstractSyntaxAwareReaderTransferableD myFontNameRegistry = mySyntaxInfo.getFontNameRegistry(); try { buildColorMap(); - myResultBuffer.append("
    ") - .append("
    "); + myResultBuffer.append(""); } finally { myResultBuffer = null; diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/view/RtfTransferableData.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/view/RtfTransferableData.java index 996e1c130054..d37da66b6f3d 100644 --- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/view/RtfTransferableData.java +++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/view/RtfTransferableData.java @@ -87,11 +87,9 @@ public class RtfTransferableData extends AbstractSyntaxAwareInputStreamTransfera } private static void rectangularBackground(@NotNull SyntaxInfo syntaxInfo, @NotNull StringBuilder buffer, @NotNull Runnable next) { - buffer.append("\n\\s0\\box\\brdrhair\\brdrcf").append(syntaxInfo.getDefaultForeground()).append("\\brsp317").append("\\cbpat") - .append(syntaxInfo.getDefaultBackground()); + buffer.append("\n\\s0\\box").append("\\cbpat").append(syntaxInfo.getDefaultBackground()); saveBackground(buffer, syntaxInfo.getDefaultBackground()); next.run(); - buffer.append("\\par"); } private static void content(@NotNull SyntaxInfo syntaxInfo, @NotNull StringBuilder buffer, @NotNull String rawText, int maxLength) { diff --git a/platform/platform-tests/testData/editor/richcopy/BlockSelection.html b/platform/platform-tests/testData/editor/richcopy/BlockSelection.html index 9f8c46f79625..1b92b6c49e76 100644 --- a/platform/platform-tests/testData/editor/richcopy/BlockSelection.html +++ b/platform/platform-tests/testData/editor/richcopy/BlockSelection.html @@ -1,3 +1,3 @@ -
     int field;
    +
     int field;
     
    - public static void main(String[] args) {
    \ No newline at end of file + public static void main(String[] args) { \ No newline at end of file diff --git a/platform/platform-tests/testData/editor/richcopy/BlockSelection.rtf b/platform/platform-tests/testData/editor/richcopy/BlockSelection.rtf index 5285d4d58390..6ae37249c24e 100644 --- a/platform/platform-tests/testData/editor/richcopy/BlockSelection.rtf +++ b/platform/platform-tests/testData/editor/richcopy/BlockSelection.rtf @@ -1,7 +1,7 @@ {\rtf1\ansi\deff0{\colortbl;\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue128;} {\fonttbl{\f1 ___PLATFORM_SPECIFIC___;}} -\s0\box\brdrhair\brdrcf1\brsp317\cbpat2\cb2 +\s0\box\cbpat2\cb2 \cf3\f1\plain \cf3\f1\fs___PLATFORM_SPECIFIC___\b int \cf1\plain @@ -15,4 +15,4 @@ field; \cf3\f1\fs___PLATFORM_SPECIFIC___\b public static void \cf1\plain \cf1\f1\fs___PLATFORM_SPECIFIC___ -main(String[] args) \{\par} \ No newline at end of file +main(String[] args) \{} \ No newline at end of file diff --git a/platform/platform-tests/testData/editor/richcopy/NormalSelection.html b/platform/platform-tests/testData/editor/richcopy/NormalSelection.html index 18efe35b80f1..e1abddb14277 100644 --- a/platform/platform-tests/testData/editor/richcopy/NormalSelection.html +++ b/platform/platform-tests/testData/editor/richcopy/NormalSelection.html @@ -1,8 +1,8 @@ -
    public class Basic {
    +
    public class Basic {
       int field;
     
       public static void main(String[] args) {
         System.out.println("Hello\tworld!");
       }
     }
    -
    \ No newline at end of file + \ No newline at end of file diff --git a/platform/platform-tests/testData/editor/richcopy/NormalSelection.rtf b/platform/platform-tests/testData/editor/richcopy/NormalSelection.rtf index 5a7393a940c7..39ee491cb9c8 100644 --- a/platform/platform-tests/testData/editor/richcopy/NormalSelection.rtf +++ b/platform/platform-tests/testData/editor/richcopy/NormalSelection.rtf @@ -1,7 +1,7 @@ {\rtf1\ansi\deff0{\colortbl;\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue0;} {\fonttbl{\f1 ___PLATFORM_SPECIFIC___;}} -\s0\box\brdrhair\brdrcf1\brsp317\cbpat2\cb2\cf3\f1\plain +\s0\box\cbpat2\cb2\cf3\f1\plain \cf3\f1\fs___PLATFORM_SPECIFIC___\b public class \cf1\plain \cf1\f1\fs___PLATFORM_SPECIFIC___ @@ -32,4 +32,4 @@ world!"\cf1\plain \}\line \}\line -\par} \ No newline at end of file +} \ No newline at end of file From e6d8c987fd6a2a4ff4c589f8da6d79729b78408a Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Wed, 23 Apr 2014 13:58:57 +0400 Subject: [PATCH 58/86] extract right arrow --- .../postfix/completion/PostfixTemplateLookupElement.java | 8 ++------ .../structureView/impl/java/JavaClassTreeElementBase.java | 3 +-- platform/util/src/com/intellij/util/ui/UIUtil.java | 6 ++++++ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupElement.java index 73bbf697f633..c01f6073845a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupElement.java @@ -19,8 +19,8 @@ import com.intellij.codeInsight.lookup.LookupElementPresentation; import com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement; import com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate; import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate; -import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; public class PostfixTemplateLookupElement extends CustomLiveTemplateLookupElement { @@ -44,15 +44,11 @@ public class PostfixTemplateLookupElement extends CustomLiveTemplateLookupElemen public void renderElement(LookupElementPresentation presentation) { super.renderElement(presentation); if (sudden) { - presentation.setTailText(" " + arrow() + " " + myTemplate.getExample()); + presentation.setTailText(" " + UIUtil.rightArrow() + " " + myTemplate.getExample()); } else { presentation.setTypeText(myTemplate.getExample()); presentation.setTypeGrayed(true); } } - - private static String arrow() { - return SystemInfo.isMac ? "→" : "->"; - } } diff --git a/java/java-structure-view/src/com/intellij/ide/structureView/impl/java/JavaClassTreeElementBase.java b/java/java-structure-view/src/com/intellij/ide/structureView/impl/java/JavaClassTreeElementBase.java index 50cc8c4cd5e4..a1d2468ddc31 100644 --- a/java/java-structure-view/src/com/intellij/ide/structureView/impl/java/JavaClassTreeElementBase.java +++ b/java/java-structure-view/src/com/intellij/ide/structureView/impl/java/JavaClassTreeElementBase.java @@ -72,8 +72,7 @@ public abstract class JavaClassTreeElementBase extends myLocation = ""; } else { myLocation = cls.getName(); - char rightArrow = '\u2192'; - myLocation = UIUtil.getLabelFont().canDisplay(rightArrow) ? rightArrow + myLocation : "->" + myLocation; + myLocation = UIUtil.rightArrow() + myLocation; } } else { myLocation = ""; diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 2195ede58d47..f0a900b56e8f 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -2943,4 +2943,10 @@ public class UIUtil { } return genericFontFamily; } + + @NotNull + public static String rightArrow() { + char rightArrow = '\u2192'; + return getLabelFont().canDisplay(rightArrow) ? String.valueOf(rightArrow) : "->"; + } } From 4bc9f42f8b227d01ba2e5bec8175567532fb8fa4 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 23 Apr 2014 14:16:11 +0400 Subject: [PATCH 59/86] fixed PY-12690 Detected from creating virtualenv interpreter has invalid slashes --- .../com/jetbrains/python/sdk/CreateVirtualEnvDialog.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java index 6ffcd0f1240d..0a9d63a24a31 100644 --- a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java +++ b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java @@ -272,16 +272,18 @@ public class CreateVirtualEnvDialog extends IdeaDialog { FileChooser.chooseFiles(descriptor, myProject, suggestedDir, new FileChooser.FileChooserConsumer() { @Override public void consume(List selectedFiles) { - final String path = selectedFiles.get(0).getPath(); + String path = selectedFiles.get(0).getPath(); if (sdkType.isValidSdkHome(path)) { + path = FileUtil.toSystemDependentName(path); Sdk newSdk = null; for (Sdk sdk : allSdks) { if (path.equals(sdk.getHomePath())) { newSdk = sdk; } } - if (newSdk == null) + if (newSdk == null) { newSdk = new PyDetectedSdk(path); + } consumer.consume(newSdk); } } From 40d91f5d13c0544176664a83b3c06452bf4c7fd7 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 23 Apr 2014 14:23:20 +0400 Subject: [PATCH 60/86] IDEA-63106 new inspections added to InconsistentResourceBundleInspection --- .../ui/MultipleCheckboxOptionsPanel.java | 59 ++--- .../codeInspection/ui/OptionAccessor.java | 65 +++++ .../codeInspection/inspection-black-list.txt | 2 +- .../src/messages/InspectionsBundle.properties | 5 + plugins/java-i18n/src/META-INF/plugin.xml | 2 +- .../InconsistentResourceBundleInspection.java | 236 ------------------ .../codeInspection/i18n/JavaI18nUtil.java | 40 ++- ...uplicatedPropertiesInspectionProvider.java | 79 ++++++ ...stentPropertiesEndsInspectionProvider.java | 104 ++++++++ .../InconsistentResourceBundleInspection.java | 206 +++++++++++++++ ...stentResourceBundleInspectionProvider.java | 47 ++++ ...MissingTranslationsInspectionProvider.java | 87 +++++++ ...tiesKeysConsistencyInspectionProvider.java | 79 ++++++ ...pertiesPlaceholdersInspectionProvider.java | 92 +++++++ .../InconsistentPlaceholders/expected.xml | 23 ++ .../src/prop.properties | 5 + .../src/prop_en.properties | 4 + .../src/prop_en_CA.properties | 3 + .../InconsistentValuesEnds/expected.xml | 13 + .../src/prop.properties | 4 + .../src/prop_en.properties | 3 + .../src/prop_en_CA.properties | 4 + .../Simple/expected.xml | 40 +++ .../Simple/src/Bu.properties | 17 ++ .../Simple/src/Bu_fr.properties | 1 + .../Simple/src/Bu_fr_SSS.properties | 2 + .../spellchecker}/ClassName.java | 0 .../spellchecker}/CorrectJava.java | 0 .../spellchecker}/DocComment.java | 0 .../spellchecker}/FieldName.java | 0 .../spellchecker}/Japanese.java | 0 .../spellchecker}/LocalVariableName.java | 0 .../spellchecker}/MethodName.java | 0 .../spellchecker}/StringLiteral.java | 0 .../spellchecker}/StringLiteralEscaping.java | 0 .../spellchecker}/Suppressions.java | 0 .../spellchecker}/TypoInJava.java | 0 .../spellchecker}/VarArg.java | 0 ...onsistentResourceBundleInspectionTest.java | 67 +++++ .../JavaSpellcheckerInspectionTest.java | 2 +- .../InconsistentResourceBundle.html | 43 +++- 41 files changed, 1040 insertions(+), 294 deletions(-) create mode 100644 platform/analysis-api/src/com/intellij/codeInspection/ui/OptionAccessor.java delete mode 100644 plugins/java-i18n/src/com/intellij/codeInspection/i18n/InconsistentResourceBundleInspection.java create mode 100644 plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/DuplicatedPropertiesInspectionProvider.java create mode 100644 plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/InconsistentPropertiesEndsInspectionProvider.java create mode 100644 plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/InconsistentResourceBundleInspection.java create mode 100644 plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/InconsistentResourceBundleInspectionProvider.java create mode 100644 plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/MissingTranslationsInspectionProvider.java create mode 100644 plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/PropertiesKeysConsistencyInspectionProvider.java create mode 100644 plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/PropertiesPlaceholdersInspectionProvider.java create mode 100644 plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/expected.xml create mode 100644 plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/src/prop.properties create mode 100644 plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/src/prop_en.properties create mode 100644 plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/src/prop_en_CA.properties create mode 100644 plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/expected.xml create mode 100644 plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/src/prop.properties create mode 100644 plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/src/prop_en.properties create mode 100644 plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/src/prop_en_CA.properties create mode 100644 plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/expected.xml create mode 100644 plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu.properties create mode 100644 plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu_fr.properties create mode 100644 plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu_fr_SSS.properties rename plugins/java-i18n/testData/{inspection => inspections/spellchecker}/ClassName.java (100%) rename plugins/java-i18n/testData/{inspection => inspections/spellchecker}/CorrectJava.java (100%) rename plugins/java-i18n/testData/{inspection => inspections/spellchecker}/DocComment.java (100%) rename plugins/java-i18n/testData/{inspection => inspections/spellchecker}/FieldName.java (100%) rename plugins/java-i18n/testData/{inspection => inspections/spellchecker}/Japanese.java (100%) rename plugins/java-i18n/testData/{inspection => inspections/spellchecker}/LocalVariableName.java (100%) rename plugins/java-i18n/testData/{inspection => inspections/spellchecker}/MethodName.java (100%) rename plugins/java-i18n/testData/{inspection => inspections/spellchecker}/StringLiteral.java (100%) rename plugins/java-i18n/testData/{inspection => inspections/spellchecker}/StringLiteralEscaping.java (100%) rename plugins/java-i18n/testData/{inspection => inspections/spellchecker}/Suppressions.java (100%) rename plugins/java-i18n/testData/{inspection => inspections/spellchecker}/TypoInJava.java (100%) rename plugins/java-i18n/testData/{inspection => inspections/spellchecker}/VarArg.java (100%) create mode 100644 plugins/java-i18n/testSrc/com/intellij/codeInspection/i18n/InconsistentResourceBundleInspectionTest.java diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ui/MultipleCheckboxOptionsPanel.java b/platform/analysis-api/src/com/intellij/codeInspection/ui/MultipleCheckboxOptionsPanel.java index da36da2926c1..a43b60adf74f 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/ui/MultipleCheckboxOptionsPanel.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/ui/MultipleCheckboxOptionsPanel.java @@ -22,22 +22,25 @@ import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; -import java.lang.reflect.Field; public class MultipleCheckboxOptionsPanel extends JPanel { - private final InspectionProfileEntry owner; + private final OptionAccessor myOptionAccessor; - public MultipleCheckboxOptionsPanel(InspectionProfileEntry owner) { + public MultipleCheckboxOptionsPanel(final InspectionProfileEntry owner) { + this(new OptionAccessor.Default(owner)); + } + + public MultipleCheckboxOptionsPanel(final OptionAccessor optionAccessor) { super(new GridBagLayout()); - this.owner = owner; + myOptionAccessor = optionAccessor; } public void addCheckbox(String label, @NonNls String property) { - final boolean selected = getPropertyValue(owner, property); + final boolean selected = myOptionAccessor.getOption(property); final JCheckBox checkBox = new JCheckBox(label, selected); - configureCheckbox(owner, property, checkBox); + configureCheckbox(myOptionAccessor, property, checkBox); final GridBagConstraints constraints = new GridBagConstraints(); constraints.anchor = GridBagConstraints.FIRST_LINE_START; constraints.gridx = 0; @@ -54,59 +57,33 @@ public class MultipleCheckboxOptionsPanel extends JPanel { add(checkBox, constraints); } - private static void configureCheckbox(InspectionProfileEntry owner, String property, JCheckBox checkBox) { + private static void configureCheckbox(OptionAccessor accessor, String property, JCheckBox checkBox) { final ButtonModel model = checkBox.getModel(); - final CheckboxChangeListener changeListener = new CheckboxChangeListener(owner, property, model); + final CheckboxChangeListener changeListener = new CheckboxChangeListener(accessor, property, model); model.addChangeListener(changeListener); } public static void initAndConfigureCheckbox(InspectionProfileEntry owner, String property, JCheckBox checkBox) { - checkBox.setSelected(getPropertyValue(owner, property)); - configureCheckbox(owner, property, checkBox); - } - - private static boolean getPropertyValue(InspectionProfileEntry owner, - String property) { - try { - final Class aClass = owner.getClass(); - final Field field = aClass.getField(property); - return field.getBoolean(owner); - } catch (IllegalAccessException ignored) { - return false; - } catch (NoSuchFieldException ignored) { - return false; - } + OptionAccessor optionAccessor = new OptionAccessor.Default(owner); + checkBox.setSelected(optionAccessor.getOption(property)); + configureCheckbox(optionAccessor, property, checkBox); } private static class CheckboxChangeListener implements ChangeListener { - private final InspectionProfileEntry owner; + private final OptionAccessor myAccessor; private final String property; private final ButtonModel model; - CheckboxChangeListener(InspectionProfileEntry owner, String property, - ButtonModel model) { - this.owner = owner; + CheckboxChangeListener(OptionAccessor myAccessor, String property, ButtonModel model) { + this.myAccessor = myAccessor; this.property = property; this.model = model; } @Override public void stateChanged(ChangeEvent e) { - setPropertyValue(owner, property, model.isSelected()); + myAccessor.setOption(property, model.isSelected()); } - private static void setPropertyValue(InspectionProfileEntry owner, - String property, - boolean selected) { - try { - final Class aClass = owner.getClass(); - final Field field = aClass.getField(property); - field.setBoolean(owner, selected); - } catch (IllegalAccessException ignored) { - // nothing - } catch (NoSuchFieldException ignored) { - // nothing - } - } } } \ No newline at end of file diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ui/OptionAccessor.java b/platform/analysis-api/src/com/intellij/codeInspection/ui/OptionAccessor.java new file mode 100644 index 000000000000..eecd6d764d10 --- /dev/null +++ b/platform/analysis-api/src/com/intellij/codeInspection/ui/OptionAccessor.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection.ui; + +import com.intellij.codeInspection.InspectionProfileEntry; + +import java.lang.reflect.Field; + +/** + * @author Dmitry Batkovich + */ +public interface OptionAccessor { + + boolean getOption(String optionName); + + void setOption(String optionName, boolean optionValue); + + class Default implements OptionAccessor { + private final InspectionProfileEntry myInspection; + + public Default(final InspectionProfileEntry inspection) { + myInspection = inspection; + } + + @Override + public boolean getOption(final String optionName) { + try { + final Class aClass = myInspection.getClass(); + final Field field = aClass.getField(optionName); + return field.getBoolean(myInspection); + } catch (IllegalAccessException ignored) { + return false; + } catch (NoSuchFieldException ignored) { + return false; + } + } + + @Override + public void setOption(final String optionName, boolean optionValue) { + try { + final Class aClass = myInspection.getClass(); + final Field field = aClass.getField(optionName); + field.setBoolean(myInspection, optionValue); + } catch (IllegalAccessException ignored) { + // nothing + } catch (NoSuchFieldException ignored) { + // nothing + } + } + } + +} diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/inspection-black-list.txt b/platform/analysis-impl/src/com/intellij/codeInspection/inspection-black-list.txt index 18ea3ddef8d5..5b937f501617 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/inspection-black-list.txt +++ b/platform/analysis-impl/src/com/intellij/codeInspection/inspection-black-list.txt @@ -10,7 +10,7 @@ com.intellij.codeInspection.htmlInspections.HtmlUnknownAttributeInspection com.intellij.codeInspection.htmlInspections.HtmlUnknownTagInspection com.intellij.codeInspection.htmlInspections.RequiredAttributesInspection com.intellij.codeInspection.i18n.I18nInspection -com.intellij.codeInspection.i18n.InconsistentResourceBundleInspection +com.intellij.codeInspection.i18n.inconsistentResourceBundle.InconsistentResourceBundleInspection com.intellij.codeInspection.javaDoc.JavaDocLocalInspection com.intellij.codeInspection.localCanBeFinal.LocalCanBeFinal com.intellij.codeInspection.miscGenerics.SuspiciousCollectionsMethodCallsInspection diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties index 191cc7fafb28..b9d5b98cce46 100644 --- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties +++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties @@ -633,6 +633,11 @@ inconsistent.bundle.untranslated.property.error=Untranslated property ''{0}''. S inconsistent.bundle.report.missing.translations=Report &missing translations inconsistent.bundle.report.inconsistent.properties=Report &inconsistent properties inconsistent.bundle.report.duplicate.properties.values=Report properties &overridden with the same value +inconsistent.bundle.report.inconsistent.properties.placeholders=Report properties with inconsistent &placeholders +inconsistent.bundle.report.inconsistent.properties.ends=Report properties with inconsistent &ends +inconsistent.bundle.property.inconsistent.placeholders=Inconsistent count of placeholders: found {0} in ''{1}'' +inconsistent.bundle.property.inconsistent.end.parent.end.from.check.symbols=Inconsistent property value end ''{0}'' but found ''{1}'' in ''{2}'' +inconsistent.bundle.property.inconsistent.end=Inconsistent property value end '{0}' inconsistent.bundle.property.inherited.with.the.same.value=Property inherited from the ''{0}'' file with the same value edit.inspection.options=Edit ''{0}'' Options offline.view.title=Offline View diff --git a/plugins/java-i18n/src/META-INF/plugin.xml b/plugins/java-i18n/src/META-INF/plugin.xml index 02c6b05c863b..399a14245c2e 100644 --- a/plugins/java-i18n/src/META-INF/plugin.xml +++ b/plugins/java-i18n/src/META-INF/plugin.xml @@ -37,7 +37,7 @@ + implementationClass="com.intellij.codeInspection.i18n.inconsistentResourceBundle.InconsistentResourceBundleInspection"/> > VISITED_BUNDLES_KEY = Key.create("VISITED_BUNDLES_KEY"); - @Override - public void inspectionStarted(@NotNull InspectionManager manager, - @NotNull GlobalInspectionContext globalContext, - @NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor) { - globalContext.putUserData(VISITED_BUNDLES_KEY, new THashSet()); - } - - @Override - public void checkFile(@NotNull PsiFile file, - @NotNull InspectionManager manager, - @NotNull ProblemsHolder problemsHolder, - @NotNull GlobalInspectionContext globalContext, - @NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor) { - Set visitedBundles = globalContext.getUserData(VISITED_BUNDLES_KEY); - checkFile(file, manager, visitedBundles, globalContext.getRefManager(), problemDescriptionsProcessor); - } - - private void checkFile(@NotNull final PsiFile file, - @NotNull final InspectionManager manager, - @NotNull Set visitedBundles, - RefManager refManager, ProblemDescriptionsProcessor processor) { - if (!(file instanceof PropertiesFile)) return; - final PropertiesFile propertiesFile = (PropertiesFile)file; - ResourceBundle resourceBundle = propertiesFile.getResourceBundle(); - if (!visitedBundles.add(resourceBundle)) return; - List files = resourceBundle.getPropertiesFiles(manager.getProject()); - if (files.size() < 2) return; - BidirectionalMap parents = new BidirectionalMap(); - for (PropertiesFile f : files) { - PropertiesFile parent = PropertiesUtil.getParent(f, files); - if (parent != null) { - parents.put(f, parent); - } - } - Map> keysUpToParent = new THashMap>(); - for (PropertiesFile f : files) { - Set keys = new THashSet(f.getNamesMap().keySet()); - PropertiesFile parent = parents.get(f); - while (parent != null) { - keys.addAll(parent.getNamesMap().keySet()); - parent = parents.get(parent); - } - keysUpToParent.put(f, keys); - } - if (REPORT_MISSING_TRANSLATIONS) { - checkMissingTranslations(parents, files, keysUpToParent, manager, refManager, processor); - } - if (REPORT_INCONSISTENT_PROPERTIES) { - checkConsistency(parents, files, keysUpToParent, manager, refManager, processor); - } - if (REPORT_DUPLICATED_PROPERTIES) { - checkDuplicatedProperties(parents, files, keysUpToParent, manager, refManager, processor); - } - } - - private static void checkDuplicatedProperties(final BidirectionalMap parents, - final List files, - final Map> keysUpToParent, - final InspectionManager manager, - RefManager refManager, - ProblemDescriptionsProcessor processor) { - for (PropertiesFile file : files) { - PropertiesFile parent = parents.get(file); - if (parent == null) continue; - Set parentKeys = keysUpToParent.get(parent); - Set overriddenKeys = new THashSet(file.getNamesMap().keySet()); - overriddenKeys.retainAll(parentKeys); - for (String overriddenKey : overriddenKeys) { - IProperty property = file.findPropertyByKey(overriddenKey); - assert property != null; - while (parent != null) { - IProperty parentProperty = parent.findPropertyByKey(overriddenKey); - if (parentProperty != null && Comparing.strEqual(property.getValue(), parentProperty.getValue())) { - String message = InspectionsBundle.message("inconsistent.bundle.property.inherited.with.the.same.value", parent.getName()); - ProblemDescriptor descriptor = manager.createProblemDescriptor(property.getPsiElement(), message, - RemovePropertyLocalFix.INSTANCE, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false); - processor.addProblemElement(refManager.getReference(file.getContainingFile()), descriptor); - } - parent = parents.get(parent); - } - } - } - } - - private static void checkConsistency(final BidirectionalMap parents, final List files, - final Map> keysUpToParent, - final InspectionManager manager, - RefManager refManager, ProblemDescriptionsProcessor processor) { - for (PropertiesFile file : files) { - PropertiesFile parent = parents.get(file); - Set parentKeys = keysUpToParent.get(parent); - if (parent == null) { - parentKeys = new THashSet(); - for (PropertiesFile otherTopLevelFile : files) { - if (otherTopLevelFile != file && parents.get(otherTopLevelFile) == null) { - parent = otherTopLevelFile; - parentKeys.addAll(otherTopLevelFile.getNamesMap().keySet()); - } - } - if (parent == null) continue; - } - Set keys = new THashSet(file.getNamesMap().keySet()); - keys.removeAll(parentKeys); - for (String inconsistentKey : keys) { - IProperty property = file.findPropertyByKey(inconsistentKey); - assert property != null; - String message = InspectionsBundle.message("inconsistent.bundle.property.error", inconsistentKey, parent.getName()); - ProblemDescriptor descriptor = manager.createProblemDescriptor(property.getPsiElement(), message, false, LocalQuickFix.EMPTY_ARRAY, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING); - processor.addProblemElement(refManager.getReference(file.getContainingFile()), descriptor); - } - } - } - - private static void checkMissingTranslations(final BidirectionalMap parents, - final List files, - final Map> keysUpToParent, - final InspectionManager manager, - RefManager refManager, - ProblemDescriptionsProcessor processor) { - for (PropertiesFile file : files) { - PropertiesFile parent = parents.get(file); - if (parent == null) continue; - List children = parents.getKeysByValue(file); - boolean isLeaf = children == null || children.isEmpty(); - if (!isLeaf) continue; - Set keys = file.getNamesMap().keySet(); - Set parentKeys = new THashSet(keysUpToParent.get(parent)); - if (parent.getLocale().getLanguage().equals(file.getLocale().getLanguage())) { - // properties can be left untranslated in the dialect files - keys = new THashSet(keys); - keys.addAll(parent.getNamesMap().keySet()); - parent = parents.get(parent); - if (parent == null) continue; - parentKeys = new THashSet(keysUpToParent.get(parent)); - } - parentKeys.removeAll(keys); - for (String untranslatedKey : parentKeys) { - IProperty untranslatedProperty = null; - PropertiesFile untranslatedFile = parent; - while (untranslatedFile != null) { - untranslatedProperty = untranslatedFile.findPropertyByKey(untranslatedKey); - if (untranslatedProperty != null) break; - untranslatedFile = parents.get(untranslatedFile); - } - assert untranslatedProperty != null; - String message = InspectionsBundle.message("inconsistent.bundle.untranslated.property.error", untranslatedKey, file.getName()); - ProblemDescriptor descriptor = manager.createProblemDescriptor(untranslatedProperty.getPsiElement(), message, false, LocalQuickFix.EMPTY_ARRAY, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING); - processor.addProblemElement(refManager.getReference(untranslatedFile.getContainingFile()), descriptor); - } - } - } -} diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/JavaI18nUtil.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/JavaI18nUtil.java index 45cd174d7d7a..0d705dc8a47b 100644 --- a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/JavaI18nUtil.java +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/JavaI18nUtil.java @@ -312,30 +312,46 @@ public class JavaI18nUtil extends I18nUtil { } /** - * Returns number of different parameters in i18n message. For example, for string + * Returns number of different message format parameters in property value + * * Class {0} info: Class {0} extends class {1} and implements interface {2} * number of parameters is 3. * + * @param propertyValue + * @return number of parameters from single property or 0 for wrong format + */ + public static int getPropertyValuePlaceholdersCount(final @NotNull String propertyValue) { + try { + return new MessageFormat(propertyValue).getFormatsByArgumentIndex().length; + } catch (final IllegalArgumentException e) { + return 0; + } + } + + /** + * Returns number of different parameters in i18n message. For example, for string + * + * Class {0} info: Class {0} extends class {1} and implements interface {2} in one translation of property + * Class {0} info: Class {0} extends class {1} in other translation of property + * + * number of parameters is 3. + * * @param expression i18n literal * @return number of parameters */ - public static int getPropertyValueParamsMaxCount(final PsiLiteralExpression expression) { + public static int getPropertyValueParamsMaxCount(final @NotNull PsiLiteralExpression expression) { int maxCount = -1; for (PsiReference reference : expression.getReferences()) { if (reference instanceof PsiPolyVariantReference) { for (ResolveResult result : ((PsiPolyVariantReference)reference).multiResolve(false)) { if (result.isValidResult() && result.getElement() instanceof IProperty) { - String value = ((IProperty)result.getElement()).getValue(); - MessageFormat format; try { - format = new MessageFormat(value); - } - catch (Exception e) { - continue; // ignore syntax error - } - try { - int count = format.getFormatsByArgumentIndex().length; - maxCount = Math.max(maxCount, count); + final IProperty property = (IProperty)result.getElement(); + final String propertyValue = property.getValue(); + if (propertyValue == null) { + continue; + } + maxCount = Math.max(maxCount, getPropertyValuePlaceholdersCount(propertyValue)); } catch (IllegalArgumentException ignored) { } diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/DuplicatedPropertiesInspectionProvider.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/DuplicatedPropertiesInspectionProvider.java new file mode 100644 index 000000000000..64c9f38d3a58 --- /dev/null +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/DuplicatedPropertiesInspectionProvider.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection.i18n.inconsistentResourceBundle; + +import com.intellij.codeInspection.*; +import com.intellij.codeInspection.reference.RefManager; +import com.intellij.lang.properties.IProperty; +import com.intellij.lang.properties.RemovePropertyLocalFix; +import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.openapi.util.Comparing; +import com.intellij.util.containers.BidirectionalMap; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Dmitry Batkovich + */ +public class DuplicatedPropertiesInspectionProvider implements InconsistentResourceBundleInspectionProvider { + @NotNull + @Override + public String getName() { + return "REPORT_DUPLICATED_PROPERTIES"; + } + + @NotNull + @Override + public String getPresentableName() { + return InspectionsBundle.message("inconsistent.bundle.report.duplicate.properties.values"); + } + + @Override + public void check(BidirectionalMap parents, + List files, + Map> keysUpToParent, + Map> propertiesFilesNamesMaps, + InspectionManager manager, + RefManager refManager, + ProblemDescriptionsProcessor processor) { + for (PropertiesFile file : files) { + PropertiesFile parent = parents.get(file); + if (parent == null) continue; + Set parentKeys = keysUpToParent.get(parent); + Set overriddenKeys = new THashSet(propertiesFilesNamesMaps.get(file).keySet()); + overriddenKeys.retainAll(parentKeys); + for (String overriddenKey : overriddenKeys) { + IProperty property = file.findPropertyByKey(overriddenKey); + assert property != null; + while (parent != null) { + IProperty parentProperty = parent.findPropertyByKey(overriddenKey); + if (parentProperty != null && Comparing.strEqual(property.getValue(), parentProperty.getValue())) { + String message = InspectionsBundle.message("inconsistent.bundle.property.inherited.with.the.same.value", parent.getName()); + ProblemDescriptor descriptor = manager.createProblemDescriptor(property.getPsiElement(), message, + RemovePropertyLocalFix.INSTANCE, + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false); + processor.addProblemElement(refManager.getReference(file.getContainingFile()), descriptor); + } + parent = parents.get(parent); + } + } + } + } +} diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/InconsistentPropertiesEndsInspectionProvider.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/InconsistentPropertiesEndsInspectionProvider.java new file mode 100644 index 000000000000..ff1e8b6c1daf --- /dev/null +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/InconsistentPropertiesEndsInspectionProvider.java @@ -0,0 +1,104 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection.i18n.inconsistentResourceBundle; + +import com.intellij.codeInspection.*; +import com.intellij.codeInspection.reference.RefManager; +import com.intellij.lang.properties.IProperty; +import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.psi.PsiElement; +import com.intellij.util.containers.BidirectionalMap; +import com.intellij.util.containers.ContainerUtil; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Dmitry Batkovich + */ +public class InconsistentPropertiesEndsInspectionProvider implements InconsistentResourceBundleInspectionProvider { + private static final Set PROPERTY_VALUE_END_CHECK_SYMBOLS = ContainerUtil.newTroveSet('!', '?', '.', ':', ';'); + + @NotNull + @Override + public String getName() { + return "REPORT_INCONSISTENT_PROPERTIES_ENDS"; + } + + @NotNull + @Override + public String getPresentableName() { + return InspectionsBundle.message("inconsistent.bundle.report.inconsistent.properties.ends"); + } + + @Override + public void check(BidirectionalMap parents, + List files, + Map> keysUpToParent, + Map> propertiesFilesNamesMaps, + InspectionManager manager, + RefManager refManager, + ProblemDescriptionsProcessor processor) { + for (PropertiesFile file : files) { + final Set filePropertyKeys = new THashSet(propertiesFilesNamesMaps.get(file).keySet()); + PropertiesFile parent = parents.get(file); + while (parent != null) { + final Collection commonKeys = ContainerUtil.intersection(propertiesFilesNamesMaps.get(parent).keySet(), filePropertyKeys); + for (final String commonKey : commonKeys) { + final IProperty property = file.findPropertyByKey(commonKey); + assert property != null; + final String propertyValue = property.getValue(); + if (propertyValue == null) { + continue; + } + final char lastChar = propertyValue.charAt(propertyValue.length() - 1); + if (!PROPERTY_VALUE_END_CHECK_SYMBOLS.contains(lastChar)) { + continue; + } + final String parentPropertyValue = propertiesFilesNamesMaps.get(parent).get(commonKey); + if (parentPropertyValue == null) { + continue; + } + final char parentLastChar = parentPropertyValue.charAt(parentPropertyValue.length() - 1); + if (lastChar != parentLastChar) { + final String message; + if (PROPERTY_VALUE_END_CHECK_SYMBOLS.contains(parentLastChar)) { + message = InspectionsBundle + .message("inconsistent.bundle.property.inconsistent.end.parent.end.from.check.symbols", lastChar, parentLastChar, + parent.getName()); + } else { + message = InspectionsBundle.message("inconsistent.bundle.property.inconsistent.end", lastChar); + } + final PsiElement propertyPsiElement = property.getPsiElement(); + processor.addProblemElement(refManager.getReference(file.getContainingFile()), + manager.createProblemDescriptor(propertyPsiElement, + message, + true, + LocalQuickFix.EMPTY_ARRAY, + ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + ); + } + } + filePropertyKeys.removeAll(commonKeys); + parent = parents.get(parent); + } + } + } +} diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/InconsistentResourceBundleInspection.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/InconsistentResourceBundleInspection.java new file mode 100644 index 000000000000..48f4b05adfb2 --- /dev/null +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/InconsistentResourceBundleInspection.java @@ -0,0 +1,206 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection.i18n.inconsistentResourceBundle; + +import com.intellij.codeHighlighting.HighlightDisplayLevel; +import com.intellij.codeInspection.*; +import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; +import com.intellij.codeInspection.ui.OptionAccessor; +import com.intellij.lang.properties.*; +import com.intellij.lang.properties.ResourceBundle; +import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.openapi.util.*; +import com.intellij.psi.PsiFile; +import com.intellij.util.containers.BidirectionalMap; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.FactoryMap; +import gnu.trove.THashMap; +import gnu.trove.THashSet; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; + +import javax.swing.*; +import java.util.*; + +/** + * @author max + */ +public class InconsistentResourceBundleInspection extends GlobalSimpleInspectionTool { + private static final Key> VISITED_BUNDLES_KEY = Key.create("VISITED_BUNDLES_KEY"); + + private final InconsistentResourceBundleInspectionProvider[] myInspectionProviders; + private final Map mySettings = new LinkedHashMap(); + + public InconsistentResourceBundleInspection() { + myInspectionProviders = new InconsistentResourceBundleInspectionProvider[] { + new PropertiesKeysConsistencyInspectionProvider(), + new DuplicatedPropertiesInspectionProvider(), + new MissingTranslationsInspectionProvider(), + new PropertiesPlaceholdersInspectionProvider(), + new InconsistentPropertiesEndsInspectionProvider(), + }; + } + + @Override + @NotNull + public String getGroupDisplayName() { + return PropertiesBundle.message("properties.files.inspection.group.display.name"); + } + + @Override + @NotNull + public String getDisplayName() { + return InspectionsBundle.message("inconsistent.resource.bundle.display.name"); + } + + @Override + @NotNull + public String getShortName() { + return "InconsistentResourceBundle"; + } + + @Override + @NotNull + public HighlightDisplayLevel getDefaultLevel() { + return HighlightDisplayLevel.ERROR; + } + + @Override + @Nullable + public JComponent createOptionsPanel() { + final MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(new OptionAccessor() { + @Override + public boolean getOption(String optionName) { + return isProviderEnabled(optionName); + } + + @Override + public void setOption(String optionName, boolean optionValue) { + if (optionValue) { + mySettings.remove(optionName); + } + else { + mySettings.put(optionName, false); + } + } + }); + for (final InconsistentResourceBundleInspectionProvider provider : myInspectionProviders) { + panel.addCheckbox(provider.getPresentableName(), provider.getName()); + } + return panel; + } + + @Override + public void writeSettings(final @NotNull Element node) throws WriteExternalException { + for (final Map.Entry e : mySettings.entrySet()) { + JDOMExternalizerUtil.writeField(node, e.getKey(), Boolean.toString(e.getValue())); + } + } + + @Override + public void readSettings(final @NotNull Element node) throws InvalidDataException { + mySettings.clear(); + for (final Object o : node.getChildren()) { + if (o instanceof Element) { + final Element e = (Element) o; + final String name = e.getAttributeValue("name"); + final boolean value = Boolean.parseBoolean(e.getAttributeValue("value")); + mySettings.put(name, value); + } + } + } + + @Override + public void inspectionStarted(@NotNull InspectionManager manager, + @NotNull GlobalInspectionContext globalContext, + @NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor) { + globalContext.putUserData(VISITED_BUNDLES_KEY, new THashSet()); + } + + @Override + public void checkFile(@NotNull PsiFile file, + @NotNull InspectionManager manager, + @NotNull ProblemsHolder problemsHolder, + @NotNull GlobalInspectionContext globalContext, + @NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor) { + Set visitedBundles = globalContext.getUserData(VISITED_BUNDLES_KEY); + if (!(file instanceof PropertiesFile)) return; + final PropertiesFile propertiesFile = (PropertiesFile)file; + ResourceBundle resourceBundle = propertiesFile.getResourceBundle(); + assert visitedBundles != null; + if (!visitedBundles.add(resourceBundle)) return; + List files = resourceBundle.getPropertiesFiles(manager.getProject()); + if (files.size() < 2) return; + BidirectionalMap parents = new BidirectionalMap(); + for (PropertiesFile f : files) { + PropertiesFile parent = PropertiesUtil.getParent(f, files); + if (parent != null) { + parents.put(f, parent); + } + } + final FactoryMap> propertiesFilesNamesMaps = new FactoryMap>() { + @Nullable + @Override + protected Map create(PropertiesFile key) { + return key.getNamesMap(); + } + }; + Map> keysUpToParent = new THashMap>(); + for (PropertiesFile f : files) { + Set keys = new THashSet(propertiesFilesNamesMaps.get(f).keySet()); + PropertiesFile parent = parents.get(f); + while (parent != null) { + keys.addAll(propertiesFilesNamesMaps.get(parent).keySet()); + parent = parents.get(parent); + } + keysUpToParent.put(f, keys); + } + for (final InconsistentResourceBundleInspectionProvider provider : myInspectionProviders) { + if (isProviderEnabled(provider.getName())) { + provider.check(parents, files, keysUpToParent, propertiesFilesNamesMaps, manager, globalContext.getRefManager(), + problemDescriptionsProcessor); + } + } + } + + private boolean isProviderEnabled(final String providerName) { + return ContainerUtil.getOrElse(mySettings, providerName, true); + } + + @TestOnly + public void enableProviders(final Class... providerClasses) { + Set> providersToEnable = ContainerUtil.newHashSet(providerClasses); + for (InconsistentResourceBundleInspectionProvider inspectionProvider : myInspectionProviders) { + if (providersToEnable.contains(inspectionProvider.getClass())) { + mySettings.put(inspectionProvider.getName(), true); + } + } + } + + @TestOnly + public void disableAllProviders() { + for (InconsistentResourceBundleInspectionProvider inspectionProvider : myInspectionProviders) { + mySettings.put(inspectionProvider.getName(), false); + } + } + + @TestOnly + public void clearSettings() { + mySettings.clear(); + } +} \ No newline at end of file diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/InconsistentResourceBundleInspectionProvider.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/InconsistentResourceBundleInspectionProvider.java new file mode 100644 index 000000000000..0389c7138660 --- /dev/null +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/InconsistentResourceBundleInspectionProvider.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection.i18n.inconsistentResourceBundle; + +import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.ProblemDescriptionsProcessor; +import com.intellij.codeInspection.reference.RefManager; +import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.util.containers.BidirectionalMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Dmitry Batkovich + */ +public interface InconsistentResourceBundleInspectionProvider { + @NotNull + String getName(); + + @NotNull + String getPresentableName(); + + void check(BidirectionalMap parents, + List files, + Map> keysUpToParent, + Map> propertiesFilesNamesMaps, + InspectionManager manager, + RefManager refManager, + ProblemDescriptionsProcessor processor); +} diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/MissingTranslationsInspectionProvider.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/MissingTranslationsInspectionProvider.java new file mode 100644 index 000000000000..297f4478d261 --- /dev/null +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/MissingTranslationsInspectionProvider.java @@ -0,0 +1,87 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection.i18n.inconsistentResourceBundle; + +import com.intellij.codeInspection.*; +import com.intellij.codeInspection.reference.RefManager; +import com.intellij.lang.properties.IProperty; +import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.util.containers.BidirectionalMap; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Dmitry Batkovich + */ +public class MissingTranslationsInspectionProvider implements InconsistentResourceBundleInspectionProvider { + @NotNull + @Override + public String getName() { + return "REPORT_MISSING_TRANSLATIONS"; + } + + @NotNull + @Override + public String getPresentableName() { + return InspectionsBundle.message("inconsistent.bundle.report.missing.translations"); + } + + @Override + public void check(BidirectionalMap parents, + List files, + Map> keysUpToParent, + Map> propertiesFilesNamesMaps, + InspectionManager manager, + RefManager refManager, + ProblemDescriptionsProcessor processor) { + for (PropertiesFile file : files) { + PropertiesFile parent = parents.get(file); + if (parent == null) continue; + List children = parents.getKeysByValue(file); + boolean isLeaf = children == null || children.isEmpty(); + if (!isLeaf) continue; + Set keys = propertiesFilesNamesMaps.get(file).keySet(); + Set parentKeys = new THashSet(keysUpToParent.get(parent)); + if (parent.getLocale().getLanguage().equals(file.getLocale().getLanguage())) { + // properties can be left untranslated in the dialect files + keys = new THashSet(keys); + keys.addAll(propertiesFilesNamesMaps.get(parent).keySet()); + parent = parents.get(parent); + if (parent == null) continue; + parentKeys = new THashSet(keysUpToParent.get(parent)); + } + parentKeys.removeAll(keys); + for (String untranslatedKey : parentKeys) { + IProperty untranslatedProperty = null; + PropertiesFile untranslatedFile = parent; + while (untranslatedFile != null) { + untranslatedProperty = untranslatedFile.findPropertyByKey(untranslatedKey); + if (untranslatedProperty != null) break; + untranslatedFile = parents.get(untranslatedFile); + } + assert untranslatedProperty != null; + String message = InspectionsBundle.message("inconsistent.bundle.untranslated.property.error", untranslatedKey, file.getName()); + ProblemDescriptor descriptor = manager.createProblemDescriptor(untranslatedProperty.getPsiElement(), message, false, LocalQuickFix.EMPTY_ARRAY, + ProblemHighlightType.GENERIC_ERROR_OR_WARNING); + processor.addProblemElement(refManager.getReference(untranslatedFile.getContainingFile()), descriptor); + } + } + } +} diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/PropertiesKeysConsistencyInspectionProvider.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/PropertiesKeysConsistencyInspectionProvider.java new file mode 100644 index 000000000000..c6d47b127c63 --- /dev/null +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/PropertiesKeysConsistencyInspectionProvider.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection.i18n.inconsistentResourceBundle; + +import com.intellij.codeInspection.*; +import com.intellij.codeInspection.reference.RefManager; +import com.intellij.lang.properties.IProperty; +import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.util.containers.BidirectionalMap; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Dmitry Batkovich + */ +public class PropertiesKeysConsistencyInspectionProvider implements InconsistentResourceBundleInspectionProvider { + @NotNull + @Override + public String getName() { + return "REPORT_INCONSISTENT_PROPERTIES"; + } + + @NotNull + @Override + public String getPresentableName() { + return InspectionsBundle.message("inconsistent.bundle.report.inconsistent.properties"); + } + + @Override + public void check(BidirectionalMap parents, + List files, + Map> keysUpToParent, + Map> propertiesFilesNamesMaps, + InspectionManager manager, + RefManager refManager, + ProblemDescriptionsProcessor processor) { + for (PropertiesFile file : files) { + PropertiesFile parent = parents.get(file); + Set parentKeys = keysUpToParent.get(parent); + if (parent == null) { + parentKeys = new THashSet(); + for (PropertiesFile otherTopLevelFile : files) { + if (otherTopLevelFile != file && parents.get(otherTopLevelFile) == null) { + parent = otherTopLevelFile; + parentKeys.addAll(propertiesFilesNamesMaps.get(otherTopLevelFile).keySet()); + } + } + if (parent == null) continue; + } + Set keys = new THashSet(propertiesFilesNamesMaps.get(file).keySet()); + keys.removeAll(parentKeys); + for (String inconsistentKey : keys) { + IProperty property = file.findPropertyByKey(inconsistentKey); + assert property != null; + String message = InspectionsBundle.message("inconsistent.bundle.property.error", inconsistentKey, parent.getName()); + ProblemDescriptor descriptor = manager.createProblemDescriptor(property.getPsiElement(), message, false, LocalQuickFix.EMPTY_ARRAY, + ProblemHighlightType.GENERIC_ERROR_OR_WARNING); + processor.addProblemElement(refManager.getReference(file.getContainingFile()), descriptor); + } + } + } +} diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/PropertiesPlaceholdersInspectionProvider.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/PropertiesPlaceholdersInspectionProvider.java new file mode 100644 index 000000000000..bfbae397759e --- /dev/null +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/inconsistentResourceBundle/PropertiesPlaceholdersInspectionProvider.java @@ -0,0 +1,92 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection.i18n.inconsistentResourceBundle; + +import com.intellij.codeInspection.*; +import com.intellij.codeInspection.i18n.JavaI18nUtil; +import com.intellij.codeInspection.reference.RefManager; +import com.intellij.lang.properties.IProperty; +import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.psi.PsiElement; +import com.intellij.util.containers.BidirectionalMap; +import com.intellij.util.containers.ContainerUtil; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Dmitry Batkovich + */ +public class PropertiesPlaceholdersInspectionProvider implements InconsistentResourceBundleInspectionProvider { + @NotNull + @Override + public String getName() { + return "REPORT_INCONSISTENT_PROPERTIES_PLACEHOLDERS"; + } + + @NotNull + @Override + public String getPresentableName() { + return InspectionsBundle.message("inconsistent.bundle.report.inconsistent.properties.placeholders"); + } + + @Override + public void check(BidirectionalMap parents, + List files, + Map> keysUpToParent, + Map> propertiesFilesNamesMaps, + InspectionManager manager, + RefManager refManager, + ProblemDescriptionsProcessor processor) { + for (PropertiesFile file : files) { + final Set filePropertyKeys = new THashSet(propertiesFilesNamesMaps.get(file).keySet()); + PropertiesFile parent = parents.get(file); + while (parent != null) { + final Collection commonKeys = ContainerUtil.intersection(propertiesFilesNamesMaps.get(parent).keySet(), filePropertyKeys); + for (final String commonKey : commonKeys) { + final IProperty property = file.findPropertyByKey(commonKey); + assert property != null; + final String propertyValue = property.getValue(); + if (propertyValue == null) { + continue; + } + final String parentPropertyValue = propertiesFilesNamesMaps.get(parent).get(commonKey); + if (parentPropertyValue == null) { + continue; + } + final int occurrences = JavaI18nUtil.getPropertyValuePlaceholdersCount(propertyValue); + final int parentOccurrences = JavaI18nUtil.getPropertyValuePlaceholdersCount(parentPropertyValue); + if (occurrences != parentOccurrences) { + final String problemDescriptorString = + InspectionsBundle.message("inconsistent.bundle.property.inconsistent.placeholders", parentOccurrences, parent.getName()); + final PsiElement propertyPsiElement = property.getPsiElement(); + processor.addProblemElement(refManager.getReference(file.getContainingFile()), + manager.createProblemDescriptor(propertyPsiElement, problemDescriptorString, true, + LocalQuickFix.EMPTY_ARRAY, + ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + ); + } + } + filePropertyKeys.removeAll(commonKeys); + parent = parents.get(parent); + } + } + } +} diff --git a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/expected.xml b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/expected.xml new file mode 100644 index 000000000000..cdb0fe530101 --- /dev/null +++ b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/expected.xml @@ -0,0 +1,23 @@ + + + + prop_en.properties + 2 + Inconsistent count of placeholders: found 0 in 'prop.properties' + + + prop_en_CA.properties + 1 + Inconsistent count of placeholders: found 2 in 'prop_en.properties' + + + prop_en_CA.properties + 2 + Inconsistent count of placeholders: found 1 in 'prop_en.properties' + + + prop_en_CA.properties + 3 + Inconsistent count of placeholders: found 0 in 'prop.properties' + + diff --git a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/src/prop.properties b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/src/prop.properties new file mode 100644 index 000000000000..8241c14c6f89 --- /dev/null +++ b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/src/prop.properties @@ -0,0 +1,5 @@ +key=value{0}{1} +key1=value1 +key2=value2 +key3=value3 +key4=value4 \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/src/prop_en.properties b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/src/prop_en.properties new file mode 100644 index 000000000000..5cc6ef0982ca --- /dev/null +++ b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/src/prop_en.properties @@ -0,0 +1,4 @@ +key=value{0} en {1} +key1=value1 {0} +key2=value2 +key3=value3 \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/src/prop_en_CA.properties b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/src/prop_en_CA.properties new file mode 100644 index 000000000000..a4f93614485c --- /dev/null +++ b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentPlaceholders/src/prop_en_CA.properties @@ -0,0 +1,3 @@ +key=value en CA {0} +key1=value1 +key4=value{0} \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/expected.xml b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/expected.xml new file mode 100644 index 000000000000..15bef11394fa --- /dev/null +++ b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/expected.xml @@ -0,0 +1,13 @@ + + + + prop_en_CA.properties + 2 + Inconsistent property value end ':' but found ';' in 'prop_en.properties' + + + prop_en_CA.properties + 4 + Inconsistent property value end ';' but found ':' in 'prop.properties' + + diff --git a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/src/prop.properties b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/src/prop.properties new file mode 100644 index 000000000000..23a0fe287624 --- /dev/null +++ b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/src/prop.properties @@ -0,0 +1,4 @@ +key1=value +key2=value; +key3=value. +key4=value: \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/src/prop_en.properties b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/src/prop_en.properties new file mode 100644 index 000000000000..f761395f76d8 --- /dev/null +++ b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/src/prop_en.properties @@ -0,0 +1,3 @@ +key1=value123 +key2=value123; +key3=value123. \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/src/prop_en_CA.properties b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/src/prop_en_CA.properties new file mode 100644 index 000000000000..52e3815b52fa --- /dev/null +++ b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/InconsistentValuesEnds/src/prop_en_CA.properties @@ -0,0 +1,4 @@ +key1=value +key2=value: +key3=value. +key4=value; \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/expected.xml b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/expected.xml new file mode 100644 index 000000000000..3b7f28ff49fc --- /dev/null +++ b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/expected.xml @@ -0,0 +1,40 @@ + + + + + Bu.properties + 1 + Untranslated property 'a'. Should be overridden in the 'Bu_fr_SSS.properties'. + + + + Bu_fr_SSS.properties + 1 + Inconsistent property 'c'. Must be defined in the parent file 'Bu_fr.properties'. + + + + Bu_fr.properties + 1 + Inconsistent property 'b'. Must be defined in the parent file 'Bu.properties'. + + + Bu_fr_SSS.properties + 2 + Property inherited from the 'Bu.properties' file with the same value + + diff --git a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu.properties b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu.properties new file mode 100644 index 000000000000..995e6e5384f7 --- /dev/null +++ b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu.properties @@ -0,0 +1,17 @@ +# +# Copyright 2000-2014 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +a=1 +zzz=zzz \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu_fr.properties b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu_fr.properties new file mode 100644 index 000000000000..e82df74c38a2 --- /dev/null +++ b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu_fr.properties @@ -0,0 +1 @@ +b=2 diff --git a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu_fr_SSS.properties b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu_fr_SSS.properties new file mode 100644 index 000000000000..1c6b89c4f11d --- /dev/null +++ b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu_fr_SSS.properties @@ -0,0 +1,2 @@ +c=3 +zzz=zzz \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspection/ClassName.java b/plugins/java-i18n/testData/inspections/spellchecker/ClassName.java similarity index 100% rename from plugins/java-i18n/testData/inspection/ClassName.java rename to plugins/java-i18n/testData/inspections/spellchecker/ClassName.java diff --git a/plugins/java-i18n/testData/inspection/CorrectJava.java b/plugins/java-i18n/testData/inspections/spellchecker/CorrectJava.java similarity index 100% rename from plugins/java-i18n/testData/inspection/CorrectJava.java rename to plugins/java-i18n/testData/inspections/spellchecker/CorrectJava.java diff --git a/plugins/java-i18n/testData/inspection/DocComment.java b/plugins/java-i18n/testData/inspections/spellchecker/DocComment.java similarity index 100% rename from plugins/java-i18n/testData/inspection/DocComment.java rename to plugins/java-i18n/testData/inspections/spellchecker/DocComment.java diff --git a/plugins/java-i18n/testData/inspection/FieldName.java b/plugins/java-i18n/testData/inspections/spellchecker/FieldName.java similarity index 100% rename from plugins/java-i18n/testData/inspection/FieldName.java rename to plugins/java-i18n/testData/inspections/spellchecker/FieldName.java diff --git a/plugins/java-i18n/testData/inspection/Japanese.java b/plugins/java-i18n/testData/inspections/spellchecker/Japanese.java similarity index 100% rename from plugins/java-i18n/testData/inspection/Japanese.java rename to plugins/java-i18n/testData/inspections/spellchecker/Japanese.java diff --git a/plugins/java-i18n/testData/inspection/LocalVariableName.java b/plugins/java-i18n/testData/inspections/spellchecker/LocalVariableName.java similarity index 100% rename from plugins/java-i18n/testData/inspection/LocalVariableName.java rename to plugins/java-i18n/testData/inspections/spellchecker/LocalVariableName.java diff --git a/plugins/java-i18n/testData/inspection/MethodName.java b/plugins/java-i18n/testData/inspections/spellchecker/MethodName.java similarity index 100% rename from plugins/java-i18n/testData/inspection/MethodName.java rename to plugins/java-i18n/testData/inspections/spellchecker/MethodName.java diff --git a/plugins/java-i18n/testData/inspection/StringLiteral.java b/plugins/java-i18n/testData/inspections/spellchecker/StringLiteral.java similarity index 100% rename from plugins/java-i18n/testData/inspection/StringLiteral.java rename to plugins/java-i18n/testData/inspections/spellchecker/StringLiteral.java diff --git a/plugins/java-i18n/testData/inspection/StringLiteralEscaping.java b/plugins/java-i18n/testData/inspections/spellchecker/StringLiteralEscaping.java similarity index 100% rename from plugins/java-i18n/testData/inspection/StringLiteralEscaping.java rename to plugins/java-i18n/testData/inspections/spellchecker/StringLiteralEscaping.java diff --git a/plugins/java-i18n/testData/inspection/Suppressions.java b/plugins/java-i18n/testData/inspections/spellchecker/Suppressions.java similarity index 100% rename from plugins/java-i18n/testData/inspection/Suppressions.java rename to plugins/java-i18n/testData/inspections/spellchecker/Suppressions.java diff --git a/plugins/java-i18n/testData/inspection/TypoInJava.java b/plugins/java-i18n/testData/inspections/spellchecker/TypoInJava.java similarity index 100% rename from plugins/java-i18n/testData/inspection/TypoInJava.java rename to plugins/java-i18n/testData/inspections/spellchecker/TypoInJava.java diff --git a/plugins/java-i18n/testData/inspection/VarArg.java b/plugins/java-i18n/testData/inspections/spellchecker/VarArg.java similarity index 100% rename from plugins/java-i18n/testData/inspection/VarArg.java rename to plugins/java-i18n/testData/inspections/spellchecker/VarArg.java diff --git a/plugins/java-i18n/testSrc/com/intellij/codeInspection/i18n/InconsistentResourceBundleInspectionTest.java b/plugins/java-i18n/testSrc/com/intellij/codeInspection/i18n/InconsistentResourceBundleInspectionTest.java new file mode 100644 index 000000000000..06135af75ebe --- /dev/null +++ b/plugins/java-i18n/testSrc/com/intellij/codeInspection/i18n/InconsistentResourceBundleInspectionTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection.i18n; + +import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper; +import com.intellij.codeInspection.i18n.inconsistentResourceBundle.*; +import com.intellij.openapi.application.PluginPathManager; +import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; + +/** + * @author Dmitry Batkovich + */ +@SuppressWarnings("unchecked") +public class InconsistentResourceBundleInspectionTest extends JavaCodeInsightFixtureTestCase { + private final InconsistentResourceBundleInspection myInspection = new InconsistentResourceBundleInspection(); + + @Override + protected String getTestDataPath() { + return PluginPathManager.getPluginHomePath("java-i18n") + "/testData/inspections/inconsistentResourceBundle"; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + myInspection.disableAllProviders(); + } + + @Override + protected void tearDown() throws Exception { + myInspection.clearSettings(); + super.tearDown(); + } + + public void testInconsistentPlaceholders() { + myInspection.enableProviders(PropertiesPlaceholdersInspectionProvider.class); + doTest(); + } + + public void testInconsistentValuesEnds() { + myInspection.enableProviders(InconsistentPropertiesEndsInspectionProvider.class); + doTest(); + } + + public void testSimple() { + myInspection.enableProviders(PropertiesKeysConsistencyInspectionProvider.class, + MissingTranslationsInspectionProvider.class, + DuplicatedPropertiesInspectionProvider.class); + doTest(); + } + + private void doTest() { + myFixture.testInspection(getTestName(false), new GlobalInspectionToolWrapper(myInspection)); + } +} diff --git a/plugins/java-i18n/testSrc/com/intellij/spellchecker/inspection/JavaSpellcheckerInspectionTest.java b/plugins/java-i18n/testSrc/com/intellij/spellchecker/inspection/JavaSpellcheckerInspectionTest.java index 0a247e30788f..a3af1060b856 100644 --- a/plugins/java-i18n/testSrc/com/intellij/spellchecker/inspection/JavaSpellcheckerInspectionTest.java +++ b/plugins/java-i18n/testSrc/com/intellij/spellchecker/inspection/JavaSpellcheckerInspectionTest.java @@ -21,7 +21,7 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; public class JavaSpellcheckerInspectionTest extends LightCodeInsightFixtureTestCase { @Override protected String getBasePath() { - return PluginPathManager.getPluginHomePathRelative("java-i18n") + "/testData/inspection"; + return PluginPathManager.getPluginHomePathRelative("java-i18n") + "/testData/inspections/spellchecker"; } public void testCorrectJava() { doTest(); } diff --git a/resources-en/src/inspectionDescriptions/InconsistentResourceBundle.html b/resources-en/src/inspectionDescriptions/InconsistentResourceBundle.html index d8d5003ec066..edd04cded600 100644 --- a/resources-en/src/inspectionDescriptions/InconsistentResourceBundle.html +++ b/resources-en/src/inspectionDescriptions/InconsistentResourceBundle.html @@ -22,8 +22,8 @@ option controls invalid resource bundle structure inspection.
    It reports properties contained in inherited properties file that are missing in parent (or in sibling if there is no parent).
    E.g. having this resource bundle:
    - messages_fr.properties: abc=xxx
    messages.properties: empty
    + messages_fr.properties: abc=xxx
    Property abc translation here is not available for any language except French, and, thus, will be reported as missing in the (default) properties file messages.properties. @@ -36,11 +36,50 @@ option checks for properties which are copy-pasted into several properties files verbatim.
    E.g. in this resource bundle:
    - messages_fr.properties: abc=xxx
    messages.properties: abc=xxx
    + messages_fr.properties: abc=xxx
    Property abc will be reported as unnecessarily inherited in the file messages_fr.properties.
    + +
      +
    • + + Report properties overridden with different placeholders +
    • +
    + option checks for properties which are overridden for placeholders consistency.
    + E.g. in this resource bundle:
    + messages.properties:
    + qwe={0}xxx{1}
    + abc={0}yyy{1}
    + messages_fr.properties:
    + qwe={0}xxx{0}xxx{1}
    + abc={0}yyy
    + + + Property abc will be reported as property contains message format placeholders + with value not corresponding to messages.properties. +
    + +
      +
    • + + Report properties overridden with different values endings +
    • +
    + option checks for properties which are overridden for endings consistency.
    + E.g. in this resource bundle:
    + messages.properties:
    + abc=xxxzzz
    + messages_fr.properties:
    + abc=xxx;
    + + + Property abc will be reported as property contains special signs + ('!', '?', '.', ':' or ';') at the end of value but + value in messages.properties doesn't. +
    From c5207b25521428c81fe1c7959629e59909f4c500 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 23 Apr 2014 14:29:46 +0400 Subject: [PATCH 61/86] fixed PY-12543 Project Interpreters: too big or too small details popup --- .../src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java b/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java index 354549d4f69d..acbe450b1acd 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java @@ -31,6 +31,7 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.*; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.util.NullableConsumer; +import com.intellij.util.ui.EmptyIcon; import com.jetbrains.python.remote.PythonRemoteInterpreterManager; import com.jetbrains.python.sdk.flavors.PythonSdkFlavor; import org.jetbrains.annotations.Nullable; @@ -62,6 +63,10 @@ public class PythonSdkDetailsStep extends BaseListPopupStep { final ListPopupStep sdkHomesStep = new PythonSdkDetailsStep(project, moreDialog, ownerComponent, existingSdks, callback); final ListPopup popup = JBPopupFactory.getInstance().createListPopup(sdkHomesStep); + Dimension size = new JLabel(VIRTUALENV, EmptyIcon.ICON_16, SwingConstants.LEFT).getMinimumSize(); + final int height = size.height * 5 + 5; + popup.setSize(new Dimension(size.width, height)); + popup.setMinimumSize(new Dimension(size.width, height)); popup.showInScreenCoordinates(ownerComponent, popupPoint); } From 40765968acf961a636bbbba9cb6b34348f7a16c8 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 23 Apr 2014 14:58:38 +0400 Subject: [PATCH 62/86] fixed memory leak --- .../python/sdk/PythonSdkDetailsStep.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java b/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java index acbe450b1acd..7a6b2db2275f 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java @@ -30,10 +30,12 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.*; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; +import com.intellij.openapi.util.Disposer; import com.intellij.util.NullableConsumer; import com.intellij.util.ui.EmptyIcon; import com.jetbrains.python.remote.PythonRemoteInterpreterManager; import com.jetbrains.python.sdk.flavors.PythonSdkFlavor; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -70,10 +72,10 @@ public class PythonSdkDetailsStep extends BaseListPopupStep { popup.showInScreenCoordinates(ownerComponent, popupPoint); } - public PythonSdkDetailsStep(Project project, - DialogWrapper moreDialog, Component ownerComponent, - Sdk[] existingSdks, - NullableConsumer callback) { + public PythonSdkDetailsStep(@Nullable final Project project, + @Nullable final DialogWrapper moreDialog, @NotNull final Component ownerComponent, + @NotNull final Sdk[] existingSdks, + @NotNull final NullableConsumer callback) { super(null, getAvailableOptions(moreDialog != null)); myProject = project; myMore = moreDialog; @@ -191,6 +193,12 @@ public class PythonSdkDetailsStep extends BaseListPopupStep { return true; } + @Override + public void canceled() { + if (getFinalRunnable() == null) + Disposer.dispose(myMore.getDisposable()); + } + @Override public PopupStep onChosen(final String selectedValue, boolean finalChoice) { return doFinalStep(new Runnable() { From 214f99bc443711961bc933a472877500ff1601d3 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 23 Apr 2014 15:08:07 +0400 Subject: [PATCH 63/86] IDEA-103836 --- .../lang/properties/PropertiesUtil.java | 69 ++++++++--------- .../lang/properties/ResourceBundleImpl.java | 2 +- .../lang/properties/PropertiesUtilTest.java | 75 +++++++++++++++++++ 3 files changed, 111 insertions(+), 35 deletions(-) create mode 100644 plugins/properties/testSrc/com/intellij/lang/properties/PropertiesUtilTest.java diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java index 03cd1ca1fbb5..abc281f7ea82 100644 --- a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java +++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2009 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.NullableComputable; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; @@ -27,14 +28,17 @@ import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; +import java.util.*; +import java.util.regex.MatchResult; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @author cdr */ public class PropertiesUtil { + private final static Pattern LOCALE_PATTERN = Pattern.compile("(_[^\\._]{2}(_[^\\._]+){0,2})\\.[^_]+$"); + private final static Locale DEFAULT_LOCALE = new Locale("", "", ""); public static boolean isPropertyComplete(final Project project, ResourceBundle resourceBundle, String propertyName) { @@ -47,23 +51,24 @@ public class PropertiesUtil { @NotNull public static String getBaseName(@NotNull VirtualFile virtualFile) { - String name = virtualFile.getNameWithoutExtension(); - - List parts = StringUtil.split(name, "_"); - if (parts.size() == 1) return parts.get(0); - if (parts.size() == 0) return ""; - - String baseName = parts.get(0); - for (int i = 1; i< parts.size(); i++) { - String part = parts.get(i); - if (part.length() == 2) { - break; + String name = virtualFile.getName(); + final Matcher matcher = LOCALE_PATTERN.matcher(name); + final String baseNameWithExtension; + if (matcher.find()) { + final MatchResult matchResult = matcher.toMatchResult(); + final String[] splitted = matchResult.group(1).split("_"); + if (splitted.length > 1) { + baseNameWithExtension = name.substring(0, matchResult.start(1)) + name.substring(matchResult.end(1)); } - baseName += "_"; - baseName += part; + else { + baseNameWithExtension = name; + } + } + else { + baseNameWithExtension = name; } - return baseName; + return FileUtil.getNameWithoutExtension(baseNameWithExtension); } /** @@ -108,24 +113,20 @@ public class PropertiesUtil { } @NotNull - public static Locale getLocale(VirtualFile propertiesFile) { - String name = propertiesFile.getNameWithoutExtension(); - String tail = StringUtil.trimStart(name, getBaseName(propertiesFile)); - tail = StringUtil.trimStart(tail, "_"); - String[] parts = tail.split("_"); - String language = parts.length == 0 ? "" : parts[0]; - String country = ""; - String variant = ""; - if (parts.length >= 2 && parts[1].length() == 2) { - country = parts[1]; - for (int i = 2; i < parts.length; i++) { - String part = parts[i]; - if (variant.length() != 0) variant += "_"; - variant += part; + public static Locale getLocale(final VirtualFile propertiesFile) { + String name = propertiesFile.getName(); + final Matcher matcher = LOCALE_PATTERN.matcher(name); + if (matcher.find()) { + String rawLocale = matcher.group(1); + String[] splittedRawLocale = rawLocale.split("_"); + if (splittedRawLocale.length > 1 && splittedRawLocale[1].length() == 2) { + final String language = splittedRawLocale[1]; + final String country = splittedRawLocale.length > 2 ? splittedRawLocale[2] : ""; + final String variant = splittedRawLocale.length > 3 ? splittedRawLocale[3] : ""; + return new Locale(language, country, variant); } } - - return new Locale(language,country,variant); + return DEFAULT_LOCALE; } @NotNull diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java index 1cd45628f498..1ac96a96f6af 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java @@ -50,7 +50,7 @@ public class ResourceBundleImpl extends ResourceBundle { List result = new SmartList(); PsiManager psiManager = PsiManager.getInstance(project); for (VirtualFile file : children) { - if (!file.isValid()) continue; + if (!file.isValid() || file.getExtension() == null) continue; if (Comparing.strEqual(PropertiesUtil.getBaseName(file), myBaseName)) { PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(psiManager.findFile(file)); if (propertiesFile != null) { diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesUtilTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesUtilTest.java new file mode 100644 index 000000000000..5ebf25d4258f --- /dev/null +++ b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesUtilTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.lang.properties; + +import com.intellij.openapi.vfs.newvfs.impl.StubVirtualFile; +import junit.framework.TestCase; +import org.jetbrains.annotations.NotNull; + +/** + * @author Dmitry Batkovich + */ +public class PropertiesUtilTest extends TestCase { + + public void testBaseNameWithoutLocale() { + assertBaseNameEquals("property-file.properties", "property-file"); + } + + public void testBaseNameWithLocale() { + assertBaseNameEquals("property-file_en._fr.asd_ru.properties", "property-file_en._fr.asd"); + } + + public void testBaseNameWithoutLocaleWithAdditionalExtension() { + assertBaseNameEquals("property-file.utf8.properties", "property-file.utf8"); + } + + public void testBaseNameWithLocaleWithAdditionalExtension() { + assertBaseNameEquals("property-file_fr.file_en.utf8.properties", "property-file_fr.file.utf8"); + } + + public void testBaseNameWithCountryAndVariant() { + assertBaseNameEquals("property-file_fr.file_en_GB_UNIX.utf8.properties", "property-file_fr.file.utf8"); + } + + public void testBaseNameWithCountry() { + assertBaseNameEquals("property-file_fr.file_en_GB.utf8.properties", "property-file_fr.file.utf8"); + } + + public void testBaseName() { + assertBaseNameEquals("Base_Properties.utf8.properties", "Base_Properties.utf8"); + } + + public void test1() { + assertBaseNameEquals("Base_Page_fr.utf8.properties", "Base_Page.utf8"); + } + public void test2() { + assertBaseNameEquals("Base_Page_en.utf8.properties", "Base_Page.utf8"); + } + public void test3() { + assertBaseNameEquals("Base_Page.utf8.properties", "Base_Page.utf8"); + } + + private static void assertBaseNameEquals(final String propertyFileName, final String expectedBaseName) { + final String actualBaseName = PropertiesUtil.getBaseName(new StubVirtualFile() { + @NotNull + @Override + public String getName() { + return propertyFileName; + } + }); + assertEquals(expectedBaseName, actualBaseName); + } +} From 577579d8375e9895cdd867e3c18f1c57660335a6 Mon Sep 17 00:00:00 2001 From: Andrey Starovoyt Date: Wed, 23 Apr 2014 15:11:16 +0400 Subject: [PATCH 64/86] cleanup after extracting java postfix template provider --- .../PostfixTemplatesCompletionProvider.java | 5 +- .../templates/BooleanPostfixTemplate.java | 2 +- .../ElseStatementPostfixTemplate.java | 17 +- .../ExpressionPostfixTemplateWithChooser.java | 19 +- .../templates/ForIndexedPostfixTemplate.java | 4 +- .../templates/ForeachPostfixTemplate.java | 4 +- .../templates/FormatPostfixTemplate.java | 2 +- .../templates/IfStatementPostfixTemplate.java | 17 +- .../InstanceofExpressionPostfixTemplate.java | 16 +- .../JavaPostfixTemplateProvider.java | 103 ++++------ .../templates/LanguagePostfixTemplate.java | 2 +- .../templates/NonVoidPostfixTemplate.java | 2 +- .../NotExpressionPostfixTemplate.java | 6 +- .../NotNullCheckPostfixTemplate.java | 24 ++- .../templates/NullCheckPostfixTemplate.java | 4 +- .../templates/PostfixLiveTemplate.java | 186 ++++++++---------- .../postfix/templates/PostfixTemplate.java | 10 - .../templates/PostfixTemplateProvider.java | 20 +- .../ReturnStatementPostfixTemplate.java | 3 +- .../StatementPostfixTemplateBase.java | 18 +- .../SwitchStatementPostfixTemplate.java | 3 +- .../SynchronizedStatementPostfixTemplate.java | 3 +- .../ThrowExceptionPostfixTemplate.java | 2 +- .../TryWithResourcesPostfixTemplate.java | 5 +- .../WhileStatementPostfixTemplate.java | 18 +- .../template/postfix/util/Aliases.java | 15 -- .../postfix/util/PostfixTemplatesUtils.java | 10 +- 27 files changed, 265 insertions(+), 255 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/codeInsight/template/postfix/util/Aliases.java diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java index 3e99fbf66db2..ec0aead68085 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.completion.CompletionParameters; import com.intellij.codeInsight.completion.CompletionProvider; import com.intellij.codeInsight.completion.CompletionResultSet; import com.intellij.codeInsight.completion.PrefixMatcher; +import com.intellij.codeInsight.template.CustomTemplateCallback; import com.intellij.codeInsight.template.impl.LiveTemplateCompletionContributor; import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings; import com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate; @@ -42,8 +43,8 @@ class PostfixTemplatesCompletionProvider extends CompletionProvider getExpressions(@NotNull PsiElement context, @NotNull Document document, final int offset) { - List expressions = ContainerUtil.filter(IntroduceVariableBase.collectExpressions(context.getContainingFile(), document, - Math.max(offset - 1, 0), false), + List expressions = ContainerUtil.filter(IntroduceVariableBase.collectExpressions(context.getContainingFile(), document, + Math.max(offset - 1, 0), false), new Condition() { @Override public boolean value(PsiExpression expression) { return expression.getTextRange().getEndOffset() == offset; } - }); + } + ); return ContainerUtil.filter(expressions.isEmpty() ? maybeTopmostExpression(context) : expressions, getTypeCondition()); } @@ -100,7 +109,7 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla @NotNull private static List maybeTopmostExpression(@NotNull PsiElement context) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); PsiType type = expression != null ? expression.getType() : null; if (type == null || PsiType.VOID.equals(type)) return ContainerUtil.emptyList(); return ContainerUtil.createMaybeSingletonList(expression); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java index c353c8d39145..bf025d17741f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java @@ -37,7 +37,7 @@ public abstract class ForIndexedPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); return expr != null && (PostfixTemplatesUtils.isNumber(expr.getType()) || PostfixTemplatesUtils.isArray(expr.getType()) || PostfixTemplatesUtils.isIterable(expr.getType())); @@ -45,7 +45,7 @@ public abstract class ForIndexedPostfixTemplate extends PostfixTemplate { @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); if (expr == null) { PostfixTemplatesUtils.showErrorHint(context.getProject(), editor); return; diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java index aabf47c8eaa1..72bbb4f703bf 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java @@ -37,13 +37,13 @@ public class ForeachPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); return expr != null && (PostfixTemplatesUtils.isArray(expr.getType()) || PostfixTemplatesUtils.isIterable(expr.getType())); } @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); if (expr == null) return; Project project = context.getProject(); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java index 5d99745168a4..a799f39ca466 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java @@ -36,7 +36,7 @@ public class FormatPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); PsiType type = expr != null ? expr.getType() : null; return expr != null && type != null && CommonClassNames.JAVA_LANG_STRING.equals(type.getCanonicalText()); } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java index 9610ec57c23d..812247428e51 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; @@ -14,7 +29,7 @@ public class IfStatementPostfixTemplate extends BooleanPostfixTemplate { @Override public void expand(@NotNull PsiElement context, @NotNull final Editor editor) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); assert expression != null; TextRange range = PostfixTemplatesUtils.ifStatement(expression.getProject(), editor, expression); if (range != null) { diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java index 8c5b58e79123..1884d099edcd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java @@ -19,7 +19,6 @@ import com.intellij.codeInsight.guess.GuessManager; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.PsiTypeLookupItem; import com.intellij.codeInsight.template.*; -import com.intellij.codeInsight.template.postfix.util.Aliases; import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -35,25 +34,30 @@ import org.jetbrains.annotations.NotNull; import java.util.LinkedHashSet; import java.util.Set; -@Aliases(".inst") public class InstanceofExpressionPostfixTemplate extends PostfixTemplate { + public InstanceofExpressionPostfixTemplate() { - super("instanceof", "Surrounds expression with instanceof", "expr instanceof SomeType ? ((SomeType) expr). : null"); + this("instanceof"); + } + + public InstanceofExpressionPostfixTemplate(String alias) { + super(alias, "Surrounds expression with instanceof", "expr instanceof SomeType ? ((SomeType) expr). : null"); } @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(getTopmostExpression(context)); + return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(PostfixTemplatesUtils.getTopmostExpression(context)); } @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); if (!PostfixTemplatesUtils.isNotPrimitiveTypeExpression(expression)) return; surroundExpression(context.getProject(), editor, expression); } - private static void surroundExpression(@NotNull Project project, @NotNull Editor editor, @NotNull PsiExpression expr) throws IncorrectOperationException { + private static void surroundExpression(@NotNull Project project, @NotNull Editor editor, @NotNull PsiExpression expr) + throws IncorrectOperationException { assert expr.isValid(); PsiType[] types = GuessManager.getInstance(project).guessTypeToCast(expr); final boolean parenthesesNeeded = expr instanceof PsiPolyadicExpression || diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java index cb628dd2c276..2ee071b98559 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java @@ -18,10 +18,8 @@ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.codeInsight.completion.CompletionInitializationContext; import com.intellij.codeInsight.completion.JavaCompletionContributor; import com.intellij.codeInsight.template.CustomTemplateCallback; -import com.intellij.codeInsight.template.postfix.util.Aliases; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.Ref; @@ -30,75 +28,47 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.util.Map; import java.util.Set; public class JavaPostfixTemplateProvider implements PostfixTemplateProvider { + private final Set templates; - private static final Logger LOG = Logger.getInstance(JavaPostfixTemplateProvider.class); - - private final Map myMapTemplates; public JavaPostfixTemplateProvider() { - myMapTemplates = ContainerUtil.newHashMap(); - for (PostfixTemplate template : getInitializeTemplateSet()) { - register(template.getKey(), template); - Aliases aliases = template.getClass().getAnnotation(Aliases.class); - if (aliases != null) { - for (String key : aliases.value()) { - register(key, template); - } - } - } - } - - @NotNull - protected Set getInitializeTemplateSet() { - return ContainerUtil.newHashSet(new AssertStatementPostfixTemplate(), - new CastExpressionPostfixTemplate(), - new ElseStatementPostfixTemplate(), - new ForAscendingPostfixTemplate(), - new ForDescendingPostfixTemplate(), - new ForeachPostfixTemplate(), - new FormatPostfixTemplate(), - new IfStatementPostfixTemplate(), - new InstanceofExpressionPostfixTemplate(), - new IntroduceFieldPostfixTemplate(), - new IntroduceVariablePostfixTemplate(), - new IsNullCheckPostfixTemplate(), - new NotExpressionPostfixTemplate(), - new NotNullCheckPostfixTemplate(), - new ParenthesizedExpressionPostfixTemplate(), - new ReturnStatementPostfixTemplate(), - new SoutPostfixTemplate(), - new SwitchStatementPostfixTemplate(), - new SynchronizedStatementPostfixTemplate(), - new ThrowExceptionPostfixTemplate(), - new TryStatementPostfixTemplate(), - new TryWithResourcesPostfixTemplate(), - new WhileStatementPostfixTemplate()); + templates = ContainerUtil.newHashSet(new AssertStatementPostfixTemplate(), + new CastExpressionPostfixTemplate(), + new ElseStatementPostfixTemplate(), + new ForAscendingPostfixTemplate(), + new ForDescendingPostfixTemplate(), + new ForeachPostfixTemplate(), + new FormatPostfixTemplate(), + new IfStatementPostfixTemplate(), + new InstanceofExpressionPostfixTemplate(), + new InstanceofExpressionPostfixTemplate("inst"), + new IntroduceFieldPostfixTemplate(), + new IntroduceVariablePostfixTemplate(), + new IsNullCheckPostfixTemplate(), + new NotExpressionPostfixTemplate(), + new NotExpressionPostfixTemplate("!"), + new NotNullCheckPostfixTemplate(), + new NotNullCheckPostfixTemplate("nn"), + new ParenthesizedExpressionPostfixTemplate(), + new ReturnStatementPostfixTemplate(), + new SoutPostfixTemplate(), + new SwitchStatementPostfixTemplate(), + new SynchronizedStatementPostfixTemplate(), + new ThrowExceptionPostfixTemplate(), + new TryStatementPostfixTemplate(), + new TryWithResourcesPostfixTemplate(), + new WhileStatementPostfixTemplate()); } @NotNull @Override public Set getTemplates() { - return ContainerUtil.newHashSet(myMapTemplates.values()); - } - - @NotNull - @Override - public Set getKeys() { - return myMapTemplates.keySet(); - } - - - @Nullable - @Override - public PostfixTemplate get(@Nullable String key) { - return myMapTemplates.get(key); + return templates; } @Override @@ -115,24 +85,17 @@ public class JavaPostfixTemplateProvider implements PostfixTemplateProvider { @NotNull @Override - public PsiFile preCheck(@NotNull Editor editor, @NotNull PsiFile file, int currentOffset) { - Document document = file.getViewProvider().getDocument(); + public PsiFile preCheck(@NotNull Editor editor, @NotNull PsiFile copyFile, int currentOffset) { + Document document = copyFile.getViewProvider().getDocument(); assert document != null; CharSequence sequence = document.getCharsSequence(); StringBuilder fileContentWithoutKey = new StringBuilder(sequence); - if (isSemicolonNeeded(file, editor)) { + if (isSemicolonNeeded(copyFile, editor)) { fileContentWithoutKey.insert(currentOffset, ';'); - file = PostfixLiveTemplate.copyFile(file, fileContentWithoutKey); + copyFile = PostfixLiveTemplate.copyFile(copyFile, fileContentWithoutKey); } - return file; - } - - private void register(@NotNull String key, @NotNull PostfixTemplate template) { - PostfixTemplate registered = myMapTemplates.put(key, template); - if (registered != null) { - LOG.error("Can't register postfix template. Duplicated key: " + template.getKey()); - } + return copyFile; } @NotNull diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/LanguagePostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/LanguagePostfixTemplate.java index d3780e1f3f12..2360d9721ab8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/LanguagePostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/LanguagePostfixTemplate.java @@ -18,7 +18,7 @@ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.lang.LanguageExtension; public class LanguagePostfixTemplate extends LanguageExtension { - public static final LanguagePostfixTemplate INSTANCE = new LanguagePostfixTemplate(); + public static final LanguagePostfixTemplate LANG_EP = new LanguagePostfixTemplate(); public static final String EP_NAME = "com.intellij.codeInsight.template.postfixTemplateProvider"; private LanguagePostfixTemplate() { diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NonVoidPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NonVoidPostfixTemplate.java index 906a943e15e6..09757e53e826 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NonVoidPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NonVoidPostfixTemplate.java @@ -28,7 +28,7 @@ abstract public class NonVoidPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); return expr != null && PostfixTemplatesUtils.isNonVoid(expr.getType()); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java index 9900c0a4c57d..e2e3db8b8be6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java @@ -16,14 +16,12 @@ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.codeInsight.CodeInsightServicesUtil; -import com.intellij.codeInsight.template.postfix.util.Aliases; import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiExpression; import org.jetbrains.annotations.NotNull; -@Aliases("!") public class NotExpressionPostfixTemplate extends ExpressionPostfixTemplateWithChooser { private static final Condition BOOLEAN_TYPE_CONDITION = new Condition() { @Override @@ -36,6 +34,10 @@ public class NotExpressionPostfixTemplate extends ExpressionPostfixTemplateWithC super("not", "Negates boolean expression", "!expr"); } + public NotExpressionPostfixTemplate(String alias) { + super(alias, alias, "Negates boolean expression", "!expr"); + } + @Override protected void doIt(@NotNull Editor editor, @NotNull PsiExpression expression) { expression.replace(CodeInsightServicesUtil.invertCondition(expression)); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java index e4bde3241fee..ea2480f86a0e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java @@ -1,12 +1,30 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.codeInsight.template.postfix.templates; -import com.intellij.codeInsight.template.postfix.util.Aliases; import org.jetbrains.annotations.NotNull; -@Aliases(".nn") public class NotNullCheckPostfixTemplate extends NullCheckPostfixTemplate { + public NotNullCheckPostfixTemplate() { - super("notnull", "Checks expression to be not-null", "if (expr != null)"); + this("notnull"); + } + + public NotNullCheckPostfixTemplate(String alias) { + super(alias, "Checks expression to be not-null", "if (expr != null)"); } @NotNull diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.java index 6a9b6769e548..c7ad21b2fb11 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.java @@ -39,12 +39,12 @@ public abstract class NullCheckPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(getTopmostExpression(context)); + return PostfixTemplatesUtils.isNotPrimitiveTypeExpression(PostfixTemplatesUtils.getTopmostExpression(context)); } @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); if (!PostfixTemplatesUtils.isNotPrimitiveTypeExpression(expr)) return; Project project = expr.getProject(); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java index 349eeda3ffb7..8fd2e725d560 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java @@ -43,40 +43,28 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; -import java.util.Collections; import java.util.Set; +import static com.intellij.codeInsight.template.postfix.templates.LanguagePostfixTemplate.LANG_EP; + public class PostfixLiveTemplate extends CustomLiveTemplateBase { public static final String POSTFIX_TEMPLATE_ID = "POSTFIX_TEMPLATE_ID"; private static final Logger LOG = Logger.getInstance(PostfixLiveTemplate.class); - private static final LanguagePostfixTemplate templates = LanguagePostfixTemplate.INSTANCE; @NotNull public Set getAllTemplateKeys(PsiFile file, int offset) { Set keys = Sets.newHashSet(); Language language = PsiUtilCore.getLanguageAtOffset(file, offset); - - for (PostfixTemplateProvider provider : templates.allForLanguage(language)) { - keys.addAll(provider.getKeys()); + for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(language)) { + keys.addAll(getKeys(provider)); } return keys; } - public boolean hasNotEmptyKey(PsiFile file, int offset) { - Language language = PsiUtilCore.getLanguageAtOffset(file, offset); - for (PostfixTemplateProvider provider : templates.allForLanguage(language)) { - if (StringUtil - .isNotEmpty(computeTemplateKeyWithoutContextChecking(provider, file.getText(), offset + 1))) { - return true; - } - } - return false; - } - @Nullable - public String computeTemplateKeyWithoutContextChecking(PostfixTemplateProvider provider, - @NotNull CharSequence documentContent, - int currentOffset) { + private static String computeTemplateKeyWithoutContextChecking(@NotNull PostfixTemplateProvider provider, + @NotNull CharSequence documentContent, + int currentOffset) { int startOffset = currentOffset; if (documentContent.length() < startOffset) { return null; @@ -102,14 +90,12 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { Editor editor = callback.getEditor(); CharSequence charsSequence = editor.getDocument().getCharsSequence(); int offset = editor.getCaretModel().getOffset(); - Language language = getLanguage(callback); - for (PostfixTemplateProvider provider : templates.allForLanguage(language)) { + for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(getLanguage(callback))) { String key = computeTemplateKeyWithoutContextChecking(provider, charsSequence, offset); if (key != null && isApplicableTemplate(provider, key, callback.getFile(), editor)) { return key; } } - return null; } @@ -117,7 +103,12 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { @Override public String computeTemplateKeyWithoutContextChecking(@NotNull CustomTemplateCallback callback) { Editor editor = callback.getEditor(); - return computeTemplateKeyWithoutContextChecking(callback.getFile(), editor, editor.getCaretModel().getOffset()); + int currentOffset = editor.getCaretModel().getOffset(); + for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(getLanguage(callback))) { + String key = computeTemplateKeyWithoutContextChecking(provider, editor.getDocument().getCharsSequence(), currentOffset); + if (key != null) return key; + } + return null; } @Override @@ -125,27 +116,26 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { return false; } - @Nullable - public String computeTemplateKeyWithoutContextChecking(PsiFile file, Editor editor, int currentOffset) { - Language language = PsiUtilCore.getLanguageAtOffset(file, currentOffset); - for (PostfixTemplateProvider provider : templates.allForLanguage(language)) { - String key = computeTemplateKeyWithoutContextChecking(provider, editor.getDocument().getCharsSequence(), currentOffset); - if (key != null) return key; - } - return null; - } - @Override public void expand(@NotNull final String key, @NotNull final CustomTemplateCallback callback) { ApplicationManager.getApplication().assertIsDispatchThread(); FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.postfix"); Editor editor = callback.getEditor(); - Language language = getLanguage(callback); - for (PostfixTemplateProvider provider : templates.allForLanguage(language)) { - PostfixTemplate postfixTemplate = provider.get(key); + for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(getLanguage(callback))) { + PostfixTemplate postfixTemplate = getTemplate(provider, key); if (postfixTemplate != null) { - expandForProvider(provider, key, callback); + final PsiFile file = callback.getContext().getContainingFile(); + if (isApplicableTemplate(provider, key, file, editor)) { + int currentOffset = editor.getCaretModel().getOffset(); + PsiElement newContext = deleteTemplateKey(file, editor.getDocument(), currentOffset, key); + newContext = provider.preExpand(editor, newContext, currentOffset, key); + expandTemplate(postfixTemplate, editor, newContext); + } + // don't care about errors in multiCaret mode + else if (editor.getCaretModel().getAllCarets().size() == 1) { + LOG.error("Template not found by key: " + key); + } return; } } @@ -156,37 +146,19 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { } } - private static Language getLanguage(CustomTemplateCallback callback) { - return PsiUtilCore.getLanguageAtOffset(callback.getFile(), callback.getEditor().getCaretModel().getOffset()); - } - - public void expandForProvider( - @NotNull PostfixTemplateProvider provider, - @NotNull final String key, - @NotNull final CustomTemplateCallback callback) { - final Editor editor = callback.getEditor(); - final PsiFile file = callback.getContext().getContainingFile(); - if (isApplicableTemplate(provider, key, file, editor)) { - int currentOffset = editor.getCaretModel().getOffset(); - PsiElement newContext = deleteTemplateKey(file, editor.getDocument(), currentOffset, key); - newContext = provider.preExpand(editor, newContext, currentOffset, key); - PostfixTemplate template = provider.get(key); - assert template != null; - expandTemplate(template, editor, newContext); - } - // don't care about errors in multiCaret mode - else if (editor.getCaretModel().getAllCarets().size() == 1) { - LOG.error("Template not found by key: " + key); - } - } - @Override public boolean isApplicable(PsiFile file, int offset, boolean wrapping) { PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance(); if (wrapping || file == null || settings == null || !settings.isPostfixTemplatesEnabled()) { return false; } - return hasNotEmptyKey(file, offset); + Language language = PsiUtilCore.getLanguageAtOffset(file, offset); + for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(language)) { + if (StringUtil.isNotEmpty(computeTemplateKeyWithoutContextChecking(provider, file.getText(), offset + 1))) { + return true; + } + } + return false; } @Override @@ -222,42 +194,25 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { @NotNull Editor editor, int offset) { Collection result = ContainerUtil.newHashSet(); - Language language = PsiUtilCore.getLanguageAtOffset(file, editor.getCaretModel().getOffset()); - for (PostfixTemplateProvider provider : templates.allForLanguage(language)) { - result.addAll(getLookupElementsForProvider(provider, file, editor, offset)); + CustomTemplateCallback callback = new CustomTemplateCallback(editor, file, false); + for (PostfixTemplateProvider provider : LANG_EP.allForLanguage(getLanguage(callback))) { + String key = computeTemplateKeyWithoutContextChecking(callback); + if (key != null && editor.getCaretModel().getCaretCount() == 1) { + Condition isApplicationTemplateFunction = createIsApplicationTemplateFunction(provider, key, file, editor); + for (PostfixTemplate postfixTemplate : provider.getTemplates()) { + if (isApplicationTemplateFunction.value(postfixTemplate)) { + result.add(new PostfixTemplateLookupElement(this, postfixTemplate, postfixTemplate.getKey(), false)); + } + } + } } return result; } - @NotNull - private Collection getLookupElementsForProvider( - @NotNull PostfixTemplateProvider provider, - @NotNull PsiFile file, - @NotNull Editor editor, - int offset) { - String key = computeTemplateKeyWithoutContextChecking(file, editor, offset); - if (key != null && editor.getCaretModel().getCaretCount() == 1) { - Collection result = ContainerUtil.newHashSet(); - - Condition isApplicationTemplateFunction = createIsApplicationTemplateFunction(provider, key, file, editor); - for (String postfixKey : provider.getKeys()) { - PostfixTemplate postfixTemplate = provider.get(postfixKey); - assert postfixTemplate != null; - if (isApplicationTemplateFunction.value(postfixTemplate)) { - result.add(new PostfixTemplateLookupElement(this, postfixTemplate, postfixKey, false)); - } - } - return result; - } - return Collections.emptyList(); - } - - - private static void expandTemplate( - @NotNull final PostfixTemplate template, - @NotNull final Editor editor, - @NotNull final PsiElement context) { + private static void expandTemplate(@NotNull final PostfixTemplate template, + @NotNull final Editor editor, + @NotNull final PsiElement context) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { @@ -293,11 +248,10 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { return CustomTemplateCallback.getContext(file, startOffset > 0 ? startOffset - 1 : startOffset); } - private static Condition createIsApplicationTemplateFunction( - @NotNull PostfixTemplateProvider provider, - @NotNull String key, - @NotNull PsiFile file, - @NotNull Editor editor) { + private static Condition createIsApplicationTemplateFunction(@NotNull PostfixTemplateProvider provider, + @NotNull String key, + @NotNull PsiFile file, + @NotNull Editor editor) { int currentOffset = editor.getCaretModel().getOffset(); final int newOffset = currentOffset - key.length(); CharSequence fileContent = editor.getDocument().getCharsSequence(); @@ -340,11 +294,35 @@ public class PostfixLiveTemplate extends CustomLiveTemplateBase { return copy; } - public static boolean isApplicableTemplate( - @NotNull PostfixTemplateProvider provider, - @NotNull String key, - @NotNull PsiFile file, - @NotNull Editor editor) { - return createIsApplicationTemplateFunction(provider, key, file, editor).value(provider.get(key)); + public static boolean isApplicableTemplate(@NotNull PostfixTemplateProvider provider, + @NotNull String key, + @NotNull PsiFile file, + @NotNull Editor editor) { + return createIsApplicationTemplateFunction(provider, key, file, editor).value(getTemplate(provider, key)); + } + + + @NotNull + private static Set getKeys(@NotNull PostfixTemplateProvider provider) { + Set result = ContainerUtil.newHashSet(); + for (PostfixTemplate template : provider.getTemplates()) { + result.add(template.getKey()); + } + + return result; + } + + @Nullable + private static PostfixTemplate getTemplate(@NotNull PostfixTemplateProvider provider, @Nullable String key) { + for (PostfixTemplate template : provider.getTemplates()) { + if (template.getKey().equals(key)) { + return template; + } + } + return null; + } + + private static Language getLanguage(@NotNull CustomTemplateCallback callback) { + return callback.getContext().getLanguage(); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java index 4131dd907d32..747366d1832f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java @@ -19,11 +19,7 @@ import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettin import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiExpressionStatement; -import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public abstract class PostfixTemplate { @NotNull private final String myPresentableName; @@ -67,12 +63,6 @@ public abstract class PostfixTemplate { return settings != null && settings.isPostfixTemplatesEnabled() && settings.isTemplateEnabled(this); } - @Nullable - public static PsiExpression getTopmostExpression(PsiElement context) { - PsiExpressionStatement statement = PsiTreeUtil.getNonStrictParentOfType(context, PsiExpressionStatement.class); - return statement != null ? PsiTreeUtil.getChildOfType(statement, PsiExpression.class) : null; - } - public abstract boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset); public abstract void expand(@NotNull PsiElement context, @NotNull Editor editor); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java index b74beba50598..eeea9a19f62e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java @@ -20,7 +20,6 @@ import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Set; @@ -32,18 +31,6 @@ public interface PostfixTemplateProvider { @NotNull Set getTemplates(); - /** - * Return all keys registered in the provider - */ - @NotNull - Set getKeys(); - - /** - * Return postfix template for key - */ - @Nullable - PostfixTemplate get(@Nullable String key); - /** * Check symbol can separate template keys */ @@ -51,14 +38,15 @@ public interface PostfixTemplateProvider { /** * Prepare original file content for template expanding + * Return context after transformation */ @NotNull - PsiElement preExpand(@NotNull Editor editor, @NotNull PsiElement context, int currentOffset, @NotNull String key); + PsiElement preExpand(@NotNull Editor editor, @NotNull PsiElement context, int offset, @NotNull String key); /** * Do some actions with the file content before check applicable. - * Return new copy of file because we should not change original file + * Return copyFile or another copy of file after processing */ @NotNull - PsiFile preCheck(@NotNull Editor editor, @NotNull PsiFile file, int currentOffset); + PsiFile preCheck(@NotNull Editor editor, @NotNull PsiFile copyFile, int currentOffset); } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java index 277a6f2c0d30..afc3236b8319 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.template.postfix.templates; +import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Editor; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; @@ -26,7 +27,7 @@ public class ReturnStatementPostfixTemplate extends NonVoidPostfixTemplate { @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); PsiElement parent = expr != null ? expr.getParent() : null; if (!(parent instanceof PsiExpressionStatement)) return; PsiElementFactory factory = JavaPsiFacade.getInstance(expr.getProject()).getElementFactory(); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java index 4449c551dbfc..8f26ec08fae0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java @@ -1,6 +1,22 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.codeInsight.CodeInsightUtilCore; +import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; @@ -17,7 +33,7 @@ public abstract class StatementPostfixTemplateBase extends PostfixTemplate { } protected void surroundWith(PsiElement context, Editor editor, String text) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); PsiElement parent = expr != null ? expr.getParent() : null; if (!(parent instanceof PsiExpressionStatement)) return; diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java index 880c0455775b..20a7299af8ec 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.template.postfix.templates; +import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -51,7 +52,7 @@ public class SwitchStatementPostfixTemplate extends StatementPostfixTemplateBase @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expr = getTopmostExpression(context); + PsiExpression expr = PostfixTemplatesUtils.getTopmostExpression(context); return expr != null && isSwitchCompatibleType(expr.getType(), context); } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java index 044dadc81c8c..eb46ba9f0540 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.template.postfix.templates; +import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; @@ -30,7 +31,7 @@ public class SynchronizedStatementPostfixTemplate extends StatementPostfixTempla @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); PsiType type = expression != null ? expression.getType() : null; return type != null && !(type instanceof PsiPrimitiveType); } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java index b1bb654d6dff..7b0aaa00f4c1 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java @@ -29,7 +29,7 @@ public class ThrowExceptionPostfixTemplate extends PostfixTemplate { @Override public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); return expression != null && PostfixTemplatesUtils.isThrowable(expression.getType()); } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryWithResourcesPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryWithResourcesPostfixTemplate.java index 6ff4d75d7d10..843c19e072c0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryWithResourcesPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryWithResourcesPostfixTemplate.java @@ -22,6 +22,7 @@ import com.intellij.codeInsight.template.TemplateManager; import com.intellij.codeInsight.template.impl.MacroCallNode; import com.intellij.codeInsight.template.impl.TextExpression; import com.intellij.codeInsight.template.macro.SuggestVariableNameMacro; +import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; @@ -44,7 +45,7 @@ public class TryWithResourcesPostfixTemplate extends PostfixTemplate { public boolean isApplicable(@NotNull PsiElement element, @NotNull Document copyDocument, int newOffset) { if (!PsiUtil.isLanguageLevel7OrHigher(element)) return false; - PsiExpression initializer = getTopmostExpression(element); + PsiExpression initializer = PostfixTemplatesUtils.getTopmostExpression(element); if (initializer == null) return false; @@ -61,7 +62,7 @@ public class TryWithResourcesPostfixTemplate extends PostfixTemplate { @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); assert expression != null; Project project = context.getProject(); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java index 03d91b2235af..4c856f7e8299 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java @@ -1,5 +1,21 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.codeInsight.template.postfix.templates; +import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils; import com.intellij.openapi.editor.Editor; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; @@ -11,7 +27,7 @@ public class WhileStatementPostfixTemplate extends BooleanPostfixTemplate { @Override public void expand(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expression = getTopmostExpression(context); + PsiExpression expression = PostfixTemplatesUtils.getTopmostExpression(context); assert expression != null; PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.getProject()); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/Aliases.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/Aliases.java deleted file mode 100644 index 3de07c310f50..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/Aliases.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.intellij.codeInsight.template.postfix.util; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author ignatov - */ -@Target(value = ElementType.TYPE) -@Retention(value = RetentionPolicy.RUNTIME) -public @interface Aliases { - String[] value(); -} diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java index 370c986c5f48..7b92ffdb1ae0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java @@ -17,12 +17,12 @@ package com.intellij.codeInsight.template.postfix.util; import com.intellij.codeInsight.generation.surroundWith.JavaExpressionSurrounder; import com.intellij.codeInsight.generation.surroundWith.JavaWithIfExpressionSurrounder; -import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.util.InheritanceUtil; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.util.CommonRefactoringUtil; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -45,7 +45,7 @@ public abstract class PostfixTemplatesUtils { } public static void createStatement(@NotNull PsiElement context, @NotNull Editor editor, @NotNull String prefix, @NotNull String suffix, int offset) { - PsiExpression expr = PostfixTemplate.getTopmostExpression(context); + PsiExpression expr = getTopmostExpression(context); PsiElement parent = expr != null ? expr.getParent() : null; assert parent instanceof PsiStatement; PsiElementFactory factory = JavaPsiFacade.getInstance(context.getProject()).getElementFactory(); @@ -121,5 +121,11 @@ public abstract class PostfixTemplatesUtils { } return null; } + + @Nullable + public static PsiExpression getTopmostExpression(PsiElement context) { + PsiExpressionStatement statement = PsiTreeUtil.getNonStrictParentOfType(context, PsiExpressionStatement.class); + return statement != null ? PsiTreeUtil.getChildOfType(statement, PsiExpression.class) : null; + } } From 460ef4152c6c937d5abc761fad7199b1fe29e832 Mon Sep 17 00:00:00 2001 From: Serega Vasiliev Date: Wed, 23 Apr 2014 13:07:01 +0200 Subject: [PATCH 65/86] DumbService.smartInvokeLater(...) --- .../LibraryDependentToolWindowManager.java | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/LibraryDependentToolWindowManager.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/LibraryDependentToolWindowManager.java index bb6213972946..09395f500601 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/LibraryDependentToolWindowManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/LibraryDependentToolWindowManager.java @@ -9,9 +9,9 @@ import com.intellij.openapi.roots.ModuleRootAdapter; import com.intellij.openapi.roots.ModuleRootEvent; import com.intellij.openapi.roots.ModuleRootListener; import com.intellij.openapi.startup.StartupManager; -import com.intellij.openapi.wm.ext.LibraryDependentToolWindow; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ex.ToolWindowManagerEx; +import com.intellij.openapi.wm.ext.LibraryDependentToolWindow; import com.intellij.psi.PsiManager; import com.intellij.util.messages.MessageBusConnection; @@ -28,11 +28,7 @@ public class LibraryDependentToolWindowManager extends AbstractProjectComponent public void projectOpened() { final ModuleRootListener rootListener = new ModuleRootAdapter() { public void rootsChanged(ModuleRootEvent event) { - DumbService.getInstance(myProject).smartInvokeLater(new Runnable() { - public void run() { - checkToolWindowStatuses(); - } - }); + checkToolWindowStatuses(); } }; @@ -54,16 +50,21 @@ public class LibraryDependentToolWindowManager extends AbstractProjectComponent return; } - for (LibraryDependentToolWindow libraryToolWindow : Extensions.getExtensions(LibraryDependentToolWindow.EXTENSION_POINT_NAME)) { - if (libraryToolWindow.getLibrarySearchHelper().isLibraryExists(myProject)) { - ensureToolWindowExists(libraryToolWindow); - } else { - ToolWindow toolWindow = myToolWindowManager.getToolWindow(libraryToolWindow.id); - if (toolWindow != null) { - myToolWindowManager.unregisterToolWindow(libraryToolWindow.id); - } - } - } + DumbService.getInstance(myProject).smartInvokeLater(new Runnable() { + public void run() { + for (LibraryDependentToolWindow libraryToolWindow : Extensions.getExtensions(LibraryDependentToolWindow.EXTENSION_POINT_NAME)) { + if (libraryToolWindow.getLibrarySearchHelper().isLibraryExists(myProject)) { + ensureToolWindowExists(libraryToolWindow); + } + else { + ToolWindow toolWindow = myToolWindowManager.getToolWindow(libraryToolWindow.id); + if (toolWindow != null) { + myToolWindowManager.unregisterToolWindow(libraryToolWindow.id); + } + } + } + } + }); } private void ensureToolWindowExists(LibraryDependentToolWindow extension) { From 773f103ccff15d00738c174840ba79501579b25c Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Wed, 23 Apr 2014 13:39:15 +0200 Subject: [PATCH 66/86] Offer to launch Vagrant if it is down on getting ssh-config (PY-12672). --- .../platform-impl/src/com/intellij/remote/VagrantSupport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java b/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java index 574f0b56a45f..5f8fa4bbd0e0 100644 --- a/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java +++ b/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java @@ -55,7 +55,7 @@ public abstract class VagrantSupport { }); } - public abstract void checkVagrantAndRunIfDown(String folder); + public abstract boolean checkVagrantAndRunIfDown(String folder); public abstract Collection getVagrantInstancesConnectors(@NotNull Project project); From fc316803e9c39d809655fc330e5cb6b3d8fcdadb Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Wed, 23 Apr 2014 15:46:45 +0400 Subject: [PATCH 67/86] IDEA-124290 --- .../designer/designSurface/tools/SelectionTracker.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTracker.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTracker.java index a8b35b1f4b68..da1590248439 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTracker.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTracker.java @@ -72,6 +72,14 @@ public class SelectionTracker extends TargetingTool { @Override protected void handleButtonUp(int button) { if (myState == STATE_DRAG) { + // Control clicking on a Mac is used to simulate right clicks: do not treat this as + // a selection reset (since it makes it impossible to pull up the context menu with + // a multi-selection: the right click action causes the selection to be replaced + // with the single item under the mouse) + if (SystemInfo.isMac && myInputEvent != null && myInputEvent.isControlDown()) { + return; + } + performSelection(); myState = STATE_NONE; } From b2d0942b69ca19a4f31322895980bcadd9c42510 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Wed, 23 Apr 2014 14:25:25 +0200 Subject: [PATCH 68/86] Add default mapping to /vagrant only in case of absent mappings in Vagrantfile (PY-12700). --- .../com/intellij/util/PathMappingSettings.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/platform/util/src/com/intellij/util/PathMappingSettings.java b/platform/util/src/com/intellij/util/PathMappingSettings.java index 438ae23c0860..9bdd98755337 100644 --- a/platform/util/src/com/intellij/util/PathMappingSettings.java +++ b/platform/util/src/com/intellij/util/PathMappingSettings.java @@ -45,7 +45,7 @@ public class PathMappingSettings implements Cloneable { List result = ContainerUtil.newArrayList(); if (mappings != null) { for (PathMapping m : mappings) { - if (m != null && !isEmpty(m.myLocalRoot, m.myRemoteRoot)) { + if (m != null && !areBothEmpty(m.myLocalRoot, m.myRemoteRoot)) { result.add(m); } } @@ -65,6 +65,10 @@ public class PathMappingSettings implements Cloneable { return result; } + public boolean isEmpty() { + return myPathMappings.isEmpty(); + } + private static class BestMappingSelector { private int myBestWeight = -1; private PathMapping myBest = null; @@ -116,7 +120,7 @@ public class PathMappingSettings implements Cloneable { } public void add(PathMapping mapping) { - if (isEmpty(mapping.myLocalRoot, mapping.myRemoteRoot)) { + if (areBothEmpty(mapping.myLocalRoot, mapping.myRemoteRoot)) { return; } myPathMappings.add(mapping); @@ -124,7 +128,7 @@ public class PathMappingSettings implements Cloneable { public void addMapping(String local, String remote) { PathMapping mapping = new PathMapping(local, remote); - if (isEmpty(mapping.myLocalRoot, mapping.myRemoteRoot)) { + if (areBothEmpty(mapping.myLocalRoot, mapping.myRemoteRoot)) { return; } myPathMappings.add(mapping); @@ -175,7 +179,7 @@ public class PathMappingSettings implements Cloneable { @NotNull public static String mapToLocal(String path, String remoteRoot, String localRoot) { - if (isEmpty(localRoot, remoteRoot)) { + if (areBothEmpty(localRoot, remoteRoot)) { return path; } path = norm(path); @@ -184,7 +188,7 @@ public class PathMappingSettings implements Cloneable { return path; } - public static boolean isEmpty(String localRoot, String remoteRoot) { + public static boolean areBothEmpty(String localRoot, String remoteRoot) { return StringUtil.isEmpty(localRoot) || StringUtil.isEmpty(remoteRoot); } @@ -305,7 +309,7 @@ public class PathMappingSettings implements Cloneable { } private boolean isEmpty() { - return PathMappingSettings.isEmpty(myLocalRoot, myRemoteRoot); + return PathMappingSettings.areBothEmpty(myLocalRoot, myRemoteRoot); } private static String trimSlash(String s) { From 1236318f3234c6cf418034a1772fa7c0ea490d04 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 23 Apr 2014 14:28:30 +0200 Subject: [PATCH 69/86] always go to file if nothing found --- .../src/com/intellij/ide/actions/Switcher.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 46a6c34bbed8..9f160518fe21 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -940,14 +940,11 @@ public class Switcher extends AnAction implements DumbAware { return; } if (keyCode == VK_ENTER && files.getModel().getSize() + toolWindows.getModel().getSize() == 0) { - AnAction gotoAction = ActionManager.getInstance().getAction("GotoClass"); - if (gotoAction == null) { - gotoAction = ActionManager.getInstance().getAction("GotoFile"); - } - if (gotoAction != null) { + AnAction gotoFile = ActionManager.getInstance().getAction("GotoFile"); + if (gotoFile != null) { final String search = mySpeedSearch.getEnteredPrefix(); myPopup.cancel(); - final AnAction action = gotoAction; + final AnAction action = gotoFile; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { From 90bb5ab61ca5d63356e0adc62c7afee73ab17235 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 23 Apr 2014 17:22:22 +0400 Subject: [PATCH 70/86] IDEA-124301 jdk9 builds cannot be used for project/module compilation --- .../com/intellij/openapi/projectRoots/JavaSdkVersion.java | 4 +++- .../com/intellij/openapi/projectRoots/JdkVersionUtil.java | 1 + .../src/com/intellij/pom/java/LanguageLevel.java | 6 ++++-- java/java-psi-api/src/messages/JavaCoreBundle.properties | 1 + 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java index 9a469ab2d40f..b185b481c315 100644 --- a/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java +++ b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java @@ -31,7 +31,9 @@ public enum JavaSdkVersion { JDK_1_5(LanguageLevel.JDK_1_5, "1.5"), JDK_1_6(LanguageLevel.JDK_1_6, "1.6"), JDK_1_7(LanguageLevel.JDK_1_7, "1.7"), - JDK_1_8(LanguageLevel.JDK_1_8, "1.8"); + JDK_1_8(LanguageLevel.JDK_1_8, "1.8"), + JDK_1_9(LanguageLevel.JDK_1_9, "1.9"); + private final LanguageLevel myMaxLanguageLevel; private final String myDescription; diff --git a/java/java-psi-api/src/com/intellij/openapi/projectRoots/JdkVersionUtil.java b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JdkVersionUtil.java index d26b1ca84c6b..98893c1b509e 100644 --- a/java/java-psi-api/src/com/intellij/openapi/projectRoots/JdkVersionUtil.java +++ b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JdkVersionUtil.java @@ -33,6 +33,7 @@ public class JdkVersionUtil { VERSION_STRINGS.put(JavaSdkVersion.JDK_1_6, new String[]{"1.6", "6.0"}); VERSION_STRINGS.put(JavaSdkVersion.JDK_1_7, new String[]{"1.7", "7.0"}); VERSION_STRINGS.put(JavaSdkVersion.JDK_1_8, new String[]{"1.8", "8.0"}); + VERSION_STRINGS.put(JavaSdkVersion.JDK_1_9, new String[]{"1.9", "9.0"}); } public static JavaSdkVersion getVersion(@NotNull String versionString) { diff --git a/java/java-psi-api/src/com/intellij/pom/java/LanguageLevel.java b/java/java-psi-api/src/com/intellij/pom/java/LanguageLevel.java index e980c0a01c10..6dc8cfb75449 100644 --- a/java/java-psi-api/src/com/intellij/pom/java/LanguageLevel.java +++ b/java/java-psi-api/src/com/intellij/pom/java/LanguageLevel.java @@ -30,9 +30,10 @@ public enum LanguageLevel { JDK_1_5(JavaCoreBundle.message("jdk.1.5.language.level.description")), JDK_1_6(JavaCoreBundle.message("jdk.1.6.language.level.description")), JDK_1_7(JavaCoreBundle.message("jdk.1.7.language.level.description")), - JDK_1_8(JavaCoreBundle.message("jdk.1.8.language.level.description")); + JDK_1_8(JavaCoreBundle.message("jdk.1.8.language.level.description")), + JDK_1_9(JavaCoreBundle.message("jdk.1.9.language.level.description")); - public static final LanguageLevel HIGHEST = JDK_1_8; + public static final LanguageLevel HIGHEST = JDK_1_8; // TODO! when language level 9 is really supported, update this field public static final Key KEY = Key.create("LANGUAGE_LEVEL"); private final String myPresentableText; @@ -59,6 +60,7 @@ public enum LanguageLevel { if ("1.6".equals(value)) return JDK_1_6; if ("1.7".equals(value)) return JDK_1_7; if ("1.8".equals(value)) return JDK_1_8; + if ("1.9".equals(value)) return JDK_1_9; return null; } diff --git a/java/java-psi-api/src/messages/JavaCoreBundle.properties b/java/java-psi-api/src/messages/JavaCoreBundle.properties index 31dc1a7440a7..5ea4ebc4c8f4 100644 --- a/java/java-psi-api/src/messages/JavaCoreBundle.properties +++ b/java/java-psi-api/src/messages/JavaCoreBundle.properties @@ -6,3 +6,4 @@ jdk.1.5.language.level.description=5.0 - 'enum' keyword, autoboxing etc. jdk.1.6.language.level.description=6.0 - @Override in interfaces jdk.1.7.language.level.description=7.0 - Diamonds, ARM, multi-catch etc. jdk.1.8.language.level.description=8.0 - Lambdas, type annotations etc. +jdk.1.9.language.level.description=9.0 - Jigsaw project etc. From 4ff20d5c3f7e47b3b3627e816cf4e83cf2e19ba5 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 23 Apr 2014 17:39:18 +0400 Subject: [PATCH 71/86] InconsistentResourceBundle test fixed --- .../Simple/src/Bu.properties | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu.properties b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu.properties index 995e6e5384f7..ccbe55066e8a 100644 --- a/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu.properties +++ b/plugins/java-i18n/testData/inspections/inconsistentResourceBundle/Simple/src/Bu.properties @@ -1,17 +1,2 @@ -# -# Copyright 2000-2014 JetBrains s.r.o. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# a=1 zzz=zzz \ No newline at end of file From 6de52dc987ab19f87691992d72fc7a3c47adc727 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Wed, 23 Apr 2014 17:28:40 +0400 Subject: [PATCH 72/86] Gradle: update Tooling API version up to 1.12-rc-1, fix classpath for out-of-process mode --- .../service/project/BaseGradleProjectResolverExtension.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java index 892eed7096f0..9b1b288e2e8e 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java @@ -57,6 +57,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.model.*; import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData; +import org.jetbrains.plugins.gradle.tooling.internal.init.Init; import org.jetbrains.plugins.gradle.util.GradleBundle; import org.jetbrains.plugins.gradle.util.GradleConstants; import org.jetbrains.plugins.gradle.util.GradleUtil; @@ -368,6 +369,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(ModuleType.class)); ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(EmptyModuleType.class)); ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(ProjectImportAction.class)); + ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(Init.class)); for (String entry : additionalEntries) { classPath.add(entry); } From 09333b1ac3ee09edeaabbc2dfea7f211fd08e7a2 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Wed, 23 Apr 2014 17:29:56 +0400 Subject: [PATCH 73/86] External system: source package prefix support added; fix for out-of-process mode support --- .../openapi/externalSystem/model/project/ContentRootData.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ContentRootData.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ContentRootData.java index e1b199cd1b9f..fb54cd26d461 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ContentRootData.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ContentRootData.java @@ -9,6 +9,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.Serializable; import java.util.Collection; import java.util.Collections; import java.util.Locale; @@ -97,7 +98,7 @@ public class ContentRootData extends AbstractExternalEntityData { return buffer.toString(); } - public static class SourceRoot { + public static class SourceRoot implements Serializable { @NotNull private final String myPath; From 6924cc4eac90536063861041ed34bad48d49b91c Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Wed, 23 Apr 2014 17:45:50 +0400 Subject: [PATCH 74/86] IDEA-118062 Gradle Run Configuration: 'working directory' is set incorrectly --- .../service/ExternalSystemFacadeManager.java | 2 +- .../RemoteExternalSystemCommunicationManager.java | 8 +++++--- .../gradle/service/project/GradleExecutionHelper.java | 10 ++++------ .../plugins/gradle/util/GradleEnvironment.java | 1 + 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java index 83a010b03620..ae3e75fcf678 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java @@ -186,7 +186,7 @@ public class ExternalSystemFacadeManager { @NotNull private RemoteExternalSystemFacade doCreateFacade(@NotNull IntegrationKey key, @NotNull Project project, @NotNull ExternalSystemCommunicationManager communicationManager) throws Exception { - final RemoteExternalSystemFacade facade = communicationManager.acquire(project.getName(), key.getExternalSystemId()); + final RemoteExternalSystemFacade facade = communicationManager.acquire(key.getExternalProjectConfigPath(), key.getExternalSystemId()); if (facade == null) { throw new IllegalStateException("Can't obtain facade to working with external api at the remote process. Project: " + project); } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/RemoteExternalSystemCommunicationManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/RemoteExternalSystemCommunicationManager.java index b8ad4f16b932..2cc4b2eb5cca 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/RemoteExternalSystemCommunicationManager.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/RemoteExternalSystemCommunicationManager.java @@ -60,6 +60,7 @@ import com.intellij.util.containers.ContainerUtilRt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.nio.charset.Charset; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; @@ -99,7 +100,7 @@ public class RemoteExternalSystemCommunicationManager implements ExternalSystemC @Override protected RunProfileState getRunProfileState(Object o, String configuration, Executor executor) throws ExecutionException { - return createRunProfileState(); + return createRunProfileState(configuration); } }; @@ -114,14 +115,15 @@ public class RemoteExternalSystemCommunicationManager implements ExternalSystemC mySupport.stopAll(wait); } - private RunProfileState createRunProfileState() { + private RunProfileState createRunProfileState(final String configuration) { return new CommandLineState(null) { private SimpleJavaParameters createJavaParameters() throws ExecutionException { final SimpleJavaParameters params = new SimpleJavaParameters(); params.setJdk(new SimpleJavaSdkType().createJdk("tmp", SystemProperties.getJavaHome())); - params.setWorkingDirectory(PathManager.getBinPath()); + File myWorkingDirectory = new File(configuration); + params.setWorkingDirectory(myWorkingDirectory.isDirectory() ? myWorkingDirectory.getPath() : PathManager.getBinPath()); final List classPath = ContainerUtilRt.newArrayList(); // IDE jars. diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java index bf5179c220d6..3a761b550192 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java @@ -39,6 +39,7 @@ import org.jetbrains.plugins.gradle.settings.DistributionType; import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings; import org.jetbrains.plugins.gradle.tooling.internal.init.Init; import org.jetbrains.plugins.gradle.util.GradleConstants; +import org.jetbrains.plugins.gradle.util.GradleEnvironment; import org.jetbrains.plugins.gradle.util.GradleUtil; import java.io.File; @@ -188,16 +189,13 @@ public class GradleExecutionHelper { projectDir = projectPath; } - // This is a workaround to get right base dir in case of 'PROJECT' setting used in case custom wrapper property file location - // see org.gradle.wrapper.PathAssembler#getBaseDir for details String userDir = null; - if (settings != null && settings.getDistributionType() == DistributionType.WRAPPED) { + if (!GradleEnvironment.ADJUST_USER_DIR) { try { userDir = System.getProperty("user.dir"); - System.setProperty("user.dir", projectDir); + if (userDir != null) System.setProperty("user.dir", projectDir); } - catch (Exception e) { - // ignore + catch (Exception ignore) { } } ProjectConnection connection = getConnection(projectDir, settings); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEnvironment.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEnvironment.java index cdd8afb782e8..2c61ac6c10eb 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEnvironment.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEnvironment.java @@ -11,6 +11,7 @@ public class GradleEnvironment { @NonNls public static final boolean DEBUG_GRADLE_HOME_PROCESSING = Boolean.getBoolean("gradle.debug.home.processing"); @NonNls public static final boolean DISABLE_ENHANCED_TOOLING_API = Boolean.getBoolean("gradle.disable.enhanced.tooling.api"); + @NonNls public static final boolean ADJUST_USER_DIR = Boolean.getBoolean("gradle.adjust.userdir"); private GradleEnvironment() { } From f3efd90a0d6248dc5946e5c04e02b2c95fec13bb Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Wed, 23 Apr 2014 18:16:46 +0400 Subject: [PATCH 75/86] IDEA-120865 jre7 osx fullscreen: "space" is not freed when project is closed --- .../openapi/wm/impl/IdeFrameImpl.java | 14 +++++++ .../ui/mac/MacMainFrameDecorator.java | 41 +++++++++++++++---- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java index 33e0a84f68a8..a782ee10472d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.wm.impl; +import com.apple.eawt.AppEvent; import com.intellij.diagnostic.IdeMessagePanel; import com.intellij.ide.AppLifecycleListener; import com.intellij.ide.DataManager; @@ -52,6 +53,7 @@ import com.intellij.openapi.wm.ex.StatusBarEx; import com.intellij.openapi.wm.impl.status.*; import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame; import com.intellij.ui.*; +import com.intellij.ui.mac.MacMainFrameDecorator; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -63,6 +65,10 @@ import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author Anton Katilin @@ -455,6 +461,14 @@ public class IdeFrameImpl extends JFrame implements IdeFrameEx, DataProvider { } public void dispose() { + if (SystemInfo.isMac && isInFullScreen()) { + ((MacMainFrameDecorator)myFrameDecorator).exitFullScreenAndDispose(); + } else { + disposeImpl(); + } + } + + public void disposeImpl() { if (isTemporaryDisposed()) { super.dispose(); return; diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java b/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java index 64d904de69ca..dcb514fc1179 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java @@ -25,6 +25,7 @@ import com.intellij.openapi.application.impl.LaterInvocator; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.BuildNumber; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.wm.impl.IdeFrameDecorator; import com.intellij.openapi.wm.impl.IdeFrameImpl; @@ -47,6 +48,9 @@ import java.lang.reflect.Method; import java.util.EventListener; import java.util.LinkedList; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import static com.intellij.ui.mac.foundation.Foundation.invoke; @@ -378,17 +382,38 @@ public class MacMainFrameDecorator extends IdeFrameDecorator implements UISettin @Override public void run() { try { - requestToggleFullScreenMethod.invoke(Application.getApplication(),myFrame); - } - catch (IllegalAccessException e) { - LOG.error(e); - } - catch (InvocationTargetException e) { - LOG.error(e); - } + requestToggleFullScreenMethod.invoke(Application.getApplication(),myFrame); + } + catch (IllegalAccessException e) { + LOG.error(e); + } + catch (InvocationTargetException e) { + LOG.error(e); + } } }); return callback; } + public void exitFullScreenAndDispose() { + + LOG.assertTrue(isInFullScreen()); + try { + requestToggleFullScreenMethod.invoke(Application.getApplication(), myFrame); + } + catch (IllegalAccessException e) { + LOG.error(e); + } + catch (InvocationTargetException e) { + LOG.error(e); + } + + myDispatcher.addListener(new FSAdapter() { + @Override + public void windowExitedFullScreen(AppEvent.FullScreenEvent event) { + myFrame.disposeImpl(); + myDispatcher.removeListener(this); + } + }); + } } From 54ced00cb4570589176b74dcf7441966030bd140 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 23 Apr 2014 13:06:43 +0200 Subject: [PATCH 76/86] highlight all pairs of methods with same erasures (IDEA-124116) --- .../impl/analysis/GenericsHighlightUtil.java | 20 +++++++++++++------ .../impl/analysis/HighlightVisitorImpl.java | 5 ++--- .../PairsWithSameErasure.java | 9 +++++++++ .../daemon/GenericsHighlightingTest.java | 1 + 4 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/PairsWithSameErasure.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 14c32171c19f..e6de88efc4e0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -42,6 +42,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; import gnu.trove.THashMap; +import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -326,7 +327,8 @@ public class GenericsHighlightUtil { if (errorResult == null && languageLevel.isAtLeast(LanguageLevel.JDK_1_7) && referenceElements.length > 1) { //todo suppress erased methods which come from the same class - return checkOverrideEquivalentMethods(languageLevel, aClass); + final Collection result = checkOverrideEquivalentMethods(languageLevel, aClass); + return result != null && result.size() > 0 ? result.iterator().next() : null; } return errorResult; } @@ -380,23 +382,29 @@ public class GenericsHighlightUtil { return null; } - public static HighlightInfo checkOverrideEquivalentMethods(@NotNull LanguageLevel languageLevel, - @NotNull PsiClass aClass) { + public static Collection checkOverrideEquivalentMethods(@NotNull LanguageLevel languageLevel, + @NotNull PsiClass aClass) { + List result = new ArrayList(); final Collection signaturesWithSupers = aClass.getVisibleSignatures(); PsiManager manager = aClass.getManager(); Map sameErasureMethods = new THashMap(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY); + final Set foundProblems = new THashSet(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY); for (HierarchicalMethodSignature signature : signaturesWithSupers) { HighlightInfo info = checkSameErasureNotSubSignatureInner(signature, manager, aClass, sameErasureMethods); - if (info != null) return info; + if (info != null && foundProblems.add(signature)) { + result.add(info); + } if (aClass instanceof PsiTypeParameter) { info = HighlightMethodUtil.checkMethodIncompatibleReturnType(signature, signature.getSuperSignatures(), true, HighlightNamesUtil.getClassDeclarationTextRange(aClass)); - if (info != null) return info; + if (info != null) { + result.add(info); + } } } - return null; + return result.isEmpty() ? null : result; } static HighlightInfo checkDefaultMethodOverrideEquivalentToObjectNonPrivate(@NotNull LanguageLevel languageLevel, diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index f386b646f1e4..e390d435707c 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -888,8 +888,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh myHolder.add(HighlightClassUtil.checkClassDoesNotCallSuperConstructorOrHandleExceptions(aClass, myRefCountHolder, myResolveHelper)); } if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkOverrideEquivalentInheritedMethods(aClass, myFile)); - if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkOverrideEquivalentMethods(myLanguageLevel, aClass - )); + if (!myHolder.hasErrorResults()) myHolder.addAll(GenericsHighlightUtil.checkOverrideEquivalentMethods(myLanguageLevel, aClass)); if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCyclicInheritance(aClass)); } catch (IndexNotReadyException ignored) { @@ -1045,7 +1044,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (parent instanceof PsiAnonymousClass && ref.equals(((PsiAnonymousClass)parent).getBaseClassReference())) { PsiClass aClass = (PsiClass)parent; - myHolder.add(GenericsHighlightUtil.checkOverrideEquivalentMethods(myLanguageLevel, aClass)); + myHolder.addAll(GenericsHighlightUtil.checkOverrideEquivalentMethods(myLanguageLevel, aClass)); } if (resolved instanceof PsiVariable) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/PairsWithSameErasure.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/PairsWithSameErasure.java new file mode 100644 index 000000000000..f7d2f026491b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/PairsWithSameErasure.java @@ -0,0 +1,9 @@ +import java.util.List; + +class MyClass { + void method1 (Comparable c) {} + void method1(Comparable c) {} + + void method2(List l) {} + void method2(List l) {} +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index c0ef03ce72b3..aaf4d57b87a1 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -74,6 +74,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testEnum() { doTest(LanguageLevel.JDK_1_5, JavaSdkVersion.JDK_1_5, false); } public void testEnum56239() { doTest(LanguageLevel.JDK_1_6, JavaSdkVersion.JDK_1_6, false); } public void testSameErasure() { doTest5(false); } + public void testPairsWithSameErasure() { doTest5(false); } public void testMethods() { doTest5(false); } public void testFields() { doTest5(false); } public void testStaticImports() { doTest5(true); } From 2200bba35fae74efe277742dc11efd668c72e2c4 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 23 Apr 2014 13:31:45 +0200 Subject: [PATCH 77/86] method hierarchy: search functional expressions by current method only (IDEA-124320); navigation (IDEA-124319) --- .../method/MethodHierarchyNodeDescriptor.java | 2 +- .../method/MethodHierarchyTreeStructure.java | 17 ++++++++++------- .../intellij/psi/PsiFunctionalExpression.java | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java b/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java index 61e530339ffa..dbdcff0f798b 100644 --- a/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java +++ b/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyNodeDescriptor.java @@ -52,7 +52,7 @@ public final class MethodHierarchyNodeDescriptor extends HierarchyNodeDescriptor myTreeStructure = treeStructure; } - private PsiMethod getMethod(final PsiClass aClass, final boolean checkBases) { + PsiMethod getMethod(final PsiClass aClass, final boolean checkBases) { return MethodHierarchyUtil.findBaseMethodInClass(myTreeStructure.getBaseMethod(), aClass, checkBases); } diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyTreeStructure.java b/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyTreeStructure.java index 7a5e86953689..922fc2d85644 100644 --- a/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyTreeStructure.java +++ b/java/java-impl/src/com/intellij/ide/hierarchy/method/MethodHierarchyTreeStructure.java @@ -172,13 +172,16 @@ public final class MethodHierarchyTreeStructure extends HierarchyTreeStructure { descriptors.add(d); } - FunctionalExpressionSearch.search(getBaseMethod()).forEach(new Processor() { - @Override - public boolean process(PsiFunctionalExpression expression) { - descriptors.add(new MethodHierarchyNodeDescriptor(myProject, descriptor, expression, false, MethodHierarchyTreeStructure.this)); - return true; - } - }); + final PsiMethod existingMethod = ((MethodHierarchyNodeDescriptor)descriptor).getMethod(psiClass, false); + if (existingMethod != null) { + FunctionalExpressionSearch.search(existingMethod).forEach(new Processor() { + @Override + public boolean process(PsiFunctionalExpression expression) { + descriptors.add(new MethodHierarchyNodeDescriptor(myProject, descriptor, expression, false, MethodHierarchyTreeStructure.this)); + return true; + } + }); + } return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiFunctionalExpression.java b/java/java-psi-api/src/com/intellij/psi/PsiFunctionalExpression.java index e03806582884..2afbe46754d1 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiFunctionalExpression.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiFunctionalExpression.java @@ -18,7 +18,7 @@ package com.intellij.psi; import com.intellij.openapi.util.Iconable; import org.jetbrains.annotations.Nullable; -public interface PsiFunctionalExpression extends PsiExpression, Iconable { +public interface PsiFunctionalExpression extends PsiExpression, Iconable, NavigatablePsiElement { /** * @return SAM type the lambda expression corresponds to * null when no SAM type could be found From 265f0dca89b6257d1c468219f94b7dc2cfaa71ad Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 23 Apr 2014 14:12:03 +0200 Subject: [PATCH 78/86] lambda -> anonymous: static calls (IDEA-124187) --- .../ReplaceLambdaWithAnonymousIntention.java | 11 +++++++---- .../ipp/types/lambda2anonymous/StaticCalls.java | 11 +++++++++++ .../lambda2anonymous/StaticCalls_after.java | 16 ++++++++++++++++ .../ReplaceLambdaWithAnonymousIntentionTest.java | 4 ++++ 4 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/StaticCalls.java create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/StaticCalls_after.java diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntention.java index 13f7f8b4c814..26ca6de593ed 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntention.java @@ -64,8 +64,8 @@ public class ReplaceLambdaWithAnonymousIntention extends Intention { PsiCodeBlock blockFromText = psiElementFactory.createCodeBlockFromText(blockText, lambdaExpression); ChangeContextUtil.encodeContextInfo(blockFromText, true); PsiNewExpression newExpression = (PsiNewExpression)psiElementFactory.createExpressionFromText("new " + functionalInterfaceType.getCanonicalText() + "(){}", lambdaExpression); - final PsiClass thisClass = PsiTreeUtil.getParentOfType(lambdaExpression, PsiClass.class, true); - final String thisClassName = thisClass.getName(); + final PsiClass thisClass = RefactoringChangeUtil.getThisClass(lambdaExpression); + final String thisClassName = thisClass != null ? thisClass.getName() : null; if (thisClassName != null) { final PsiThisExpression thisAccessExpr = thisClass instanceof PsiAnonymousClass ? null : RefactoringChangeUtil .createThisExpression(lambdaExpression.getManager(), thisClass); @@ -86,8 +86,11 @@ public class ReplaceLambdaWithAnonymousIntention extends Intention { @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); - if (thisAccessExpr != null && expression.getMethodExpression().getQualifierExpression() == null) { - replacements.put(expression, psiElementFactory.createExpressionFromText(thisAccessExpr.getText() + "." + expression.getText(), expression)); + if (thisAccessExpr != null) { + final PsiMethod psiMethod = expression.resolveMethod(); + if (psiMethod != null && !psiMethod.hasModifierProperty(PsiModifier.STATIC) && expression.getMethodExpression().getQualifierExpression() == null) { + replacements.put(expression, psiElementFactory.createExpressionFromText(thisAccessExpr.getText() + "." + expression.getText(), expression)); + } } } }); diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/StaticCalls.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/StaticCalls.java new file mode 100644 index 000000000000..b4fa8c284200 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/StaticCalls.java @@ -0,0 +1,11 @@ +class Foo { + + public static void main(String[] args) { + new Thread(() -> print()); + } + + public static void print() { + System.out.println("print"); + } + +} diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/StaticCalls_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/StaticCalls_after.java new file mode 100644 index 000000000000..2d4f54c9ab7f --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/StaticCalls_after.java @@ -0,0 +1,16 @@ +class Foo { + + public static void main(String[] args) { + new Thread(new Runnable() { + @Override + public void run() { + print(); + } + }); + } + + public static void print() { + System.out.println("print"); + } + +} diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntentionTest.java index a6076422ffd5..6f209415d468 100644 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntentionTest.java +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntentionTest.java @@ -75,6 +75,10 @@ public class ReplaceLambdaWithAnonymousIntentionTest extends IPPTestCase { doTest(); } + public void testStaticCalls() { + doTest(); + } + @Override protected String getIntentionName() { return IntentionPowerPackBundle.message("replace.lambda.with.anonymous.intention.name"); From c160fc5adf7e94acaab1419538f1464c7af52e54 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 23 Apr 2014 15:17:11 +0200 Subject: [PATCH 79/86] copy to temp/array for non-effectively final variables used in lambda expressions --- .../intention/QuickFixFactory.java | 2 +- .../analysis/HighlightControlFlowUtil.java | 23 +++++++---- .../VariableAccessFromInnerClassFix.java | 38 +++++++++---------- .../impl/config/QuickFixFactoryImpl.java | 4 +- .../mustBeFinal18/afterInsideLambda.java | 11 ++++++ .../mustBeFinal18/beforeInsideLambda.java | 10 +++++ .../VariableAccessFromInnerClass18Test.java | 19 ---------- .../VariableAccessFromInnerClassTest.java | 6 ++- 8 files changed, 63 insertions(+), 50 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18/afterInsideLambda.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18/beforeInsideLambda.java diff --git a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java index 8bbc7567cbdc..c72c5fcceb5d 100644 --- a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java +++ b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java @@ -206,7 +206,7 @@ public abstract class QuickFixFactory { @NotNull public abstract IntentionAction createDeferFinalAssignmentFix(@NotNull PsiVariable variable, @NotNull PsiReferenceExpression expression); - @NotNull public abstract IntentionAction createVariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiClass aClass); + @NotNull public abstract IntentionAction createVariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiElement scope); @NotNull public abstract IntentionAction createCreateConstructorParameterFromFieldFix(@NotNull PsiField field); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java index 73603037a187..40463be3d6e1 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java @@ -590,7 +590,7 @@ public class HighlightControlFlowUtil { JavaErrorMessages.message("assignment.to.final.variable", name); final HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(reference.getTextRange()).descriptionAndTooltip(description).create(); - final PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, expression); + final PsiElement innerClass = getInnerClassVariableReferencedFrom(variable, expression); if (innerClass == null || variable instanceof PsiField) { QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createModifierListFix(variable, PsiModifier.FINAL, false, false)); @@ -607,7 +607,7 @@ public class HighlightControlFlowUtil { private static boolean canWriteToFinal(PsiVariable variable, PsiExpression expression, final PsiReferenceExpression reference, @NotNull PsiFile containingFile) { if (variable.hasInitializer()) return false; if (variable instanceof PsiParameter) return false; - PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, expression); + PsiElement innerClass = getInnerClassVariableReferencedFrom(variable, expression); if (variable instanceof PsiField) { // if inside some field initializer if (HighlightUtil.findEnclosingFieldInitializer(expression) != null) return true; @@ -642,8 +642,8 @@ public class HighlightControlFlowUtil { @NotNull PsiJavaCodeReferenceElement context, @NotNull LanguageLevel languageLevel) { if (variable.hasModifierProperty(PsiModifier.FINAL)) return null; - final PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, context); - if (innerClass != null) { + final PsiElement innerClass = getInnerClassVariableReferencedFrom(variable, context); + if (innerClass instanceof PsiClass) { if (variable instanceof PsiParameter) { final PsiElement parent = variable.getParent(); if (parent instanceof PsiParameterList && parent.getParent() instanceof PsiLambdaExpression && @@ -672,8 +672,12 @@ public class HighlightControlFlowUtil { return null; } if (!isEffectivelyFinal(variable, lambdaExpression, context)) { - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(context).descriptionAndTooltip( - "Variable used in lambda expression should be effectively final").create(); + final HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(context) + .descriptionAndTooltip("Variable used in lambda expression should be effectively final") + .create(); + QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createVariableAccessFromInnerClassFix(variable, lambdaExpression)); + return highlightInfo; } } return null; @@ -716,7 +720,7 @@ public class HighlightControlFlowUtil { } @Nullable - public static PsiClass getInnerClassVariableReferencedFrom(@NotNull PsiVariable variable, @NotNull PsiElement context) { + public static PsiElement getInnerClassVariableReferencedFrom(@NotNull PsiVariable variable, @NotNull PsiElement context) { final PsiElement[] scope; if (variable instanceof PsiResourceVariable) { scope = ((PsiResourceVariable)variable).getDeclarationScope(); @@ -741,7 +745,10 @@ public class HighlightControlFlowUtil { if (parent.equals(scopeElement)) break outer; } if (parent instanceof PsiClass && !(prevParent instanceof PsiExpressionList && parent instanceof PsiAnonymousClass)) { - return (PsiClass)parent; + return parent; + } + if (parent instanceof PsiLambdaExpression) { + return parent; } prevParent = parent; parent = parent.getParent(); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java index 98a271629093..47ed78e48760 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java @@ -42,16 +42,16 @@ import java.util.*; public class VariableAccessFromInnerClassFix implements IntentionAction { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.VariableAccessFromInnerClassFix"); private final PsiVariable myVariable; - private final PsiClass myClass; + private final PsiElement myContext; private final int myFixType; private static final int MAKE_FINAL = 0; private static final int MAKE_ARRAY = 1; private static final int COPY_TO_FINAL = 2; private static final Key>[] VARS = new Key[] {Key.create("VARS_TO_MAKE_FINAL"), Key.create("VARS_TO_TRANSFORM"), Key.create("???")}; - public VariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiClass aClass) { + public VariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiElement element) { myVariable = variable; - myClass = aClass; + myContext = element; myFixType = getQuickFixType(variable); if (myFixType == -1) return; @@ -87,21 +87,21 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return myClass.isValid() && - myClass.getManager().isInProject(myClass) && + return myContext.isValid() && + myContext.getManager().isInProject(myContext) && myVariable.isValid() && myFixType != -1 && !getVariablesToFix().isEmpty() && - !inOwnInitializer(myVariable, myClass); + !inOwnInitializer(myVariable, myContext); } - private static boolean inOwnInitializer(PsiVariable variable, PsiClass aClass) { - return PsiTreeUtil.isAncestor(variable, aClass, false); + private static boolean inOwnInitializer(PsiVariable variable, PsiElement context) { + return PsiTreeUtil.isAncestor(variable, context, false); } @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) { - if (!FileModificationService.getInstance().preparePsiElementsForWrite(myClass, myVariable)) return; + if (!FileModificationService.getInstance().preparePsiElementsForWrite(myContext, myVariable)) return; try { switch (myFixType) { case MAKE_FINAL: @@ -131,8 +131,8 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { @NotNull private Collection getVariablesToFix() { - Map vars = myClass.getUserData(VARS[myFixType]); - if (vars == null) myClass.putUserData(VARS[myFixType], vars = new ConcurrentWeakHashMap(1)); + Map vars = myContext.getUserData(VARS[myFixType]); + if (vars == null) myContext.putUserData(VARS[myFixType], vars = new ConcurrentWeakHashMap(1)); final Map finalVars = vars; return new AbstractCollection() { @Override @@ -164,7 +164,7 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { private void makeArray(PsiVariable variable) throws IncorrectOperationException { PsiType type = variable.getType(); - PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory(); + PsiElementFactory factory = JavaPsiFacade.getInstance(myContext.getProject()).getElementFactory(); PsiType newType = type.createArrayType(); PsiDeclarationStatement variableDeclarationStatement; @@ -195,9 +195,9 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { } private void copyToFinal() throws IncorrectOperationException { - PsiManager psiManager = myClass.getManager(); + PsiManager psiManager = myContext.getManager(); PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory(); - PsiExpression initializer = factory.createExpressionFromText(myVariable.getName(), myClass); + PsiExpression initializer = factory.createExpressionFromText(myVariable.getName(), myContext); String newName = suggestNewName(psiManager.getProject(), myVariable); PsiType type = myVariable.getType(); PsiDeclarationStatement copyDecl = factory.createVariableDeclarationStatement(newName, type, initializer); @@ -206,7 +206,7 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { PsiElement statement = getStatementToInsertBefore(); if (statement == null) return; PsiExpression newExpression = factory.createExpressionFromText(newName, myVariable); - replaceReferences(myClass, myVariable, newExpression); + replaceReferences(myContext, myVariable, newExpression); if (RefactoringUtil.isLoopOrIf(statement.getParent())) { RefactoringUtil.putStatementInLoopBody(copyDecl, statement.getParent(), statement); } else { @@ -219,7 +219,7 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { ? ((PsiParameter)myVariable).getDeclarationScope() : PsiUtil.getVariableCodeBlock(myVariable, null); if (declarationScope == null) return null; - PsiElement statement = myClass; + PsiElement statement = myContext; nextInnerClass: do { statement = RefactoringUtil.getParentStatement(statement, false); @@ -291,11 +291,11 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { int type = MAKE_FINAL; for (PsiReferenceExpression expression : outerReferences) { // if it happens that variable referenced from another inner class, make sure it can be make final from there - PsiClass innerClass = HighlightControlFlowUtil.getInnerClassVariableReferencedFrom(variable, expression); + PsiElement innerScope = HighlightControlFlowUtil.getInnerClassVariableReferencedFrom(variable, expression); - if (innerClass != null) { + if (innerScope != null) { int thisType = MAKE_FINAL; - if (writtenInside(variable, innerClass)) { + if (writtenInside(variable, innerScope)) { // cannot make parameter array if (variable instanceof PsiParameter) return -1; thisType = MAKE_ARRAY; diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java index 5f95da053db3..c8a6cfa0271f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java @@ -547,8 +547,8 @@ public class QuickFixFactoryImpl extends QuickFixFactory { @NotNull @Override - public IntentionAction createVariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiClass aClass) { - return new VariableAccessFromInnerClassFix(variable, aClass); + public IntentionAction createVariableAccessFromInnerClassFix(@NotNull PsiVariable variable, @NotNull PsiElement scope) { + return new VariableAccessFromInnerClassFix(variable, scope); } @NotNull diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18/afterInsideLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18/afterInsideLambda.java new file mode 100644 index 000000000000..8754e8e4ebbe --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18/afterInsideLambda.java @@ -0,0 +1,11 @@ +// "Copy 'a' to temp final variable" "true" +class Test { + public void test() { + int a = 1; + a = 2; + final int finalA = a; + Runnable r = () -> { + System.out.println(finalA); + }; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18/beforeInsideLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18/beforeInsideLambda.java new file mode 100644 index 000000000000..7dabe1912e37 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18/beforeInsideLambda.java @@ -0,0 +1,10 @@ +// "Copy 'a' to temp final variable" "true" +class Test { + public void test() { + int a = 1; + a = 2; + Runnable r = () -> { + System.out.println(a); + }; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableAccessFromInnerClass18Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableAccessFromInnerClass18Test.java index 84201d73e69b..dfdf74b15a33 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableAccessFromInnerClass18Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableAccessFromInnerClass18Test.java @@ -15,8 +15,6 @@ */ package com.intellij.codeInsight.daemon.quickFix; -import com.intellij.openapi.command.WriteCommandAction; - /** * User: anna */ @@ -29,21 +27,4 @@ public class VariableAccessFromInnerClass18Test extends LightQuickFixParameteriz protected String getBasePath() { return "/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18"; } - - @Override - protected void beforeActionStarted(String testName, String contents) { - for (int i=0;i<10;i++) { - WriteCommandAction.runWriteCommandAction(null, new Runnable() { - @Override - public void run() { - myEditor.getDocument().insertString(myEditor.getCaretModel().getOffset(), "//"); - } - }); - - doHighlighting(); - delete(); - delete(); - doHighlighting(); - } - } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableAccessFromInnerClassTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableAccessFromInnerClassTest.java index 98b8a7432baf..e5bd455a9dd9 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableAccessFromInnerClassTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableAccessFromInnerClassTest.java @@ -3,8 +3,12 @@ package com.intellij.codeInsight.daemon.quickFix; import com.intellij.pom.java.LanguageLevel; -public class VariableAccessFromInnerClassTest extends VariableAccessFromInnerClass18Test { +public class VariableAccessFromInnerClassTest extends LightQuickFixParameterizedTestCase { + public void test() throws Exception { + doAllTests(); + } + @Override protected String getBasePath() { return "/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal"; From 1c431a8076f1cf43747a753f58297b10c1aa33cb Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 23 Apr 2014 15:35:14 +0200 Subject: [PATCH 80/86] create meth reference from usage: substitute param types (IDEA-124322) --- .../CreateMethodFromMethodReferenceFix.java | 5 +++-- .../afterSubstitutionParams.java | 15 +++++++++++++++ .../beforeSubstitutionParams.java | 11 +++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromMethodRef/afterSubstitutionParams.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromMethodRef/beforeSubstitutionParams.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromMethodReferenceFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromMethodReferenceFix.java index b0c29bf641e3..74df48381201 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromMethodReferenceFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromMethodReferenceFix.java @@ -124,15 +124,16 @@ public class CreateMethodFromMethodReferenceFix extends CreateFromUsageBaseFix { final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType); LOG.assertTrue(interfaceReturnType != null); + final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, classResolveResult); final ExpectedTypeInfo[] expectedTypes = {new ExpectedTypeInfoImpl(interfaceReturnType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, interfaceReturnType, TailType.NONE, null, ExpectedTypeInfoImpl.NULL)}; CreateMethodFromUsageFix.doCreate(targetClass, method, false, ContainerUtil.map2List(interfaceMethod.getParameterList().getParameters(), new Function>() { @Override public Pair fun(PsiParameter parameter) { - return Pair.create(null, parameter.getType()); + return Pair.create(null, substitutor.substitute(parameter.getType())); } }), - LambdaUtil.getSubstitutor(interfaceMethod, classResolveResult), + PsiSubstitutor.EMPTY, expectedTypes, context); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromMethodRef/afterSubstitutionParams.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromMethodRef/afterSubstitutionParams.java new file mode 100644 index 000000000000..f4c31662d976 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromMethodRef/afterSubstitutionParams.java @@ -0,0 +1,15 @@ +// "Create Method 'fooBar'" "true" +class FooBar { + { + Comparator c = this::fooBar; + } + + private int fooBar(String s, String s1) { + return 0; + } +} + + +interface Comparator { + int compare(T o1, T o2); +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromMethodRef/beforeSubstitutionParams.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromMethodRef/beforeSubstitutionParams.java new file mode 100644 index 000000000000..96dc6d176061 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromMethodRef/beforeSubstitutionParams.java @@ -0,0 +1,11 @@ +// "Create Method 'fooBar'" "true" +class FooBar { + { + Comparator c = this::fooBar; + } +} + + +interface Comparator { + int compare(T o1, T o2); +} \ No newline at end of file From f72e4f5a7cc54aeb77cafeb0797d30ccf2295dcf Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 23 Apr 2014 15:44:04 +0200 Subject: [PATCH 81/86] testdata for IDEA-124148 --- .../lambda/newMethodRef/IDEA124148.java | 25 +++++++++++++++++++ .../lambda/NewMethodRefHighlightingTest.java | 4 +++ 2 files changed, 29 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA124148.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA124148.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA124148.java new file mode 100644 index 000000000000..073d6494557c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA124148.java @@ -0,0 +1,25 @@ +import java.util.*; + + +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Supplier; + +class A +{ + public S foldRight(Supplier value, BiFunction, Supplier> f) + { + return null; + } + + public static Optional h(A flow) + { + return flow.foldRight(() -> Optional.empty(), (element, lazyResult) -> () -> Optional.of(element)); + + } + + public static Optional hR(A flow) + { + return flow.foldRight(Optional::empty, (element, lazyResult) -> () -> Optional.of(element)); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java index 4dbe40750de2..4028d71b7ca0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java @@ -245,6 +245,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(true); } + public void testIDEA124148() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } From 0d9b47d5ae18d15f926fd26cf65951db6fb817ad Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Wed, 23 Apr 2014 18:34:07 +0400 Subject: [PATCH 82/86] IDEA-124260 Data Sources and Drivers: can't apply changes to schemas that are shown and used to resolve --- .../src/com/intellij/ui/ComponentTreeWatcher.java | 8 ++++++-- .../src/com/intellij/ui/UserActivityWatcher.java | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/ComponentTreeWatcher.java b/platform/platform-api/src/com/intellij/ui/ComponentTreeWatcher.java index cbcceb34c5b5..15364cbf6ba7 100644 --- a/platform/platform-api/src/com/intellij/ui/ComponentTreeWatcher.java +++ b/platform/platform-api/src/com/intellij/ui/ComponentTreeWatcher.java @@ -63,7 +63,7 @@ public abstract class ComponentTreeWatcher { return; } - if (parentComponent instanceof Container) { + if (parentComponent instanceof Container && processChildren((Container)parentComponent)) { Container container = (Container)parentComponent; for (int i = 0; i < container.getComponentCount(); i++) { register(container.getComponent(i)); @@ -74,11 +74,15 @@ public abstract class ComponentTreeWatcher { processComponent(parentComponent); } + protected boolean processChildren(Container container) { + return true; + } + protected abstract void processComponent(Component parentComponent); private void unregister(Component component) { - if (component instanceof Container) { + if (component instanceof Container && processChildren((Container)component)) { Container container = (Container)component; for (int i = 0; i < container.getComponentCount(); i++) { unregister(container.getComponent(i)); diff --git a/platform/platform-api/src/com/intellij/ui/UserActivityWatcher.java b/platform/platform-api/src/com/intellij/ui/UserActivityWatcher.java index cbe1b841dda4..031eb947857c 100644 --- a/platform/platform-api/src/com/intellij/ui/UserActivityWatcher.java +++ b/platform/platform-api/src/com/intellij/ui/UserActivityWatcher.java @@ -16,6 +16,7 @@ package com.intellij.ui; import com.intellij.openapi.Disposable; +import com.intellij.openapi.ui.ComboBox; import com.intellij.util.ArrayUtil; import com.intellij.util.EventDispatcher; @@ -51,6 +52,7 @@ public class UserActivityWatcher extends ComponentTreeWatcher { fireUIChanged(); } }; + private final PropertyChangeListener myTableListener = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { TableModel oldModel = (TableModel)evt.getOldValue(); @@ -68,12 +70,19 @@ public class UserActivityWatcher extends ComponentTreeWatcher { } } }; + private final ChangeListener myChangeListener = new ChangeListener() { public void stateChanged(final ChangeEvent e) { fireUIChanged(); } }; + private final PropertyChangeListener myCellEditorChangeListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if (e.getOldValue() != null && e.getNewValue() == null) fireUIChanged(); + } + }; + public void addUserActivityListener(UserActivityListener listener) { myListeners.addListener(listener); } @@ -147,6 +156,10 @@ public class UserActivityWatcher extends ComponentTreeWatcher { } + protected boolean processChildren(Container container) { + return !(container instanceof JTable); + } + protected void processComponent(final Component parentComponent) { if (parentComponent instanceof JTextComponent) { ((JTextComponent)parentComponent).getDocument().addDocumentListener(myDocumentListener); @@ -177,6 +190,7 @@ public class UserActivityWatcher extends ComponentTreeWatcher { if (model != null) { model.addTableModelListener(myTableModelListener); } + table.addPropertyChangeListener(ComboBox.TABLE_CELL_EDITOR_PROPERTY, myCellEditorChangeListener); } if (parentComponent instanceof JSlider) { @@ -206,6 +220,7 @@ public class UserActivityWatcher extends ComponentTreeWatcher { if (model != null) { model.removeTableModelListener(myTableModelListener); } + component.removePropertyChangeListener(myCellEditorChangeListener); } if (component instanceof JSlider){ From 76f35f3cf7f523326226eac6a9fa7c7a1c9783be Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Wed, 23 Apr 2014 16:56:29 +0400 Subject: [PATCH 83/86] suppress doCancelAction --- .../com/intellij/ide/customize/CustomizeIDEWizardDialog.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java index 47eecc092162..203e0418f6de 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java @@ -139,6 +139,11 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis } } + @Override + public void doCancelAction() { + // lets pretend it is the wind.. + } + @Override protected void doOKAction() { for (AbstractCustomizeWizardStep step : mySteps) { From 1d04dc782352086863ba94b76667abc453d157ee Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 23 Apr 2014 20:25:48 +0400 Subject: [PATCH 84/86] fixed unittest folder tests --- python/helpers/pycharm/utrunner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/helpers/pycharm/utrunner.py b/python/helpers/pycharm/utrunner.py index b2e333bd6d9d..1f11206b7d30 100644 --- a/python/helpers/pycharm/utrunner.py +++ b/python/helpers/pycharm/utrunner.py @@ -104,7 +104,7 @@ if __name__ == "__main__": a_splitted = a[0].split(";") if len(a_splitted) != 1: # means we have pattern to match against - if a_splitted[0].endswith("/"): + if a_splitted[0].endswith(os.path.sep): debug("/ from folder " + a_splitted[0] + ". Use pattern: " + a_splitted[1]) modules = loadModulesFromFolderRec(a_splitted[0], a_splitted[1]) else: From 817908d1b1cf675edf9ad5024477858f49514026 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 23 Apr 2014 20:45:14 +0400 Subject: [PATCH 85/86] fixed importing for the iron python --- python/helpers/pycharm/pycharm_run_utils.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/helpers/pycharm/pycharm_run_utils.py b/python/helpers/pycharm/pycharm_run_utils.py index d905d0542303..78aada54daaa 100644 --- a/python/helpers/pycharm/pycharm_run_utils.py +++ b/python/helpers/pycharm/pycharm_run_utils.py @@ -1,7 +1,9 @@ __author__ = 'ktisha' -import os, sys +import os +import sys import imp + PYTHON_VERSION_MAJOR = sys.version_info[0] PYTHON_VERSION_MINOR = sys.version_info[1] @@ -26,6 +28,8 @@ def adjust_django_sys_path(): sys.path.append(pycharm_path) def import_system_module(name): + if sys.platform == "cli": # hack for the ironpython + return __import__(name) f, filename, desc = imp.find_module(name) return imp.load_module('pycharm_' + name, f, filename, desc) From 2bd67bce3eed4e3609d2efe9a0039bc353cd24e9 Mon Sep 17 00:00:00 2001 From: Vassiliy Date: Wed, 23 Apr 2014 21:46:24 +0400 Subject: [PATCH 86/86] IDEA-90194 Ability to disable drag & drop in Project View --- .../src/com/intellij/ide/ui/UISettings.java | 1 + .../src/com/intellij/ui/MouseDragHelper.java | 16 +++++++++---- .../com/intellij/ui/tabs/impl/DragHelper.java | 2 +- .../com/intellij/ide/dnd/DnDManagerImpl.java | 3 ++- .../ide/ui/AppearanceConfigurable.java | 4 ++++ .../com/intellij/ide/ui/AppearancePanel.form | 24 +++++++++++++------ .../openapi/wm/impl/StripeButton.java | 2 +- 7 files changed, 38 insertions(+), 14 deletions(-) diff --git a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java index f0980909d743..dba42bec1155 100644 --- a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java +++ b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java @@ -110,6 +110,7 @@ public class UISettings implements PersistentStateComponent, Exporta public int MAX_LOOKUP_WIDTH2 = 500; public int MAX_LOOKUP_LIST_HEIGHT = 11; public boolean HIDE_NAVIGATION_ON_FOCUS_LOSS = true; + public boolean DND_WITH_PRESSED_ALT_ONLY = false; public boolean FILE_COLORS_IN_PROJECT_VIEW = false; public boolean DEFAULT_AUTOSCROLL_TO_SOURCE = false; @Transient diff --git a/platform/platform-api/src/com/intellij/ui/MouseDragHelper.java b/platform/platform-api/src/com/intellij/ui/MouseDragHelper.java index 1543c5ddedec..e46748c3a56f 100644 --- a/platform/platform-api/src/com/intellij/ui/MouseDragHelper.java +++ b/platform/platform-api/src/com/intellij/ui/MouseDragHelper.java @@ -15,6 +15,7 @@ */ package com.intellij.ui; +import com.intellij.ide.ui.UISettings; import com.intellij.openapi.Disposable; import com.intellij.openapi.ui.NullableComponent; import com.intellij.openapi.util.Disposer; @@ -27,10 +28,7 @@ import com.intellij.util.ui.update.UiNotifyConnector; import javax.swing.*; import java.awt.*; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; +import java.awt.event.*; public abstract class MouseDragHelper implements MouseListener, MouseMotionListener, KeyEventDispatcher, Weighted { @@ -58,6 +56,16 @@ public abstract class MouseDragHelper implements MouseListener, MouseMotionListe } + /** + * + * @param event + * @return false if Settings -> Appearance -> Drag-n-Drop with ALT pressed only is selected but event doesn't have ALT modifier + */ + public static boolean checkModifiers(InputEvent event) { + if (event == null || !UISettings.getInstance().DND_WITH_PRESSED_ALT_ONLY) return true; + return (event.getModifiers() & InputEvent.ALT_MASK) != 0; + } + public void start() { if (myGlassPane != null) return; diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java index 3ba5cd0b381d..655854ac933c 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java @@ -94,7 +94,7 @@ class DragHelper extends MouseDragHelper { } protected void processDrag(MouseEvent event, Point targetScreenPoint, Point startPointScreen) { - if (!myTabs.isTabDraggingEnabled() || !isDragSource(event)) return; + if (!myTabs.isTabDraggingEnabled() || !isDragSource(event) || !MouseDragHelper.checkModifiers(event)) return; SwingUtilities.convertPointFromScreen(startPointScreen, myTabs); diff --git a/platform/platform-impl/src/com/intellij/ide/dnd/DnDManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/dnd/DnDManagerImpl.java index fd486552272e..02e4d54f1135 100644 --- a/platform/platform-impl/src/com/intellij/ide/dnd/DnDManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/dnd/DnDManagerImpl.java @@ -21,6 +21,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.reference.SoftReference; +import com.intellij.ui.MouseDragHelper; import com.intellij.ui.awt.RelativeRectangle; import com.intellij.util.ui.GeometryUtil; import com.intellij.util.ui.UIUtil; @@ -538,7 +539,7 @@ public class DnDManagerImpl extends DnDManager implements Disposable { public void dragGestureRecognized(DragGestureEvent dge) { try { final DnDSource source = getSource(dge.getComponent()); - if (source == null) return; + if (source == null || !MouseDragHelper.checkModifiers(dge.getTriggerEvent())) return; DnDAction action = getDnDActionForPlatformAction(dge.getDragAction()); if (source.canStartDragging(action, dge.getDragOrigin())) { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java index 69944b4febe3..c60ddc44748d 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java @@ -154,6 +154,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab settings.OVERRIDE_NONIDEA_LAF_FONTS = myComponent.myOverrideLAFFonts.isSelected(); settings.MOVE_MOUSE_ON_DEFAULT_BUTTON = myComponent.myMoveMouseOnDefaultButtonCheckBox.isSelected(); settings.HIDE_NAVIGATION_ON_FOCUS_LOSS = myComponent.myHideNavigationPopupsCheckBox.isSelected(); + settings.DND_WITH_PRESSED_ALT_ONLY = myComponent.myAltDNDCheckBox.isSelected(); update |= settings.DISABLE_MNEMONICS != myComponent.myDisableMnemonics.isSelected(); settings.DISABLE_MNEMONICS = myComponent.myDisableMnemonics.isSelected(); @@ -270,6 +271,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab myComponent.myHideIconsInQuickNavigation.setSelected(settings.SHOW_ICONS_IN_QUICK_NAVIGATION); myComponent.myMoveMouseOnDefaultButtonCheckBox.setSelected(settings.MOVE_MOUSE_ON_DEFAULT_BUTTON); myComponent.myHideNavigationPopupsCheckBox.setSelected(settings.HIDE_NAVIGATION_ON_FOCUS_LOSS); + myComponent.myAltDNDCheckBox.setSelected(settings.DND_WITH_PRESSED_ALT_ONLY); myComponent.myLafComboBox.setSelectedItem(LafManager.getInstance().getCurrentLookAndFeel()); myComponent.myOverrideLAFFonts.setSelected(settings.OVERRIDE_NONIDEA_LAF_FONTS); myComponent.myDisableMnemonics.setSelected(settings.DISABLE_MNEMONICS); @@ -330,6 +332,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab isModified |= myComponent.myMoveMouseOnDefaultButtonCheckBox.isSelected() != settings.MOVE_MOUSE_ON_DEFAULT_BUTTON; isModified |= myComponent.myHideNavigationPopupsCheckBox.isSelected() != settings.HIDE_NAVIGATION_ON_FOCUS_LOSS; + isModified |= myComponent.myAltDNDCheckBox.isSelected() != settings.DND_WITH_PRESSED_ALT_ONLY; isModified |= !Comparing.equal(myComponent.myLafComboBox.getSelectedItem(), LafManager.getInstance().getCurrentLookAndFeel()); if (WindowManagerEx.getInstanceEx().isAlphaModeSupported()) { isModified |= myComponent.myEnableAlphaModeCheckBox.isSelected() != settings.ENABLE_ALPHA_MODE; @@ -385,6 +388,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab private JCheckBox myDisableMnemonics; private JCheckBox myDisableMnemonicInControlsCheckBox; private JCheckBox myHideNavigationPopupsCheckBox; + private JCheckBox myAltDNDCheckBox; private JCheckBox myAllowMergeButtons; private JBCheckBox myUseSmallLabelsOnTabs; private JBCheckBox myWidescreenLayoutCheckBox; diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form b/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form index 911ca64281e1..59197a00e70b 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form +++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form @@ -3,7 +3,7 @@ - + @@ -16,7 +16,7 @@ - + @@ -49,7 +49,7 @@ - + @@ -77,7 +77,7 @@ - + @@ -137,7 +137,7 @@ - + @@ -164,7 +164,9 @@
    - + + + @@ -174,7 +176,7 @@ - + @@ -198,6 +200,14 @@
    + + + + + + + +
    diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java index 8f9a4ac24536..7d534d5be545 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java @@ -174,7 +174,7 @@ public final class StripeButton extends AnchoredButton implements ActionListener } private void processDrag(final MouseEvent e) { - if (myDragCancelled) return; + if (myDragCancelled || !MouseDragHelper.checkModifiers(e)) return; if (!isDraggingNow()) { if (myPressedPoint == null) return; if (isWithinDeadZone(e)) return;