From 21de2af88fbc1b9a23aa81a9f40b52a92530343f Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 5 May 2014 14:35:07 +0400 Subject: [PATCH 01/35] fixed PY-12848 Adding local Python SDK does not work Regression produced in f3eda43 --- python/src/com/jetbrains/python/sdk/PythonSdkType.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java index c369f1c35e53..5238c5a1af99 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java @@ -288,6 +288,7 @@ public class PythonSdkType extends SdkType { public void consume(@Nullable Sdk sdk) { if (sdk != null) { sdk.putUserData(SDK_CREATOR_COMPONENT_KEY, new WeakReference(parentComponent)); + sdkCreatedCallback.consume(sdk); } } }); @@ -500,6 +501,11 @@ public class PythonSdkType extends SdkType { setupSdkPaths(sdk, project, ownerComponent); } + @Override + public boolean setupSdkPaths(Sdk sdk, SdkModel sdkModel) { + return true; // run setupSdkPaths only once (from PythonSdkDetailsStep). Skip this from showCustomCreateUI + } + public static void setupSdkPaths(Sdk sdk, @Nullable Project project, @Nullable Component ownerComponent) { final SdkModificator sdkModificator = sdk.getSdkModificator(); final boolean success = setupSdkPaths(project, ownerComponent, sdk, sdkModificator); From 4a61e1accfd2ed1f9fb7bd34780bf04987f163c7 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Mon, 5 May 2014 12:39:15 +0200 Subject: [PATCH 02/35] Show debug command line action renamed (PY-12835). --- .../src/messages/ExecutionBundle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources-en/src/messages/ExecutionBundle.properties b/platform/platform-resources-en/src/messages/ExecutionBundle.properties index 5776b6b664b2..407e5176c629 100644 --- a/platform/platform-resources-en/src/messages/ExecutionBundle.properties +++ b/platform/platform-resources-en/src/messages/ExecutionBundle.properties @@ -16,7 +16,7 @@ home.directory.not.specified.for.jdk.error.message=Home directory is not specifi run.configuration.pause.output.action.name=Pause Output main.class.is.not.specified.error.message=Main class is not specified close.tab.action.name=Close -run.configuration.show.command.line.action.name=Show command line +run.configuration.show.command.line.action.name=Show Python Prompt #--- create.run.configuration.action.name=Create Run Configuration From 2ec17056882c9995930e28a4eccaa791adc02d0d Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 5 May 2014 15:36:16 +0400 Subject: [PATCH 03/35] fixed PY-12698 Noticeable hang when selecting not yet added virtualenv as project interpreter --- .../psi/impl/PythonLanguageLevelPusher.java | 57 +++++++++++++------ 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java b/python/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java index 67af272bdf1d..6fa7ed5c68bf 100644 --- a/python/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java +++ b/python/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java @@ -20,6 +20,9 @@ import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.project.DumbModeTask; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.*; @@ -156,27 +159,45 @@ public class PythonLanguageLevelPusher implements FilePropertyPusher updatedSdks = new HashSet(); - final Module[] modules = ModuleManager.getInstance(project).getModules(); - boolean needReparseOpenFiles = false; - for (Module module : modules) { - Sdk newSdk = PythonSdkType.findPythonSdk(module); - if (myModuleSdks.containsKey(module)) { - Sdk oldSdk = myModuleSdks.get(module); - if ((newSdk != null || oldSdk != null) && newSdk != oldSdk) { - needReparseOpenFiles = true; + public void afterRootsChanged(@NotNull final Project project) { + final Runnable updateLanguageLevel = new Runnable() { + @Override + public void run() { + final Set updatedSdks = new HashSet(); + final Module[] modules = ModuleManager.getInstance(project).getModules(); + boolean needReparseOpenFiles = false; + for (Module module : modules) { + Sdk newSdk = PythonSdkType.findPythonSdk(module); + if (myModuleSdks.containsKey(module)) { + Sdk oldSdk = myModuleSdks.get(module); + if ((newSdk != null || oldSdk != null) && newSdk != oldSdk) { + needReparseOpenFiles = true; + } + } + myModuleSdks.put(module, newSdk); + if (newSdk != null && !updatedSdks.contains(newSdk)) { + updatedSdks.add(newSdk); + updateSdkLanguageLevel(project, newSdk); + } } + final boolean finalNeedReparseOpenFiles = needReparseOpenFiles; + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + if (finalNeedReparseOpenFiles) { + FileContentUtil.reparseFiles(project, Collections.emptyList(), true); + } + } + }); } - myModuleSdks.put(module, newSdk); - if (newSdk != null && !updatedSdks.contains(newSdk)) { - updatedSdks.add(newSdk); - updateSdkLanguageLevel(project, newSdk); + }; + final DumbModeTask task = new DumbModeTask() { + @Override + public void performInDumbMode(@NotNull ProgressIndicator indicator) { + ApplicationManager.getApplication().runReadAction(updateLanguageLevel); } - } - if (needReparseOpenFiles) { - FileContentUtil.reparseFiles(project, Collections.emptyList(), true); - } + }; + DumbService.getInstance(project).queueTask(task); } private void updateSdkLanguageLevel(Project project, Sdk sdk) { From 420f39260953a2c16b98d93113ed6e029c92a30f Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Tue, 6 May 2014 02:16:40 +0200 Subject: [PATCH 04/35] WinPty libs for Win XP. --- lib/libpty/win/xp/libwinpty.dll | Bin 0 -> 155648 bytes lib/libpty/win/xp/winpty-agent.exe | Bin 0 -> 129536 bytes lib/pty4j-0.3.jar | Bin 42013 -> 42314 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 lib/libpty/win/xp/libwinpty.dll create mode 100644 lib/libpty/win/xp/winpty-agent.exe diff --git a/lib/libpty/win/xp/libwinpty.dll b/lib/libpty/win/xp/libwinpty.dll new file mode 100644 index 0000000000000000000000000000000000000000..f7eef719e72a5f908db713bff47b006000874670 GIT binary patch literal 155648 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 literal 0 HcmV?d00001 diff --git a/lib/libpty/win/xp/winpty-agent.exe b/lib/libpty/win/xp/winpty-agent.exe new file mode 100644 index 0000000000000000000000000000000000000000..5abeecdd25e3b22d0bcd00e56a97e4b3772494ca GIT binary patch literal 129536 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%0ANOpNXR{0=R5c*Iq4i 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 literal 0 HcmV?d00001 diff --git a/lib/pty4j-0.3.jar b/lib/pty4j-0.3.jar index 8ffcc9c0d67b7d38e5f7e6d9c9f0e5deb577a219..d1345bc7026428a9641c59eb4123cd0daa8da8fd 100644 GIT binary patch delta 12815 zcmZX4Wk4Lu(l+kyEEe1e?h=B#y99T4-{7u`ySuwXa0~A4kOU1HAn3N>=)>u>qDmve0}FfjA@_bSXc zNV{@KE+E+`Z1$%}43M)jcIH(i!uLoFnU4<~o^2j&VE-X${)c3g80sIA_-_>G|NOr4 z{ClB-&;gjp|Bm_3W6(SBxBr8~0r_j-|9{H;0+xW&{vrm=gERbUG(bU6ga2;5g|vnI z-O7d82LEk@uJC#!G#J<_C>o9dxaN#$iuK|v#kpqFJgwY}Hbyj%I158}2N6+}^v*UH zzDhaIhHK4a+>DDNV>KdT3I8oy%pL(!fgpFkjAtA!rV@!y9DdIA;7c#=2OqagrKy#H z=GF2jP#S2b$N`9o8xQKt^1!kJEV||*# zJB&OD-Ykv~ibaaam2?ixq_~s~R$M%p84_a0IN8{f8YI2rdTmuvw+fk7r#WEtbhKrOdGy`Gxlbo%v>6+GMH9{D%Xt3KG1cT#kQUhucRbB zLf^A*2C?`>-(M7&E^Pb@Ixci!z8br?FUR=ggIzEp=3F8JzD8JeV^R&_M>a%t( z@uFfK5ueHQ9R(7$7BH2rI8G%#w8$uZ29vvNm(B(s8XJXIwUws4H6$T|wLt(Id!p1M zyU3iSWEWajrC<`5^hO_beW!?jyX=s-k3 zX5zuUMDlun$M0mM$DgLlq~bp3HqQTb9Fhvt#9*0-`Mcc)hg$~g0av4}`ye5Cc+}&L zIsM?~P&@@CF%Sr-yYENtv0v99wSRcN>obr@ZdCB9K1qYlKGuqCr^!sm!>GzC0sULK3_N}*IsyQ_H62n z;EfnDDd09uZdpvV3UOO$;HSW5_=f92uREL}cHQ?`+%e#cB({ISOzJiAYEyBBMYNc4 zJRkskJp?N?R?Hd>o=}y2P{?|W@d*o2jkIpacTw{*tD#cL(!ORZ!jIhYGGt%5syy0{ zEOK42UNU85UUMlF3mi|HwIwhdAA5)45*klPhVI=miq&T(7B%8wp&HGq+CmnD8B$Re zr!k-k;$nd~Q6XLwIgX*o7Uhj^G`O~iPJDY~+)vB$l8V$>&Z-UN;EWl$$}Ktq8`7OH z18wT0Kr8479za)^h=_}9Js{2t zNLr48pCs@GsJWv%BzFZTcV%XMK3?4uTRwe6@*AM>EAD~nnWlRt;z19lTs4gROcO@r zAWB$$Jj5{*nZO-Y&ke3{Z7d#TAg|l!YPcPenr}PabwhkJr58~U>0?hdB}hTSSGreP z0{96WDkTtD4-CS<((09XgoE~-muVp-5fE3B66Af?SsROzAh044>X6E-oqrb_rwgUG z%PqDk{6l5H^m@lpG+d^KI(lYgR^}~JQw?1SwQe&Z%w;p+Z&vO=)%}Czm zf7bVg7i6+Ot2rfVFvRcGyc%5_>URqX=Nb~_A6yPUlw=i5Tb}1~tWw3jv2EjRciG;_=RS9zG40oZSiSht zhHw=Z!DxUwu8|oc)}Kabzz=;{em*=ZbmDXL^MyI)hr|sm|ad-}qB9okZrUlU*p@m)vQ$r2gD|w)4&Bsh{`3Bt5EV zQFj~^m|sj}HF9kf717SEBQ4jiaTw*L9OrOsGt_bCFg9Fm&Bi2M-l}Ye-vwhL9I}gn zF5C4R>@SnsW&4(uT7Xou=?OH6-V;C!PThon;})YwDMR-XY&s#^&L9rs=3wSjZO1hTy|DgwyhqWWmOq1$4Ve8 z-|^@m!)nFt>hzwNWG)K6FAMWj zr+nSy%v14TfCVDUT5hWBfwQ^3Uxm*rchDrOIEE--pZxK_n>L5SIF0c~8bc0d$oz`)Cj4!ub7+Z}H_c4i^5p()BQiY6B{t5sw@P~a zBm@%!I2Z6Zn9tV5S!LB^dJf|4XJ*`$7^hfk@{EAnp_?5^okGF-=I9*@)S3j(J!x-T zM4H+%fewHsaWqd5mX(Z|vXXBSX%db>CvL=NIr{0W0jKJs2UsqTQwKOG^;H z+9km;opzo0piF&{Mg9?8Uu)P%^S*dJ(>m{%4gyeKf1HMCz9Ar3i7{R>9l26mr9{eT z#2$OXZ@fN9jzry&CB5{#%2HU2OY5oeKUM{mz#hn z^lw z@d*V+^o%@wxa7hH4hyM1VYZatr?9^yA6n@a>?${o9t&Yy!{6WT_0T}`QJhapxTD8;yW`hzT)Re>)j%sxV%?IPw z9KN+?uA!31*f|M+TDH1J;1l^N#kbw@%h-W8Fi}Bm@{y*6PP4opI^+!(Mh~di72W#2 z1-T{T>!APV0g+2u4xS7Y}+^i5sG+pw$6QB}NSxYhVRi zgF5l)`CFO$5KKR^X4nZsBfS7&knEjMt^@)Ox64d>@t4!&e4i-K?@dlHd& z8GW8L3_)uq7{pd1IOmKA1>0);A(6hv=Dx&k`=57**n zt528KHL+F5d0u5D6VCiV^P8ptypf+SWm5`ITB45DnFLlkkoq=QoHpMb=4~da{Q;lLW zLWvM3N;Asa0qJ%H&ng`47tOOmFItoY$L0FiaW8G`Z|D0#A;NtOmOFqF+aUHpS#%*B z%J<8hiDh%Y*<*OdId{_Qat4buIXLmlY_JA1Pr2LE&GvAA#PiLTt?}Q0>a%4(a8n=9 zpWl`rx@21Xy1`QnT-YPWk%N^4TiPjLAEn&tMll%_b+jU;b(Olpi`|S#h}fV3U?Le> zp86~KWf~Uk5;xzmCOz`>#Pa(whaw(DFHZ1>B6jJvITGToVn~H#6~?kyJq5YuyTR`< zq!(lMA1EtfH^9`{;Eivjj>tpu;3~L3B`Gy)mhcS%2B;l?4F!UG7ck&_Ep5%2XdbZ{ z*t_kJ9Q-xng8#U!SsHw2kbA{fFn_t5fiax{nNT5xDM3GpU@dC|^{AJ$SN+as!j zSUlgYQrTWvS}#S0pAFE)jviP+|YN3)Xu)Rc#kx6qH^;b^IyBWUam&Es2x4^Q0XwyzLEV1#I*PvhILMSx;c)lh} zGcWO0E6@LIg#C{sFbEZTr{a(emcR#}$fR9SS%@s7AqOYzMrG`w_&H!_9UH+^P^ z$G&KFCrC)tPa+)IM8;;jd-Jk+JFy)yD_61xS-PIGuw^&#?SXZa=6ftdr^t16pi3ohBkdTw!*Kez#Q|CNo2)^kS^2YFl{Z>^b=z#>)-?@#ffsJ@pS+rKe$Z)l#!M_aSau)yATrLZaV| za*9K!Gkv^8x9&S!@3U&2c$7_a5@WMg{n75VqkNY*F%kBu2}#6eg#>Tu^xY)Fa*@v_ z9TsGPIw_h047;Or=Aq8?=75Aa=3V5S)voV#0@-FwIP5@R00iP8;ap^EbOk~_kW4T) z9CcQPb>e_S9#vXXa>|wlhBa9bV}yqo;sT$!FcvJvSop21)vm}cY1E3nF@pckI)iO) zPGVw+MT=Z3Svh_NVsw|&faTkx>+!E1Y7j%AvG`whcNr_`3Z2h8gW;75mJzHn`3@eB zzS{ayB!=xU?!^$s3~TZeM&)^U0lhG~k|dP8MhHJ28$aQkL{ifOWUStYJD{E8YS6ST z%#_f3DNtZV)p5B)y(LNR4^=Tt{xL{R;%8VQQ9Rop-EGMfO|yLF@8E+f^cGb1MyT_m zQg-l1)}r&(A|u!42-i`ZLTH6ZU^oplgrrIw_zD6qTjO?9Qn2oHf&$UB|b%br92xy z7R!{a6z#GknVy@p4%#v-CITK*z>udkcVaV(2;^|xAJo>VAABfG;0o~3+g%iX?>wXb z((F}`(PE+IA*`WRh543uv5W+3?vu*I7$FzkC`MJL)ydQefmQds)dDL5oe=^`fqj|9 zHBV8Oes_-*<@+Qm4*goHd&^UPw{=V}Qup9Yf?SUKm~PCiw_J*dOK3m`!Ri(iMkz1d zS$HW0NnYA7Qc~y1*ThoiN!Nl>3Q}I$vyVip@6VyJuLYkY^6y0aa;5#yzQdO9qrQKh zHm#2x&)z#Xlp=}0R+1tCUH2#WiO#Ym_^HmuNFu{H8F0$aODr)yMl{HQLn=G|}(c1Ul$1Z!7TjVKoU# z*kaFaK3}h|4q5PAtnC+_8)Ws!5Pb1&OzKwf{^H6jZckLmj zHP0SuOzS!K)x56cq#HbNLH+UA{n(vIqentP26nC1fBn$@5>`+o;v0kK2IE;gCgRV^ z((ijE<|drGKWTrSB!t&O(az1Xh!8PpAMZZ2X?=>ycGYDD-VtVzKTn0QnxEcTy{1)O&y>9qVK_j^&+5z%1c;TespjqmnPuj6 zHYQ}3AmZhtv)wbexZ+(0(@z@A?c%RL04KJ|ZW}@x)Y#^mmRHWkGe1x8bR4fU2>Q*) zm_HskS;(6JE6k6@@5t<7E6gfCd(Q1gr9DFO82ex_@E^{(%&DZ1IQwkhA0u8TH0mCS zYK0r5b52cvc5U1?>P?9qBf;k|vO7P{%wvo+ChlQ46e@l@mii%2!*l`&5o0{$9(moN zM%6jyXMUXZDiYA|9;;wdQLk1cT=dWYyTo?9W{xy|6( z;XdamcoJq=x%SJCeWBAew4e|)<7(er;-&Xl@_GM$shXie8raLX>PQpRt`yDVBFId7gD}> zDd4-;X%GD@PjWp|c^IZr@a($Ga6WDeQ9QFE)Z|*0QBj zT)U-FEbvTey86wYW=`-H_wp_MoZm|X>rMU#>IbosFTI%iJ?~iNi#*c4PAYq(KM*bm zmtw?NU9nT<yKqH%Ft3$NIYxc}j~nPVD`1FEb+BG9`w?{06%8_j)Oq&1(opVpV~$E_trpB6=L z1NVoiy&zxWqdkn~2M(Jvf@?L=hqp93AH*#mA}*#W6N_r{P<-@sVIx;MzHzK~z98`h zm_qudb?+8#YY;tYjQMl=k8cO34DvHhcMjhP{T;8J7Ox%)gtwAHN+Qp{LJfzRhh9V2;f$ZE9`E1!-;YS^bk2R z@k~g28&pL0g-8U?EcKXD_fEEgl#qxr5kCazo#I;gF+I8JSW`r6 zm`#LfcP*#aqmdcH_l3cZ3e6d~vUkRZ3e65ys6%($>ZB4F&D`j}QiRQv=`?Bo=F z*EuKNfP1i)C4n4(3{^P!(YP@7>7wVp#OL|)Bl*5Y!+7iaZyHm^^!tF%W=~Jms2Vh( z1UoS5eT1`vZ7L=)EFM^G;cp}#_$2{cj**L)q?RZxzC4jEd=!{i_3s4VWaClhbz^n) z+%YG~zCiu`eblQiyt{@61M|WJ10w`E8exKZa$$f>#x{n|&RLqCK3EGxFWn{$Y%56q zHW*CkxKK#&hQaS6pj6=s85p22-xV}*uOK-do0(;$QHD1+>sNK1m|EwBu10FxMy}f7 zlu5i@U4866pWD3CTRYEK**Kw+5n2>tJ->_DI=}Pnxw0h&e$SHtt3)@KKpURK{I6>Ehy$RAe*l&jE#Hdleu;S?!|71mfMebY)Fz_nc(V2s|0ZXc10Zm)ik z43|!^ciO6=>|WNY6Jwu5Zx4dqs@^3+FZC#i*hAQSJvqZZk1;?$ORBgl^H6{~AABrq z^*%TXdRqSw+vV}@Qy_ZGc}foIh=Tl?T=@ua{IW126e}}fAGWA8RE?huRe(+?w(MRJ zieyMa)kk%3cz@QC=cP45VdN4-N1U=(qUxhPXio7%EBw)!POxSdk*>RRR|aDsMa@S{ z`lURgrtIDeYO9y);7Nz>c6_u2+eZQnLc6aXsf41pP3SsudduSx~Opt_M!K$mGKEQAAE61 z;+VBA2}L%qIn!gT?W~F#L=8MkS_q;EbuC#+G_yczmg8eOnoY$2pgeHnGAyGB>>q0V zC<#{@!l9eWiPZ|3Whg+24bT30T8@QwXzF8@tMYskGxs*2tkT#E^D=ujo4?JM-_(SE z?scKv!nQaRz~_>3E`17Mv{gHw+r_KS5;QuQ5x5EyCYEr=({qj}DXG@TVL~to1DQz{ z)2lJqRqUscl4Z^i387?A3^bkriR!av@+X+%P3G2ZcFdqN1s-T@b5qZXie0sa6l%vU z7v;)aNcYJ686kQsf-|)kldQQv%3%8_^xs`VLJQ4bkUyn*stbHhu9~^Pd{X^1#r{O7 zFpV_FSiFOKPbsHM*^Big-CuJ_0Nt~2!S|&9iG=+L9Y~h%#71-95Yn>^tif2>f;yB- zY2dJy_O`g^8{&9^d?_?le{{^>`QY?r%R{*z_$JW0U?_Hb3&Y>J7>aV%(pXdh)uY`! z(J0X9X*yy?fn_ebC~YH~g|NZqEvH%ilO~J6(8W3)Ijd4ZxHdXQ=~_=si*q2^S9Wxq z2r5PFQd{x6FGz3Y>Z-jaWUHgT$t>PQi-&j}HqY&Qvf+X~BaO zckXQiSOOB#Bz33pz(#ax9xEL}JO$dRniZD_Gkjw|ROyGTf`U#5D*pa>x%>`YhcC4Z zWZ4Be)r|%36xObbL78PflJ3zS_KVV^YpP+4k~WpPhWKuut&w{qYj5eY^^Q|)Z4Y<| zf>cZkXe#SuktydS*mQH-W#F-PI$+vS*U76C!>P;WHzd3wdZkWeWw( zQ)$j>V+)aG%T}>7VWvW3gH?@_!wSCd=a#z-Av48b@f9QDI(W+-OT}%WTLhwN0T0t$ z^GNOM#z~ycM<8C24+2_?zCbRm(j?J2t~Vc|Sko);-086ThJYMe0;lpbi`!7?M=(CkCMpJ6dsZUwDFSV3PQ{UgS4`Dn@hFxi>A>)iV$y(*v*b%+>?II#8F(imQq4zF8N__KzPn) zzqfF}a0Pk>fryBx^WgZAZYaK5U*M5Zdo(WMl3cDF<^>D27DlxB;}H(15$a4M5s9c~ zlrIx7o#LbEi(8(|i9}dBx17o&g=Jic@2{M*5C|R;mO5ni#&C8c8J0UO znHDWnBDR^#qg)+RKyh|XP3eCU$eMxXVL;Mbzy^Me$`&iHsOC_0rv9q)&FTz73l|w@ zxxgG$Lu1S$l;xi(m3d`hZe7~M6uLZg5#Zn=MJ&S=LKy?SBbC|Vt%fr0r0JJ$a@o|# zRvXZ>v&uq1uJz{pDe_F4asR>PUH3j9n+) zt{Otp) za7l--wY%(CehTb+oqDI9jdFVA(&7e~YBt3wZx3s>tBT%OQ3SoSYzu(b)ls~l@zoet znle79zMVTxIW*GE&Nvw<&`Yn}qe)a7W*G+FnY%1d@J130*Q&Ntwzr=d4!~Nsxjgq8 zgb98Sj2i}giBY3|g0!a83+M;{`=}qV@@ehdWZ>MW_q2H9(PFR5Z%lX0C0-*8T^Dmo zUxJ{n(+Dy9NQYi@i+@X@YRp>igJhjfE0qZM&IjsPb2K;BSXYV2JI$%!y|9BBHEl0o zaSuCvs!be{VA?QrVM*o2@!B^8?K|mJowwsfQ2Os2X3sM4(J&lD1&I;k&aMn0_`WZD zVBO4|=?&NM#L6XX%6iEW<4Qk}&5n=v|1=75C)ROV2ArlvT;I})%2mg-A)<|)?M@soeIH63Y5AwBm^9~lnw zA^h%0VyZh?(ttbndHi@nKmP|XerdeL3;c)p*4z2L0)a?-|4P7*dM+x18ByR;guLZ)e?^3t}5eUQ}>CKS!3HP_Y z4>I5g|3v+PG5-Sb_l~gv#kuWI$TRNE@;j8O|0wsTf>$Xp?N9u47F6@6l^2r!rzI5j z4(?aI@QV|apd~mMm`BrJmqs!07EGlDu^g$=<${@?(VzlZ*Z7CZ?A zNc&w%4dPD&K=grw;^VMDHfeu^ebNBn-$5y9^d$cb3T_ho$O8!mHt-r-0{$Ho46M+f z2(**-r*Il29RLvn1FD9>r~i+!zmt;X|5q*jx{)XUOWp}&m(Kdju(7homk0_BOcwUP$xlJH8NbN~Yw|*yUkxyX z0RyA>i(Cc=)bj`QpV~h#FucD&A^;G2Ce?2Z_%Z#8>;)8*a{6(-#_Y2rV4GYSlgF*Xm z$AbK`01)Nepo^?Gpsp;;Ut|@$>Tt!c{vdyKHr-!jD!i{i?%!H4WCI|CgtQ zIe!S_U;CCdUZ)@)C|!f(U(){^Q~bBT#I^r`k^Vy>oeKaT0h#8~{8H%G;l=AmS^HXi zPyClc%;un~T!vquzk68h@%Duf3r&m;Nm-p_de2onEaeN-Q@KwWviT?{l^C)a*; zFYGG`Kh9|`5$%1 zpVvs?UTt(j`)~j0hrg-@0BIHcd3p8)0Eqnf*FM_+Az_Uvp4fbyV)?Ht*WW5Df?fqk SK?VshAlO1Q7{}Cq4Ele?8$hoB delta 12427 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 From f09a0842696e0b55de33247e366ac25ecd895eda Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 5 May 2014 21:26:11 +0400 Subject: [PATCH 05/35] ensure cancel definitions search on popup closing --- .../actions/ShowImplementationsAction.java | 20 ++++++++++++++++++- .../navigation/BackgroundUpdaterTask.java | 10 ++++------ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java index 77995ac6fd2a..1f6f1347f16d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java @@ -33,9 +33,11 @@ import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.TextEditor; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Ref; import com.intellij.openapi.vfs.VirtualFile; @@ -285,10 +287,21 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { @Override public boolean process(JBPopup popup) { usageView.set(component.showInUsageView()); + myTaskRef = new WeakReference(null); popup.cancel(); return false; } }) + .setCancelCallback(new Computable() { + @Override + public Boolean compute() { + final BackgroundUpdaterTask task = myTaskRef.get(); + if (task != null) { + task.setCanceled(); + } + return Boolean.TRUE; + } + }) .createPopup(); updateInBackground(editor, element, component, title, (AbstractPopup)popup, usageView); @@ -315,7 +328,12 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { task.init(popup, component, usageView); myTaskRef = new WeakReference(task); - ProgressManager.getInstance().run(task); + ProgressManager.getInstance().runProcessWithProgressAsynchronously(task, new BackgroundableProcessIndicator(task) { + @Override + public boolean isCanceled() { + return super.isCanceled() || task.isCanceled(); + } + }); } protected boolean isIncludeAlwaysSelf() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java index 539a54ca9126..4fb9dc21fb06 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java @@ -73,12 +73,6 @@ public abstract class BackgroundUpdaterTask extends Task.Backgroundable { myComponent = component; myUsageView = usageView; - myPopup.addPopupListener(new JBPopupAdapter() { - @Override - public void onClosed(LightweightWindowEvent event) { - setCanceled(); - } - }); } public abstract String getCaption(int size); @@ -91,6 +85,10 @@ public abstract class BackgroundUpdaterTask extends Task.Backgroundable { return canceled; } + public boolean isCanceled() { + return myCanceled; + } + public boolean updateComponent(final PsiElement element, @Nullable final Comparator comparator) { final UsageView view = myUsageView.get(); if (view != null && !((UsageViewImpl)view).isDisposed()) { From 6e2082426e7c5a5866247d58ac3e0267f95a8249 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 6 May 2014 12:32:20 +0400 Subject: [PATCH 06/35] capitalization --- .../expected.xml | 0 .../src/Test.java | 0 .../com/intellij/codeInspection/DeprecationInspectionTest.java | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename java/java-tests/testData/inspection/deprecation/{DeprecatedDefaultConstructorFromTypeParameter => deprecatedDefaultConstructorTypeParameter}/expected.xml (100%) rename java/java-tests/testData/inspection/deprecation/{DeprecatedDefaultConstructorFromTypeParameter => deprecatedDefaultConstructorTypeParameter}/src/Test.java (100%) diff --git a/java/java-tests/testData/inspection/deprecation/DeprecatedDefaultConstructorFromTypeParameter/expected.xml b/java/java-tests/testData/inspection/deprecation/deprecatedDefaultConstructorTypeParameter/expected.xml similarity index 100% rename from java/java-tests/testData/inspection/deprecation/DeprecatedDefaultConstructorFromTypeParameter/expected.xml rename to java/java-tests/testData/inspection/deprecation/deprecatedDefaultConstructorTypeParameter/expected.xml diff --git a/java/java-tests/testData/inspection/deprecation/DeprecatedDefaultConstructorFromTypeParameter/src/Test.java b/java/java-tests/testData/inspection/deprecation/deprecatedDefaultConstructorTypeParameter/src/Test.java similarity index 100% rename from java/java-tests/testData/inspection/deprecation/DeprecatedDefaultConstructorFromTypeParameter/src/Test.java rename to java/java-tests/testData/inspection/deprecation/deprecatedDefaultConstructorTypeParameter/src/Test.java diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DeprecationInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DeprecationInspectionTest.java index 2cd737e5ed78..15b82e9382b0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DeprecationInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DeprecationInspectionTest.java @@ -49,7 +49,7 @@ public class DeprecationInspectionTest extends InspectionTestCase { doTest(); } - public void testDeprecatedDefaultConstructorFromTypeParameter() throws Exception { + public void testDeprecatedDefaultConstructorTypeParameter() throws Exception { doTest(); } From 753dd855ce67692a4063e1b68d5ea8b2539e551b Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 6 May 2014 12:06:59 +0400 Subject: [PATCH 07/35] do not remove contents added by other subsystems, which were run independently from any compile session (e.g. ant build) --- .../com/intellij/compiler/progress/CompilerTask.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java b/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java index c4497e09827c..710baf36f29b 100644 --- a/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java +++ b/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java @@ -198,14 +198,15 @@ public class CompilerTask extends Task.Backgroundable { ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { - if (myProject.isDisposed()) { + final Project project = myProject; + if (project == null || project.isDisposed()) { return; } synchronized (myMessageViewLock) { // clear messages from the previous compilation if (myErrorTreeView == null) { // if message view != null, the contents has already been cleared - removeAllContents(myProject, null); + removeAllContents(project, null); } } } @@ -454,7 +455,12 @@ public class CompilerTask extends Task.Backgroundable { if (content == notRemove) { continue; } - if (CONTENT_ID_KEY.get(content) == myContentId || SESSION_ID_KEY.get(content) != mySessionId) { // the content was added by previous compilation + boolean toRemove = CONTENT_ID_KEY.get(content) == myContentId; + if (!toRemove) { + final Object contentSessionId = SESSION_ID_KEY.get(content); + toRemove = contentSessionId != null && contentSessionId != mySessionId; // the content was added by previous compilation + } + if (toRemove) { messageView.getContentManager().removeContent(content, true); } } From 765dacbcf09c05a2d5eb71a9e6b8d3c8354e3cff Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 6 May 2014 13:33:41 +0400 Subject: [PATCH 08/35] cosmetics --- .../lang/ant/config/execution/AntBuildMessageView.java | 6 +++--- .../intellij/lang/ant/config/execution/OutputParser.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/AntBuildMessageView.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/AntBuildMessageView.java index d47ac8d0da19..cb6008231f76 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/execution/AntBuildMessageView.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/execution/AntBuildMessageView.java @@ -90,8 +90,8 @@ public final class AntBuildMessageView extends JPanel implements DataProvider, O private AntBuildFileBase myBuildFile; private final String[] myTargets; private int myPriorityThreshold = PRIORITY_BRIEF; - private int myErrorCount; - private int myWarningCount; + private volatile int myErrorCount; + private volatile int myWarningCount; private volatile boolean myIsOutputPaused = false; @NotNull @@ -109,7 +109,7 @@ public final class AntBuildMessageView extends JPanel implements DataProvider, O private final Runnable myFlushLogRunnable = new Runnable() { @Override public void run() { - if (myTreeView != null && myCommandsProcessedCount < myLog.size()) { + if (myCommandsProcessedCount < myLog.size()) { if (!myIsOutputPaused) { new OutputFlusher().doFlush(); myTreeView.scrollToLastMessage(); diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java index f96df5472736..3508cdb35e85 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java @@ -47,7 +47,7 @@ public class OutputParser{ private final WeakReference myProgress; private final String myBuildName; private final OSProcessHandler myProcessHandler; - private boolean isStopped; + private volatile boolean isStopped; private List myJavacMessages; private boolean myFirstLineProcessed; private boolean myStartedSuccessfully; From 85f6ea19ee0e403fd461cc1bf0029eee95c7138c Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Tue, 6 May 2014 13:43:07 +0400 Subject: [PATCH 09/35] IDEA-121171 Reformat only VCS changed text - does not work when editor is not opened --- .../AbstractLayoutCodeProcessorTest.java | 41 +-- .../actions/ReformatCodeActionTest.java | 29 +- .../actions/AbstractLayoutCodeProcessor.java | 118 +++--- .../codeInsight/actions/FileTreeIterator.java | 111 ++++++ .../actions/FormatChangedTextUtil.java | 109 +++++- .../actions/ReformatCodeProcessor.java | 25 +- .../codeInsight/actions/ChangedLines.java | 41 +++ .../actions/MockCodeStyleManager.java | 172 +++++++++ .../MockPlainTextFormattingModelBuilder.java | 46 +++ .../ReformatOnlyVcsChangedTextTest.java | 339 ++++++++++++++++++ .../actions/TestFileStructure.java | 128 +++++++ 11 files changed, 1022 insertions(+), 137 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/actions/FileTreeIterator.java create mode 100644 platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ChangedLines.java create mode 100644 platform/platform-tests/testSrc/com/intellij/codeInsight/actions/MockCodeStyleManager.java create mode 100644 platform/platform-tests/testSrc/com/intellij/codeInsight/actions/MockPlainTextFormattingModelBuilder.java create mode 100644 platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatOnlyVcsChangedTextTest.java create mode 100644 platform/platform-tests/testSrc/com/intellij/codeInsight/actions/TestFileStructure.java diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java index f6327b780569..efc85b5805b5 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java @@ -97,8 +97,8 @@ public abstract class AbstractLayoutCodeProcessorTest extends PsiTestCase { @Override public void tearDown() throws Exception { - super.tearDown(); delete(myWorkingDirectory.getVirtualFile()); + super.tearDown(); } @NotNull @@ -277,45 +277,6 @@ public abstract class AbstractLayoutCodeProcessorTest extends PsiTestCase { PsiTestUtil.addSourceRoot(module, src.getVirtualFile()); return module; } - - class TestFileStructure { - private int myLevel; - @NotNull private PsiDirectory myRoot; - @NotNull private PsiDirectory myCurrentLevelDirectory; - private List> myFilesForLevel = new ArrayList>(); - - TestFileStructure(@NotNull PsiDirectory root) { - myRoot = root; - myCurrentLevelDirectory = root; - myFilesForLevel.add(new ArrayList()); - myLevel = 0; - } - - TestFileStructure addTestFilesToCurrentDirectory(String[] names) throws IOException { - getFilesAtLevel(myLevel).addAll(createTestFiles(myCurrentLevelDirectory, names)); - return this; - } - - TestFileStructure createDirectoryAndMakeItCurrent(String name) { - myLevel++; - myFilesForLevel.add(new ArrayList()); - myCurrentLevelDirectory = createDirectory(myCurrentLevelDirectory.getVirtualFile(), name); - return this; - } - - List getFilesAtLevel(int level) { - assert (myLevel >= level); - return myFilesForLevel.get(level); - } - - List getAllFiles() { - List all = new ArrayList(); - for (List files: myFilesForLevel) { - all.addAll(files); - } - return all; - } - } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java index fa0a4c1f2d80..f2cd858132db 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java @@ -32,14 +32,6 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { private static String[] classNames = {"Vasya", "Main", "Oiie", "Ololo"}; - private TestFileStructure getThreeLevelDirectoryStructure() throws IOException { - TestFileStructure fileStructure = new TestFileStructure(getTempRootDirectory()); - fileStructure.createDirectoryAndMakeItCurrent("dir").addTestFilesToCurrentDirectory(classNames) - .createDirectoryAndMakeItCurrent("innerDir").addTestFilesToCurrentDirectory(classNames) - .createDirectoryAndMakeItCurrent("innerInnerDir").addTestFilesToCurrentDirectory(classNames); - return fileStructure; - } - public void testReformatAndOptimizeMultipleFiles() throws IOException { List files = createTestFiles(getTempRootDirectory(), classNames); injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true)); @@ -118,4 +110,25 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { checkFormationAndImportsOptimizationFor(files); } + private TestFileStructure getThreeLevelDirectoryStructure() throws IOException { + TestFileStructure fileStructure = new TestFileStructure(getModule(), getTempRootDirectory()); + + fileStructure.createDirectoryAndMakeItCurrent("dir"); + addFilesToCurrentDirectory(fileStructure); + + fileStructure.createDirectoryAndMakeItCurrent("innerDir"); + addFilesToCurrentDirectory(fileStructure); + + fileStructure.createDirectoryAndMakeItCurrent("innerInnerDir"); + addFilesToCurrentDirectory(fileStructure); + + return fileStructure; + } + + private void addFilesToCurrentDirectory(TestFileStructure fileStructure) throws IOException { + for (int i = 0; i < 5; i++) { + String className = "Test" + i; + fileStructure.addTestFile("Test" + i + ".java", getUntouchedJavaSourceForTotalProcessing(className)); + } + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java index b024ef473d03..b524697e42c1 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java @@ -25,7 +25,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -34,18 +33,23 @@ import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectCoreUtil; import com.intellij.openapi.roots.GeneratedSourcesFilter; -import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.ex.MessagesEx; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.PsiBundle; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import com.intellij.util.SequentialModalProgressTask; import com.intellij.util.SequentialTask; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; @@ -205,7 +209,14 @@ public abstract class AbstractLayoutCodeProcessor { return; } - FileTreeIterator iterator = buildFileTreeIterator(); + FileTreeIterator iterator; + if (myFiles != null) { + iterator = new FileTreeIterator(myFiles); + } + else { + iterator = myProcessChangedTextOnly ? buildChangedFilesIterator() + : buildFileTreeIterator(); + } runProcessFiles(iterator); } @@ -226,6 +237,35 @@ public abstract class AbstractLayoutCodeProcessor { return new FileTreeIterator(Collections.emptyList()); } + @NotNull + private FileTreeIterator buildChangedFilesIterator() { + List files = getChangedFilesFromContext(); + return new FileTreeIterator(files); + } + + @NotNull + private List getChangedFilesFromContext() { + List dirs = getAllSearchableDirsFromContext(); + return FormatChangedTextUtil.getChangedFilesFromDirs(myProject, dirs); + } + + private List getAllSearchableDirsFromContext() { + List dirs = ContainerUtil.newArrayList(); + if (myDirectory != null) { + dirs.add(myDirectory); + } + else if (myModule != null) { + List allModuleDirs = FileTreeIterator.collectModuleDirectories(myModule); + dirs.addAll(allModuleDirs); + } + else if (myProject != null) { + List allProjectDirs = FileTreeIterator.collectProjectDirectories(myProject); + dirs.addAll(allProjectDirs); + } + return dirs; + } + + private void runProcessFile(@NotNull final PsiFile file) { Document document = PsiDocumentManager.getInstance(myProject).getDocument(file); @@ -493,72 +533,4 @@ public abstract class AbstractLayoutCodeProcessor { myCompositeTask = compositeTask; } } - - private static class FileTreeIterator { - private Queue myCurrentFiles = new LinkedList(); - private Queue myCurrentDirectories = new LinkedList(); - - public FileTreeIterator(@NotNull List files) { - myCurrentFiles.addAll(files); - } - - public FileTreeIterator(@NotNull Module module) { - addDirectoriesFrom(module); - expandDirectoriesUntilFilesNotEmpty(); - } - - public FileTreeIterator(@NotNull Project project) { - Module[] modules = ModuleManager.getInstance(project).getModules(); - for (Module module : modules) { - addDirectoriesFrom(module); - } - expandDirectoriesUntilFilesNotEmpty(); - } - - public FileTreeIterator(@NotNull PsiDirectory directory) { - myCurrentDirectories.add(directory); - expandDirectoriesUntilFilesNotEmpty(); - } - - public FileTreeIterator(@NotNull FileTreeIterator fileTreeIterator) { - myCurrentFiles = new LinkedList(fileTreeIterator.myCurrentFiles); - myCurrentDirectories = new LinkedList(fileTreeIterator.myCurrentDirectories); - } - - @NotNull - public PsiFile next() { - if (myCurrentFiles.isEmpty()) { - throw new NoSuchElementException(); - } - PsiFile current = myCurrentFiles.poll(); - expandDirectoriesUntilFilesNotEmpty(); - return current; - } - - public boolean hasNext() { - return !myCurrentFiles.isEmpty(); - } - - private void expandDirectoriesUntilFilesNotEmpty() { - while (myCurrentFiles.isEmpty() && !myCurrentDirectories.isEmpty()) { - PsiDirectory dir = myCurrentDirectories.poll(); - expandDirectory(dir); - } - } - - private void expandDirectory(@NotNull PsiDirectory dir) { - Collections.addAll(myCurrentFiles, dir.getFiles()); - Collections.addAll(myCurrentDirectories, dir.getSubdirectories()); - } - - private void addDirectoriesFrom(Module module) { - VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots(); - for (VirtualFile root : contentRoots) { - PsiDirectory dir = PsiManager.getInstance(module.getProject()).findDirectory(root); - if (dir != null) { - myCurrentDirectories.add(dir); - } - } - } - } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileTreeIterator.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileTreeIterator.java new file mode 100644 index 000000000000..af629e9c02f1 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileTreeIterator.java @@ -0,0 +1,111 @@ +/* + * 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.actions; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +public class FileTreeIterator { + private Queue myCurrentFiles = new LinkedList(); + private Queue myCurrentDirectories = new LinkedList(); + + public FileTreeIterator(@NotNull List files) { + myCurrentFiles.addAll(files); + } + + public FileTreeIterator(@NotNull Module module) { + myCurrentDirectories.addAll(collectModuleDirectories(module)); + expandDirectoriesUntilFilesNotEmpty(); + } + + public FileTreeIterator(@NotNull Project project) { + myCurrentDirectories.addAll(collectProjectDirectories(project)); + expandDirectoriesUntilFilesNotEmpty(); + } + + @NotNull + public static List collectProjectDirectories(@NotNull Project project) { + List directories = ContainerUtil.newArrayList(); + + Module[] modules = ModuleManager.getInstance(project).getModules(); + for (Module module : modules) { + directories.addAll(collectModuleDirectories(module)); + } + + return directories; + } + + public FileTreeIterator(@NotNull PsiDirectory directory) { + myCurrentDirectories.add(directory); + expandDirectoriesUntilFilesNotEmpty(); + } + + public FileTreeIterator(@NotNull FileTreeIterator fileTreeIterator) { + myCurrentFiles = new LinkedList(fileTreeIterator.myCurrentFiles); + myCurrentDirectories = new LinkedList(fileTreeIterator.myCurrentDirectories); + } + + @NotNull + public PsiFile next() { + if (myCurrentFiles.isEmpty()) { + throw new NoSuchElementException(); + } + PsiFile current = myCurrentFiles.poll(); + expandDirectoriesUntilFilesNotEmpty(); + return current; + } + + public boolean hasNext() { + return !myCurrentFiles.isEmpty(); + } + + private void expandDirectoriesUntilFilesNotEmpty() { + while (myCurrentFiles.isEmpty() && !myCurrentDirectories.isEmpty()) { + PsiDirectory dir = myCurrentDirectories.poll(); + expandDirectory(dir); + } + } + + private void expandDirectory(@NotNull PsiDirectory dir) { + Collections.addAll(myCurrentFiles, dir.getFiles()); + Collections.addAll(myCurrentDirectories, dir.getSubdirectories()); + } + + @NotNull + public static List collectModuleDirectories(Module module) { + List dirs = ContainerUtil.newArrayList(); + + VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots(); + for (VirtualFile root : contentRoots) { + PsiDirectory dir = PsiManager.getInstance(module.getProject()).findDirectory(root); + if (dir != null) { + dirs.add(dir); + } + } + + return dirs; + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java index e51deaed6de7..a296689352ec 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java @@ -17,7 +17,9 @@ package com.intellij.codeInsight.actions; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.application.Result; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.module.ModifiableModuleModel; import com.intellij.openapi.module.Module; @@ -25,27 +27,30 @@ import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vcs.changes.ContentRevision; import com.intellij.openapi.vcs.ex.LineStatusTracker; import com.intellij.openapi.vcs.ex.Range; +import com.intellij.openapi.vcs.ex.RangesBuilder; import com.intellij.openapi.vcs.impl.LineStatusTrackerManager; import com.intellij.openapi.vcs.impl.LineStatusTrackerManagerI; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.ContainerUtilRt; +import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.*; -/** - * Contains utility methods for 'format only changed text' (in terms of VCS changes). - * - * @author Denis Zhdanov - * @since 12/19/11 10:55 AM - */ public class FormatChangedTextUtil { + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.FormatChangedTextUtil"); private FormatChangedTextUtil() { } @@ -209,4 +214,96 @@ public class FormatChangedTextUtil { } return result; } + + @NotNull + public static List getChangedFilesFromDirs(@NotNull Project project, @NotNull List dirs) { + ChangeListManager changeListManager = ChangeListManager.getInstance(project); + Collection changes = ContainerUtil.newArrayList(); + + for (PsiDirectory dir : dirs) { + changes.addAll(changeListManager.getChangesIn(dir.getVirtualFile())); + } + + return getChangedFiles(project, changes); + } + + @NotNull + public static List getChangedFiles(@NotNull Project project, @NotNull Collection changes) { + List files = ContainerUtil.newArrayList(); + for (Change change : changes) { + VirtualFile vFile = change.getVirtualFile(); + if (vFile != null) { + PsiFile file = PsiManager.getInstance(project).findFile(vFile); + if (file != null) files.add(file); + } + } + return files; + } + + @NotNull + public static List getChangedTextRanges(@NotNull Project project, @NotNull PsiFile file) { + Change change = ChangeListManager.getInstance(project).getChange(file.getVirtualFile()); + if (change == null) { + return ContainerUtilRt.emptyList(); + } + if (change.getType() == Change.Type.NEW) { + return ContainerUtil.newArrayList(file.getTextRange()); + } + + String contentFromVcs = getRevisionedContentFrom(change); + return contentFromVcs != null ? calculateChangedTextRanges(project, file, contentFromVcs) + : ContainerUtil.emptyList(); + } + + @Nullable + private static String getRevisionedContentFrom(@NotNull Change change) { + ContentRevision revision = change.getBeforeRevision(); + if (revision == null) { + return null; + } + + try { + return revision.getContent(); + } + catch (VcsException e) { + LOG.error("Can't get content for: " + change.getVirtualFile(), e); + return null; + } + } + + @NotNull + private static List calculateChangedTextRanges(@NotNull Project project, @NotNull PsiFile file, @NotNull String contentFromVcs) { + Document documentFromVcs = EditorFactory.getInstance().createDocument(contentFromVcs); + Document document = PsiDocumentManager.getInstance(project).getDocument(file); + + if (document == null) { + return ContainerUtil.emptyList(); + } + + try { + List changedRanges = new RangesBuilder(document, documentFromVcs).getRanges(); + return getChangedTextRanges(document, changedRanges); + } + catch (FilesTooBigForDiffException e) { + LOG.error("Error while calculating changed ranges for: " + file.getVirtualFile(), e); + return ContainerUtil.emptyList(); + } + } + + @NotNull + private static List getChangedTextRanges(@NotNull Document document, @NotNull List changedRanges) { + List ranges = ContainerUtil.newArrayList(); + for (Range range : changedRanges) { + if (range.getType() != Range.DELETED) { + int changeStartLine = range.getOffset1(); + int changeEndLine = range.getOffset2(); + + int lineStartOffset = document.getLineStartOffset(changeStartLine); + int lineEndOffset = document.getLineEndOffset(changeEndLine - 1); + + ranges.add(new TextRange(lineStartOffset, lineEndOffset)); + } + } + return ranges; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java index 9bd23c30f5dc..ff032c22747b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java @@ -26,6 +26,7 @@ import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -62,14 +63,14 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { } } - public ReformatCodeProcessor(Project project, PsiFile[] files, Runnable postRunnable, boolean processChangedTextOnly) { + public ReformatCodeProcessor(Project project, PsiFile[] files, @Nullable Runnable postRunnable, boolean processChangedTextOnly) { this(project, files, COMMAND_NAME, postRunnable, processChangedTextOnly); } public ReformatCodeProcessor(Project project, PsiFile[] files, String commandName, - Runnable postRunnable, + @Nullable Runnable postRunnable, boolean processChangedTextOnly) { super(project, files, PROGRESS_TEXT, commandName, postRunnable, processChangedTextOnly); @@ -85,13 +86,8 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { public Boolean call() throws Exception { FormattingProgressTask.FORMATTING_CANCELLED_FLAG.set(false); try { - if (myRanges.isEmpty() && processChangedTextOnly) { - myRanges.addAll(FormatChangedTextUtil.getChanges(file)); - } - if (myRanges.isEmpty()) { - myRanges.add(file.getTextRange()); - } - CodeStyleManager.getInstance(myProject).reformatText(file, myRanges); + Collection ranges = getRangesToFormat(processChangedTextOnly, file); + CodeStyleManager.getInstance(myProject).reformatText(file, ranges); return !FormattingProgressTask.FORMATTING_CANCELLED_FLAG.get(); } catch (IncorrectOperationException e) { @@ -104,4 +100,13 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { } }); } -} + + @NotNull + private Collection getRangesToFormat(boolean processChangedTextOnly, PsiFile file) { + if (processChangedTextOnly) { + return FormatChangedTextUtil.getChangedTextRanges(myProject, file); + } + + return !myRanges.isEmpty() ? myRanges : ContainerUtil.newArrayList(file.getTextRange()); + } +} \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ChangedLines.java b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ChangedLines.java new file mode 100644 index 000000000000..35c02e5bb904 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ChangedLines.java @@ -0,0 +1,41 @@ +/* + * 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.actions; + +public class ChangedLines { + public final int from; + public final int to; + + ChangedLines(int from, int to) { + this.from = from; + this.to = to; + } + + @Override + public String toString() { + return "(" + from + ", " + to + ")"; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ChangedLines) { + ChangedLines line = (ChangedLines)obj; + return from == line.from && to == line.to; + } + + return false; + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/MockCodeStyleManager.java b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/MockCodeStyleManager.java new file mode 100644 index 000000000000..1b3771fe3c10 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/MockCodeStyleManager.java @@ -0,0 +1,172 @@ +/* + * 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.actions; + +import com.intellij.lang.ASTNode; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.codeStyle.Indent; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ThrowableRunnable; +import com.intellij.util.containers.HashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Map; + +public class MockCodeStyleManager extends CodeStyleManager { + private Map myFormattedLinesForFile = new HashMap(); + + @NotNull + public ChangedLines[] getFormattedLinesFor(@NotNull PsiFile file) { + ChangedLines[] changedLines = myFormattedLinesForFile.get(file); + return changedLines != null ? changedLines : new ChangedLines[0]; + } + + @Override + public void reformatText(@NotNull PsiFile file, @NotNull Collection ranges) throws IncorrectOperationException { + Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); + assert(document != null); + + ChangedLines[] formattedLines = new ChangedLines[ranges.size()]; + int i = 0; + for (TextRange range : ranges) { + int lineStart = document.getLineNumber(range.getStartOffset()); + int lineEnd = document.getLineNumber(range.getEndOffset()); + formattedLines[i++] = new ChangedLines(lineStart, lineEnd); + } + + myFormattedLinesForFile.put(file, formattedLines); + } + + @NotNull + @Override + public Project getProject() { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.getProject(...)"); + } + + @NotNull + @Override + public PsiElement reformat(@NotNull PsiElement element) throws IncorrectOperationException { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.reformat(...)"); + } + + @NotNull + @Override + public PsiElement reformat(@NotNull PsiElement element, boolean canChangeWhiteSpacesOnly) throws IncorrectOperationException { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.reformat(...)"); + } + + @Override + public PsiElement reformatRange(@NotNull PsiElement element, int startOffset, int endOffset) throws IncorrectOperationException { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.reformatRange(...)"); + } + + @Override + public PsiElement reformatRange(@NotNull PsiElement element, int startOffset, int endOffset, boolean canChangeWhiteSpacesOnly) + throws IncorrectOperationException { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.reformatRange(...)"); + } + + @Override + public void reformatText(@NotNull PsiFile file, int startOffset, int endOffset) throws IncorrectOperationException { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.reformatText(...)"); + } + + @Override + public void adjustLineIndent(@NotNull PsiFile file, TextRange rangeToAdjust) throws IncorrectOperationException { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.adjustLineIndent(...)"); + } + + @Override + public int adjustLineIndent(@NotNull PsiFile file, int offset) throws IncorrectOperationException { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.adjustLineIndent(...)"); + } + + @Override + public int adjustLineIndent(@NotNull Document document, int offset) { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.adjustLineIndent(...)"); + } + + @Override + public boolean isLineToBeIndented(@NotNull PsiFile file, int offset) { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.isLineToBeIndented(...)"); + } + + @Nullable + @Override + public String getLineIndent(@NotNull PsiFile file, int offset) { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.getLineIndent(...)"); + } + + @Nullable + @Override + public String getLineIndent(@NotNull Document document, int offset) { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.getLineIndent(...)"); + } + + @Override + public Indent getIndent(String text, FileType fileType) { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.getIndent(...)"); + } + + @Override + public String fillIndent(Indent indent, FileType fileType) { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.fillIndent(...)"); + } + + @Override + public Indent zeroIndent() { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.zeroIndent(...)"); + } + + @Override + public void reformatNewlyAddedElement(@NotNull ASTNode block, @NotNull ASTNode addedElement) + throws IncorrectOperationException { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.reformatNewlyAddedElement(...)"); + } + + @Override + public boolean isSequentialProcessingAllowed() { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.isSequentialProcessingAllowed(...)"); + } + + @Override + public void performActionWithFormatterDisabled(Runnable r) { + throw new UnsupportedOperationException( + "com.intellij.codeInsight.actions.MockCodeStyleManager.performActionWithFormatterDisabled(...)"); + } + + @Override + public void performActionWithFormatterDisabled(ThrowableRunnable r) throws T { + throw new UnsupportedOperationException( + "com.intellij.codeInsight.actions.MockCodeStyleManager.performActionWithFormatterDisabled(...)"); + } + + @Override + public T performActionWithFormatterDisabled(Computable r) { + throw new UnsupportedOperationException( + "com.intellij.codeInsight.actions.MockCodeStyleManager.performActionWithFormatterDisabled(...)"); + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/MockPlainTextFormattingModelBuilder.java b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/MockPlainTextFormattingModelBuilder.java new file mode 100644 index 000000000000..fb98cb52f52e --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/MockPlainTextFormattingModelBuilder.java @@ -0,0 +1,46 @@ +/* + * 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.actions; + +import com.intellij.formatting.CustomFormattingModelBuilder; +import com.intellij.formatting.FormattingModel; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class MockPlainTextFormattingModelBuilder implements CustomFormattingModelBuilder { + + @Override + public boolean isEngagedToFormat(PsiElement context) { + return true; + } + + @NotNull + @Override + public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockPlainTextFormattingModelBuilder.createModel(...)"); + } + + @Nullable + @Override + public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) { + throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockPlainTextFormattingModelBuilder.getRangeAffectingIndent(...)"); + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatOnlyVcsChangedTextTest.java b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatOnlyVcsChangedTextTest.java new file mode 100644 index 000000000000..476bd66ddde4 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatOnlyVcsChangedTextTest.java @@ -0,0 +1,339 @@ +/* + * 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.actions; + +import com.intellij.lang.LanguageFormatting; +import com.intellij.openapi.components.impl.ComponentManagerImpl; +import com.intellij.openapi.fileTypes.PlainTextLanguage; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.FilePathImpl; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vcs.changes.SimpleContentRevision; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.testFramework.LightPlatformTestCase; +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.vcs.MockChangeListManager; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.picocontainer.MutablePicoContainer; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +public class ReformatOnlyVcsChangedTextTest extends LightPlatformTestCase { + private static final String TEMP_DIR_NAME = "dir"; + private PsiDirectory myWorkingDirectory; + + private MockChangeListManager myMockChangeListManager; + private MockCodeStyleManager myMockCodeStyleManager; + private MockPlainTextFormattingModelBuilder myMockPlainTextFormattingModelBuilder; + + private ChangeListManager myRealChangeListManager; + private CodeStyleManager myRealCodeStyleManger; + + private final static String COMMITTED = + "class Test {\n" + + " int a = 22;\n" + + " public String getName() { return \"Test\"; }\n" + + "}"; + + private final static String MODIFIED = + "class Test {\n" + + " int a = 22;\n" + + " long l;\n" + + " double d;\n" + + " int i;\n" + + " public String getName() { return \"Test\"; }\n" + + " String test1;\n" + + " String test2;\n" + + "}"; + + private final static ChangedLines[] CHANGED_LINES = new ChangedLines[] { line(2, 4), line(6, 7) }; + private final static ChangedLines[] NO_CHANGED_LINES = new ChangedLines[0]; + + @Override + public void setUp() throws Exception { + PlatformTestCase.initPlatformLangPrefix(); + super.setUp(); + myWorkingDirectory = TestFileStructure.createDirectory(getProject(), getSourceRoot(), TEMP_DIR_NAME); + + myRealChangeListManager = ChangeListManager.getInstance(getProject()); + myMockChangeListManager = new MockChangeListManager(); + registerChangeListManager(myMockChangeListManager); + + myRealCodeStyleManger = CodeStyleManager.getInstance(getProject()); + myMockCodeStyleManager = new MockCodeStyleManager(); + registerCodeStyleManager(myMockCodeStyleManager); + + myMockPlainTextFormattingModelBuilder = new MockPlainTextFormattingModelBuilder(); + LanguageFormatting.INSTANCE.addExplicitExtension(PlainTextLanguage.INSTANCE, myMockPlainTextFormattingModelBuilder); + } + + @Override + public void tearDown() throws Exception { + registerChangeListManager(myRealChangeListManager); + registerCodeStyleManager(myRealCodeStyleManger); + LanguageFormatting.INSTANCE.removeExplicitExtension(PlainTextLanguage.INSTANCE, myMockPlainTextFormattingModelBuilder); + + TestFileStructure.delete(myWorkingDirectory.getVirtualFile()); + super.tearDown(); + } + + public void testInsertion() throws IOException { + doTest( + "public class B {\n" + + " int a = 3;\n" + + " String text;\n" + + " Object last = null;\n" + + "}", + + "public class B {\n" + + " int a = 3;\n" + + " int toIndent1 = 1;\n" + + " String text;\n" + + " int toIndent2\n" + + " Object last = null;\n" + + "}", + + line(2, 2), line(4, 4) + ); + } + + private static ChangedLines line(int from, int to) { + return new ChangedLines(from, to); + } + + public void testDeletion() throws IOException { + doTest( + "public class B {\n" + + " int a = 3;\n" + + " String text;\n" + + " Object last = null;\n" + + " Object first = null;\n" + + " Object second = null;\n" + + "}", + + "public class B {\n" + + " int newInt = 1;\n" + + " Object last = null;\n" + + "}", + + line(1, 1) + ); + } + + public void testModification() throws IOException { + doTest( + "public class B {\n" + + " int a = 3;\n" + + " String text;\n" + + " Object last = null;\n" + + " Object first = null;\n" + + " Object second = null;\n" + + "}", + + "public class B {\n" + + " int a = 33;\n" + + " String text;\n" + + " Object last = new Object();\n" + + " Object first = null;\n" + + " Object second = new Object();\n" + + "}", + + line(1, 1), line(3,3), line(5,5) + ); + } + + public void testReformatFiles() throws IOException { + ChangedFilesStructure fs = new ChangedFilesStructure(myWorkingDirectory); + + PsiFile m1 = fs.createFile("Test1.java", COMMITTED, MODIFIED); + PsiFile u1 = fs.createFile("Test2.java", COMMITTED, COMMITTED); + + fs.createDirectoryAndMakeItCurrent(); + PsiFile m2 = fs.createFile("Test3.java", COMMITTED, MODIFIED); + PsiFile u2 = fs.createFile("Test4.java", COMMITTED, COMMITTED); + + new ReformatCodeProcessor(getProject(), new PsiFile[] {m1, m2, u1, u2}, null, true).run(); + + assertFormattedLines(CHANGED_LINES, m1, m2); + assertFormattedLines(NO_CHANGED_LINES, u1, u2); + } + + public void testNoChangesNoFormatting() throws IOException { + ChangedFilesStructure fs = new ChangedFilesStructure(myWorkingDirectory); + + PsiFile u1 = fs.createFile("Test1.java", COMMITTED, COMMITTED); + PsiFile u2 = fs.createFile("Test2.java", COMMITTED, COMMITTED); + + reformatDirectory(fs.getCurrentDirectory()); + + assertFormattedLines(NO_CHANGED_LINES, u1, u2); + } + + + public void testReformatOnlyChanged() throws IOException { + ChangedFilesStructure fs = new ChangedFilesStructure(myWorkingDirectory); + + PsiFile untouched1 = fs.createFile("Test1.java", COMMITTED, COMMITTED); + PsiFile untouched2 = fs.createFile("Test2.java", COMMITTED, COMMITTED); + + PsiFile modified1 = fs.createFile("Test4.java", COMMITTED, MODIFIED); + PsiFile modified2 = fs.createFile("Test5.java", COMMITTED, MODIFIED); + PsiFile modified3 = fs.createFile("Test6.java", COMMITTED, MODIFIED); + + reformatDirectory(fs.getCurrentDirectory()); + + + assertFormattedLines(CHANGED_LINES, modified1, modified2, modified3); + assertFormattedLines(NO_CHANGED_LINES, untouched1, untouched2); + } + + public void testReformatInAllSubtree() throws IOException { + ChangedFilesStructure fs = new ChangedFilesStructure(myWorkingDirectory); + PsiFile modified11 = fs.createFile("Test4.java", COMMITTED, MODIFIED); + PsiFile modified12 = fs.createFile("Test5.java", COMMITTED, MODIFIED); + + fs.createDirectoryAndMakeItCurrent(); + PsiDirectory dirToReformat = fs.getCurrentDirectory(); + PsiFile modified21 = fs.createFile("Test6.java", COMMITTED, MODIFIED); + PsiFile modified22 = fs.createFile("Test7.java", COMMITTED, MODIFIED); + + fs.createDirectoryAndMakeItCurrent(); + PsiFile modified31 = fs.createFile("Test8.java", COMMITTED, MODIFIED); + PsiFile modified32 = fs.createFile("Test9.java", COMMITTED, MODIFIED); + + reformatDirectory(dirToReformat); + + assertFormattedLines(CHANGED_LINES, modified21, modified22, modified31, modified32); + assertFormattedLines(NO_CHANGED_LINES, modified11, modified12); + } + + private static void registerChangeListManager(@NotNull ChangeListManager manager) { + Project project = getProject(); + assert (project instanceof ComponentManagerImpl); + ComponentManagerImpl projectComponentManager = (ComponentManagerImpl)project; + projectComponentManager.registerComponentInstance(ChangeListManager.class, manager); + } + + private static void registerCodeStyleManager(@NotNull CodeStyleManager manager) { + String componentKey = CodeStyleManager.class.getName(); + MutablePicoContainer container = (MutablePicoContainer)getProject().getPicoContainer(); + container.unregisterComponent(componentKey); + container.registerComponentInstance(componentKey, manager); + } + + private void doTest(@NotNull String committed, @NotNull String modified, @NotNull ChangedLines... lines) throws IOException { + ChangedFilesStructure fs = new ChangedFilesStructure(myWorkingDirectory); + PsiFile file = fs.createFile("Test.java", committed, modified); + reformatDirectory(myWorkingDirectory); + assertFormattedRangesEqualsTo(file, lines); + } + + private void assertFormattedLines(@NotNull ChangedLines[] expectedLines, @NotNull PsiFile... files) { + for (PsiFile file : files) + assertFormattedRangesEqualsTo(file, expectedLines); + } + + private void assertFormattedRangesEqualsTo(@NotNull PsiFile file, ChangedLines... expected) { + ChangedLines[] formatted = myMockCodeStyleManager.getFormattedLinesFor(file); + + Comparator cmp = new Comparator() { + @Override + public int compare(ChangedLines o1, ChangedLines o2) { + return o1.from < o2.from ? -1 : 1; + } + }; + Arrays.sort(expected, cmp); + Arrays.sort(formatted, cmp); + + assertTrue(getErrorMessage(expected, formatted), Arrays.equals(expected, formatted)); + } + + @NotNull + private static String getErrorMessage(ChangedLines[] expected, ChangedLines[] actual) { + return "Expected: " + Arrays.toString(expected) + " Actual: " + Arrays.toString(actual); + } + + private static void reformatDirectory(@NotNull PsiDirectory dir) { + ReformatCodeProcessor processor = new ReformatCodeProcessor(getProject(), dir, true, true); + processor.run(); + } + + class ChangedFilesStructure { + private TestFileStructure myFileStructure; + + public ChangedFilesStructure(@NotNull PsiDirectory directory) { + myFileStructure = new TestFileStructure(getModule(), directory); + } + + public void createDirectoryAndMakeItCurrent() throws IOException { + myFileStructure.createDirectoryAndMakeItCurrent("inner"); + } + + @NotNull + public PsiFile createFile(@NotNull String fileName, + @NotNull String committedContent, + @NotNull String actualContent) throws IOException + { + PsiFile file = myFileStructure.addTestFile(fileName, actualContent); + if (committedContent != actualContent) { + registerCommittedRevision(committedContent, file); + } + return file; + } + + private void registerCommittedRevision(@NotNull String committedContent, @NotNull PsiFile... files) { + List changes = createChanges(committedContent, files); + injectChanges(changes); + } + + @NotNull + private List createChanges(@NotNull String committed, @NotNull PsiFile... files) { + List changes = ContainerUtil.newArrayList(); + for (PsiFile file : files) { + changes.add(createChange(committed, file)); + } + return changes; + } + + private void injectChanges(@NotNull List changes) { + Change[] arr = new Change[changes.size()]; + ContainerUtil.toArray(changes, arr); + myMockChangeListManager.addChanges(arr); + } + + @NotNull + private Change createChange(@NotNull String committed, @NotNull PsiFile file) { + FilePathImpl filePath = new FilePathImpl(file.getVirtualFile()); + ContentRevision before = new SimpleContentRevision(committed, filePath, ""); + ContentRevision after = new SimpleContentRevision("", filePath, ""); + return new Change(before, after); + } + + @NotNull + public PsiDirectory getCurrentDirectory() { + return myFileStructure.getCurrentDirectory(); + } + } +} + diff --git a/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/TestFileStructure.java b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/TestFileStructure.java new file mode 100644 index 000000000000..6dbe45689332 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/TestFileStructure.java @@ -0,0 +1,128 @@ +/* + * 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.actions; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.impl.file.PsiDirectoryFactory; +import com.intellij.testFramework.PsiTestUtil; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class TestFileStructure { + private int myLevel; + @NotNull private Project myProject; + @NotNull private Module myModule; + @NotNull private PsiDirectory myCurrentLevelDirectory; + private List> myFilesForLevel = new ArrayList>(); + + public TestFileStructure(@NotNull Module module, @NotNull PsiDirectory root) { + myProject = module.getProject(); + myModule = module; + myCurrentLevelDirectory = root; + myFilesForLevel.add(new ArrayList()); + myLevel = 0; + } + + @NotNull + public PsiFile addTestFile(@NotNull String name, @NotNull String content) throws IOException { + PsiFile createdFile = createFile(myModule, myCurrentLevelDirectory.getVirtualFile(), name, content); + getCurrentDirectoryFiles().add(createdFile); + return createdFile; + } + + @NotNull + public List getCurrentDirectoryFiles() { + return myFilesForLevel.get(myLevel); + } + + @NotNull + public PsiDirectory getCurrentDirectory() { + return myCurrentLevelDirectory; + } + + @NotNull + public TestFileStructure createDirectoryAndMakeItCurrent(String name) throws IOException { + myLevel++; + myFilesForLevel.add(new ArrayList()); + myCurrentLevelDirectory = createDirectory(myProject, myCurrentLevelDirectory.getVirtualFile(), name); + return this; + } + + public List getFilesAtLevel(int level) { + assert (myLevel >= level); + return myFilesForLevel.get(level); + } + + private PsiFile createFile(final Module module, final VirtualFile vDir, final String fileName, final String text) { + return new WriteAction() { + @Override + protected void run(@NotNull Result result) throws Throwable { + if (!ModuleRootManager.getInstance(module).getFileIndex().isInSourceContent(vDir)) { + PsiTestUtil.addSourceContentToRoots(module, vDir); + } + + final VirtualFile vFile = vDir.createChildData(vDir, fileName); + VfsUtil.saveText(vFile, text); + final PsiFile file = PsiManager.getInstance(myProject).findFile(vFile); + assert (file != null); + result.setResult(file); + } + }.execute().getResultObject(); + } + + public static PsiDirectory createDirectory(@NotNull Project project, @NotNull final VirtualFile parent, @NotNull final String name) throws IOException { + final VirtualFile[] dir = new VirtualFile[1]; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + try { + dir[0] = parent.createChildDirectory(null, name); + } + catch (IOException e) { + e.printStackTrace(); + } + } + }); + return PsiDirectoryFactory.getInstance(project).createDirectory(dir[0]); + } + + public static void delete(@NotNull final VirtualFile file) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + try { + file.delete(null); + } + catch (IOException e) { + e.printStackTrace(); + } + } + }); + } +} From efa4d644d60c7d07631d4af3d7ddf21e7fb51bba Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 6 May 2014 13:26:35 +0400 Subject: [PATCH 10/35] junit 4 library setup (IDEA-124780) --- .../daemon/impl/quickfix/OrderEntryFix.java | 30 +++++++++++-------- .../testIntegration/JavaTestFramework.java | 5 ++++ .../createTest/CreateTestDialog.java | 11 +++---- .../groovy/spock/SpockTestFramework.java | 1 - .../execution/junit/JUnit4Framework.java | 15 ++++++++++ 5 files changed, 43 insertions(+), 19 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/OrderEntryFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/OrderEntryFix.java index 6b4a4721b4f0..97249280bb4e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/OrderEntryFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/OrderEntryFix.java @@ -124,19 +124,7 @@ public abstract class OrderEntryFix implements IntentionAction, LocalQuickFix { final VirtualFile location = PsiUtilCore.getVirtualFile(reference != null ? reference.getElement() : null); boolean inTests = location != null && ModuleRootManager.getInstance(currentModule).getFileIndex().isInTestSourceContent(location); try { - final String[] junit4Paths = {JavaSdkUtil.getJunit4JarPath(), - PathUtil.getJarPathForClass(Class.forName("org.hamcrest.Matcher")), - PathUtil.getJarPathForClass(Class.forName("org.hamcrest.Matchers"))}; - ModuleRootModificationUtil.addModuleLibrary(currentModule, - "JUnit4", - ContainerUtil.map(junit4Paths, - new Function() { - @Override - public String fun(String libPath) { - return convertToLibraryRoot(libPath).getUrl(); - } - }), - Collections.emptyList(), inTests ? DependencyScope.TEST : DependencyScope.COMPILE); + addJUnit4Library(inTests, currentModule); final GlobalSearchScope scope = GlobalSearchScope.moduleWithLibrariesScope(currentModule); final PsiClass aClass = JavaPsiFacade.getInstance(project).findClass(className, scope); if (aClass != null && editor != null && reference != null) { @@ -276,6 +264,22 @@ public abstract class OrderEntryFix implements IntentionAction, LocalQuickFix { return result; } + public static void addJUnit4Library(boolean inTests, Module currentModule) throws ClassNotFoundException { + final String[] junit4Paths = {JavaSdkUtil.getJunit4JarPath(), + PathUtil.getJarPathForClass(Class.forName("org.hamcrest.Matcher")), + PathUtil.getJarPathForClass(Class.forName("org.hamcrest.Matchers"))}; + ModuleRootModificationUtil.addModuleLibrary(currentModule, + "JUnit4", + ContainerUtil.map(junit4Paths, + new Function() { + @Override + public String fun(String libPath) { + return convertToLibraryRoot(libPath).getUrl(); + } + }), + Collections.emptyList(), inTests ? DependencyScope.TEST : DependencyScope.COMPILE); + } + private static List filterAllowedDependencies(PsiElement element, PsiClass[] classes) { DependencyValidationManager dependencyValidationManager = DependencyValidationManager.getInstance(element.getProject()); PsiFile fromFile = element.getContainingFile(); diff --git a/java/java-impl/src/com/intellij/testIntegration/JavaTestFramework.java b/java/java-impl/src/com/intellij/testIntegration/JavaTestFramework.java index 400648016cba..6dfb54116bbb 100644 --- a/java/java-impl/src/com/intellij/testIntegration/JavaTestFramework.java +++ b/java/java-impl/src/com/intellij/testIntegration/JavaTestFramework.java @@ -15,6 +15,7 @@ */ package com.intellij.testIntegration; +import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateDescriptor; import com.intellij.ide.fileTemplates.FileTemplateManager; @@ -119,4 +120,8 @@ public abstract class JavaTestFramework implements TestFramework { public FileTemplateDescriptor getTestClassFileTemplateDescriptor() { return null; } + + public void setupLibrary(Module module) { + OrderEntryFix.addJarToRoots(getLibraryPath(), module, null); + } } diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java index fe2b896499b3..cf4c67911208 100644 --- a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java +++ b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java @@ -126,10 +126,7 @@ public class CreateTestDialog extends DialogWrapper { for (final TestFramework descriptor : Extensions.getExtensions(TestFramework.EXTENSION_NAME)) { final JRadioButton b = new JRadioButton(descriptor.getName()); if (descriptor instanceof JavaTestFramework) { - final char mnemonic = ((JavaTestFramework)descriptor).getMnemonic(); - if (mnemonic > -1) { - b.setMnemonic(mnemonic); - } + b.setMnemonic(((JavaTestFramework)descriptor).getMnemonic()); } myLibraryButtons.add(b); group.add(b); @@ -173,7 +170,11 @@ public class CreateTestDialog extends DialogWrapper { public void actionPerformed(ActionEvent e) { ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { - OrderEntryFix.addJarToRoots(mySelectedFramework.getLibraryPath(), myTargetModule, null); + if (mySelectedFramework instanceof JavaTestFramework) { + ((JavaTestFramework)mySelectedFramework).setupLibrary(myTargetModule); + } else { + OrderEntryFix.addJarToRoots(mySelectedFramework.getLibraryPath(), myTargetModule, null); + } } }); myFixLibraryPanel.setVisible(false); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockTestFramework.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockTestFramework.java index 9a36c8c83990..77a592325701 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockTestFramework.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockTestFramework.java @@ -20,7 +20,6 @@ import com.intellij.ide.fileTemplates.FileTemplateDescriptor; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; -import com.intellij.util.PathUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnit4Framework.java b/plugins/junit/src/com/intellij/execution/junit/JUnit4Framework.java index 61fc645dd227..2b4ff0c4bd84 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnit4Framework.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnit4Framework.java @@ -17,10 +17,13 @@ package com.intellij.execution.junit; import com.intellij.CommonBundle; import com.intellij.codeInsight.AnnotationUtil; +import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix; import com.intellij.codeInsight.intention.AddAnnotationFix; import com.intellij.icons.AllIcons; import com.intellij.ide.fileTemplates.FileTemplateDescriptor; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.module.Module; import com.intellij.openapi.projectRoots.ex.JavaSdkUtil; import com.intellij.openapi.ui.Messages; import com.intellij.psi.*; @@ -34,6 +37,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; public class JUnit4Framework extends JavaTestFramework { + private static final Logger LOG = Logger.getInstance("#" + JUnit4Framework.class.getName()); + @NotNull public String getName() { return "JUnit4"; @@ -153,6 +158,16 @@ public class JUnit4Framework extends JavaTestFramework { return new FileTemplateDescriptor("JUnit4 Test Class.java"); } + @Override + public void setupLibrary(Module module) { + try { + OrderEntryFix.addJUnit4Library(false, module); + } + catch (ClassNotFoundException e) { + LOG.info(e); + } + } + @Override public boolean isParameterized(PsiClass clazz) { final PsiAnnotation annotation = AnnotationUtil.findAnnotation(clazz, JUnitUtil.RUN_WITH); From 459d870ccf09cfd3d3e1d4c648d923648a8bfcdb Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 6 May 2014 13:30:33 +0400 Subject: [PATCH 11/35] ignore @org.mockito.Spy (IDEA-124802) --- .../execution/junit2/inspection/JUnitEntryPoint.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java b/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java index b59854e320e6..ca813def140f 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java +++ b/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java @@ -98,6 +98,11 @@ public class JUnitEntryPoint extends EntryPoint { @Override public String[] getIgnoreAnnotations() { - return new String[]{"org.junit.Rule", "org.mockito.Mock", "org.mockito.InjectMocks", "org.junit.ClassRule", "org.junit.experimental.theories.DataPoint"}; + return new String[]{"org.junit.Rule", + "org.mockito.Mock", + "org.mockito.Spy", + "org.mockito.InjectMocks", + "org.junit.ClassRule", + "org.junit.experimental.theories.DataPoint"}; } } \ No newline at end of file From 2a38f58c36157d7cbefa2852988b57049c7b84bb Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Tue, 6 May 2014 14:18:59 +0400 Subject: [PATCH 12/35] IDEA-115737 Mercurial problem on Windows when repository replaced right inside disk directory. *relative path should be constructed using FileUtil method, because File.getParent method has side effect with minimal prefix length. --- .../hg4idea/src/org/zmlx/hg4idea/HgFile.java | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgFile.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgFile.java index d82cd97c8e43..0d3e2d8c4da2 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgFile.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgFile.java @@ -16,10 +16,11 @@ import com.google.common.base.Objects; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.util.HgUtil; import java.io.File; @@ -53,10 +54,11 @@ public class HgFile { return file; } - @NotNull + @Nullable public String getRelativePath() { if (relativePath == null) { - relativePath = buildRelativePath(VfsUtil.virtualToIoFile(vcsRoot), file); + //For configuration like "d:/.hg" File.getParent method has minimal prefix length, so vcsRoot will be "d:", getParent will be "d:/". + relativePath = FileUtil.getRelativePath(VfsUtilCore.virtualToIoFile(vcsRoot), file); } return relativePath; } @@ -66,17 +68,6 @@ public class HgFile { return VcsUtil.getFilePath(file); } - private static String buildRelativePath(File anchestor, File descendant) { - if (anchestor.equals(descendant)) { - return "."; - } - if (anchestor.equals(descendant.getParentFile())) { - return descendant.getName(); - } - return buildRelativePath(anchestor, descendant.getParentFile()) - + File.separator + descendant.getName(); - } - @Override public boolean equals(Object o) { if (this == o) { From 5790679a23aecba812d8ce2c656c38bd8e7fbec0 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 5 May 2014 18:55:33 +0200 Subject: [PATCH 13/35] getter invocation in case of object-backed scope --- .../src/org/jetbrains/debugger/ObjectProperty.java | 10 ---------- .../src/org/jetbrains/debugger/ValueModifier.java | 4 ++++ .../src/org/jetbrains/debugger/VariableView.java | 6 +++--- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/ObjectProperty.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/ObjectProperty.java index a3f9a9683fc8..94bdb29a59c6 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/ObjectProperty.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/ObjectProperty.java @@ -1,11 +1,7 @@ package org.jetbrains.debugger; -import com.intellij.openapi.util.AsyncResult; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.debugger.values.FunctionValue; -import org.jetbrains.debugger.values.ObjectValue; -import org.jetbrains.debugger.values.Value; /** * Exposes additional data if variable is a property of object and its property descriptor @@ -38,10 +34,4 @@ public interface ObjectProperty extends Variable { * @return whether property described as 'enumerable' */ boolean isEnumerable(); - - /** - * Asynchronously evaluates property getter and returns property value - */ - @NotNull - AsyncResult evaluateGet(@NotNull ObjectValue host, @NotNull EvaluateContext evaluateContext); } diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/ValueModifier.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/ValueModifier.java index e7bcbbb889b9..d276c1d6e8d2 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/ValueModifier.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/ValueModifier.java @@ -1,6 +1,7 @@ package org.jetbrains.debugger; import com.intellij.openapi.util.ActionCallback; +import com.intellij.openapi.util.AsyncResult; import org.jetbrains.annotations.NotNull; import org.jetbrains.debugger.values.Value; @@ -13,4 +14,7 @@ public interface ValueModifier { ActionCallback setValue(@NotNull Variable variable, String newValue, @NotNull EvaluateContext evaluateContext); ActionCallback setValue(@NotNull Variable variable, Value newValue, @NotNull EvaluateContext evaluateContext); + + @NotNull + AsyncResult evaluateGet(@NotNull ObjectProperty property, @NotNull EvaluateContext evaluateContext); } \ No newline at end of file diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableView.java b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableView.java index 0b7c43a3684c..e35a488b3829 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableView.java +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableView.java @@ -153,9 +153,9 @@ public final class VariableView extends XNamedValue implements VariableContext { node.setFullValueEvaluator(new XFullValueEvaluator(" (invoke getter)") { @Override public void startEvaluation(@NotNull final XFullValueEvaluationCallback callback) { - ObjectValue host = (ObjectValue)((VariableView)context).getValue(); - assert host != null; - ObsolescentAsyncResults.consume(((ObjectProperty)variable).evaluateGet(host, getEvaluateContext()), node, new PairConsumer() { + ValueModifier valueModifier = variable.getValueModifier(); + assert valueModifier != null; + ObsolescentAsyncResults.consume(valueModifier.evaluateGet((ObjectProperty)variable, getEvaluateContext()), node, new PairConsumer() { @Override public void consume(Value value, XValueNode node) { callback.evaluated(""); From 61b298f6d38080105819a705bcfc72dc9d42d29c Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 6 May 2014 10:03:27 +0200 Subject: [PATCH 14/35] ^461 don't create invalid range marker --- .../editor/LazyRangeMarkerFactory.java | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java index e99e06527878..2dca4e6c88a8 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java @@ -45,6 +45,15 @@ public class LazyRangeMarkerFactory { EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() { @Override public void beforeDocumentChange(DocumentEvent e) { + transformRangeMarkers(e); + } + + @Override + public void documentChanged(DocumentEvent e) { + transformRangeMarkers(e); + } + + private void transformRangeMarkers(DocumentEvent e) { VirtualFile file = fileDocumentManager.getFile(e.getDocument()); if (file == null) { return; @@ -58,8 +67,7 @@ public class LazyRangeMarkerFactory { List markers = lazyMarkers.toStrongList(); List markersToRemove = null; for (LazyMarker marker : markers) { - if (file.equals(marker.getFile())) { - marker.getOrCreateDelegate(); + if (file.equals(marker.getFile()) && marker.documentChanged(e.getDocument()) != null) { if (markersToRemove == null) { markersToRemove = new SmartList(); } @@ -143,13 +151,26 @@ public class LazyRangeMarkerFactory { return myDelegate; } - @NotNull + @Nullable + protected final RangeMarker documentChanged(@NotNull Document document) { + if (myDelegate == null) { + myDelegate = createDelegate(myFile, document); + } + return myDelegate; + } + + @Nullable protected abstract RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document); @Override @NotNull public Document getDocument() { - return getOrCreateDelegate().getDocument(); + RangeMarker delegate = getOrCreateDelegate(); + if (delegate == null) { + //noinspection ConstantConditions + return FileDocumentManager.getInstance().getDocument(myFile); + } + return delegate.getDocument(); } @Override @@ -222,10 +243,13 @@ public class LazyRangeMarkerFactory { } @Override - @NotNull - public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull final Document document) { - int offset = calculateOffset(myProject, file, document, myLine, myColumn); + @Nullable + public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document) { + if (document.getTextLength() == 0 && !(myLine == 0 && myColumn == 0)) { + return null; + } + int offset = calculateOffset(myProject, file, document, myLine, myColumn); return document.createRangeMarker(offset, offset); } From 78e7840e180328a4b37d4e4de9e31067a3822dfc Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 6 May 2014 12:09:24 +0200 Subject: [PATCH 15/35] WEB-12106 node-webkit crashes when opening developer tools --- .../util/io/socketConnection/ConnectionStatus.java | 11 ++++++++--- .../org/jetbrains/debugger/StandaloneVmHelper.java | 2 +- .../jetbrains/debugger/connection/VmConnection.java | 6 +++--- .../src/org/jetbrains/protocolReader/Generator.java | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/util/io/socketConnection/ConnectionStatus.java b/platform/platform-impl/src/com/intellij/util/io/socketConnection/ConnectionStatus.java index cad91b35802d..1c4fd2a664e6 100644 --- a/platform/platform-impl/src/com/intellij/util/io/socketConnection/ConnectionStatus.java +++ b/platform/platform-impl/src/com/intellij/util/io/socketConnection/ConnectionStatus.java @@ -3,11 +3,16 @@ package com.intellij.util.io.socketConnection; import org.jetbrains.annotations.NotNull; public enum ConnectionStatus { - NOT_CONNECTED("Not connected"), WAITING_FOR_CONNECTION("Waiting for connection"), CONNECTED("Connected"), DISCONNECTED("Disconnected"), - CONNECTION_FAILED("Connection failed"); + NOT_CONNECTED("Not connected"), + WAITING_FOR_CONNECTION("Waiting for connection"), + CONNECTED("Connected"), + DISCONNECTED("Disconnected"), + CONNECTION_FAILED("Connection failed"), + DETACHED("Detached"); + private final String myStatusText; - ConnectionStatus(String statusText) { + ConnectionStatus(@NotNull String statusText) { myStatusText = statusText; } diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/StandaloneVmHelper.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/StandaloneVmHelper.java index 36d2ec0515f2..e9eed257fd8f 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/StandaloneVmHelper.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/StandaloneVmHelper.java @@ -16,7 +16,7 @@ public final class StandaloneVmHelper extends MessageWriter { private final VmEx vm; - public StandaloneVmHelper(VmEx vm) { + public StandaloneVmHelper(@NotNull VmEx vm) { this.vm = vm; } diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/VmConnection.java b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/VmConnection.java index 6cdf3306d3f1..ad0bb6f0ac9e 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/VmConnection.java +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/VmConnection.java @@ -70,7 +70,7 @@ public abstract class VmConnection implements Disposable, BrowserC started.setDone(); } - public final void close(@Nullable String message) { + public final void close(@Nullable String message, @NotNull ConnectionStatus status) { if (!closed.compareAndSet(false, true)) { return; } @@ -79,7 +79,7 @@ public abstract class VmConnection implements Disposable, BrowserC if (!started.isProcessed()) { started.setRejected(); } - setState(ConnectionStatus.DISCONNECTED, message); + setState(status, message); Disposer.dispose(this, false); } @@ -101,7 +101,7 @@ public abstract class VmConnection implements Disposable, BrowserC vm = null; callback = currentVm.detach(); } - close(null); + close(null, ConnectionStatus.DISCONNECTED); return callback; } } \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java index acea0626c3db..e545f0280f81 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java @@ -70,7 +70,7 @@ class Generator { } private static boolean isDomainSkipped(Domain domain) { - if (domain.domain().equals("CSS")) { + if (domain.domain().equals("CSS") || domain.domain().equals("Inspector")) { return false; } From 1c6ba24c4bb4d0ad171ef1e9e2f43369e5cd2461 Mon Sep 17 00:00:00 2001 From: Vassiliy Date: Tue, 6 May 2014 14:40:53 +0400 Subject: [PATCH 16/35] Start plugins wizard #27 cleanup --- .../startupWizardV2/AbstractWizardPage.java | 41 ----- .../startupWizardV2/FeaturedPluginsPage.java | 45 ------ .../ide/startupWizardV2/KeymapPage.java | 39 ----- .../intellij/ide/startupWizardV2/LafPage.java | 115 ------------- .../ide/startupWizardV2/PluginsPage.java | 39 ----- .../ide/startupWizardV2/StartupWizard2.java | 153 ------------------ 6 files changed, 432 deletions(-) delete mode 100644 platform/platform-impl/src/com/intellij/ide/startupWizardV2/AbstractWizardPage.java delete mode 100644 platform/platform-impl/src/com/intellij/ide/startupWizardV2/FeaturedPluginsPage.java delete mode 100644 platform/platform-impl/src/com/intellij/ide/startupWizardV2/KeymapPage.java delete mode 100644 platform/platform-impl/src/com/intellij/ide/startupWizardV2/LafPage.java delete mode 100644 platform/platform-impl/src/com/intellij/ide/startupWizardV2/PluginsPage.java delete mode 100644 platform/platform-impl/src/com/intellij/ide/startupWizardV2/StartupWizard2.java diff --git a/platform/platform-impl/src/com/intellij/ide/startupWizardV2/AbstractWizardPage.java b/platform/platform-impl/src/com/intellij/ide/startupWizardV2/AbstractWizardPage.java deleted file mode 100644 index 727fb7326eb3..000000000000 --- a/platform/platform-impl/src/com/intellij/ide/startupWizardV2/AbstractWizardPage.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.ide.startupWizardV2; - -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; - -public abstract class AbstractWizardPage extends JPanel { - public AbstractWizardPage() { - } - - @NotNull - abstract String getID(); - - @NotNull - abstract String getTitle(); - - @NotNull - String getHeader() { - return " "; - } - - @NotNull - String getFooter() { - return " "; - } -} diff --git a/platform/platform-impl/src/com/intellij/ide/startupWizardV2/FeaturedPluginsPage.java b/platform/platform-impl/src/com/intellij/ide/startupWizardV2/FeaturedPluginsPage.java deleted file mode 100644 index 12aac3dd61e4..000000000000 --- a/platform/platform-impl/src/com/intellij/ide/startupWizardV2/FeaturedPluginsPage.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.ide.startupWizardV2; - -import com.intellij.CommonBundle; -import org.jetbrains.annotations.NotNull; - -public class FeaturedPluginsPage extends AbstractWizardPage{ - @NotNull - @Override - String getID() { - return "Featured plugins"; - } - - @NotNull - @Override - String getTitle() { - return "Download featured plugins"; - } - - @NotNull - @Override - String getHeader() { - return "We have a few plugins in our web repository that most users like to download. Perhaps, you need them too?"; - } - - @NotNull - @Override - String getFooter() { - return "New plugins can be also downloaded in " + CommonBundle.settingsTitle() +" | Plugins"; - } -} diff --git a/platform/platform-impl/src/com/intellij/ide/startupWizardV2/KeymapPage.java b/platform/platform-impl/src/com/intellij/ide/startupWizardV2/KeymapPage.java deleted file mode 100644 index 2bcf1a091c5e..000000000000 --- a/platform/platform-impl/src/com/intellij/ide/startupWizardV2/KeymapPage.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.ide.startupWizardV2; - -import com.intellij.CommonBundle; -import org.jetbrains.annotations.NotNull; - -public class KeymapPage extends AbstractWizardPage { - @NotNull - @Override - String getID() { - return "Keymaps"; - } - - @NotNull - @Override - String getTitle() { - return "Select keymap scheme"; - } - - @NotNull - @Override - String getFooter() { - return "Keymap scheme can be later changed in " + CommonBundle.settingsTitle() + " | Keymap"; - } -} diff --git a/platform/platform-impl/src/com/intellij/ide/startupWizardV2/LafPage.java b/platform/platform-impl/src/com/intellij/ide/startupWizardV2/LafPage.java deleted file mode 100644 index bee68fb93411..000000000000 --- a/platform/platform-impl/src/com/intellij/ide/startupWizardV2/LafPage.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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.ide.startupWizardV2; - -import com.intellij.CommonBundle; -import com.intellij.ide.ui.laf.IntelliJLookAndFeelInfo; -import com.intellij.ide.ui.laf.darcula.DarculaLookAndFeelInfo; -import com.intellij.openapi.util.IconLoader; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.util.IconUtil; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; -import java.awt.*; -import java.util.LinkedHashMap; -import java.util.Map; - -public class LafPage extends AbstractWizardPage { - private static final String AQUA = "Default"; - private static final String DARCULA = "Darcula"; - private static final String ALLOY = "Alloy. IDEA Theme"; - private static final String INTELLIJ = "IntelliJ"; - private static final String GTK = "GTK+"; - - private Map myLafs = new LinkedHashMap(); - private final JLabel myPreviewLabel = new JLabel(); - private final boolean myVertical; - - public LafPage() { - boolean isAlloyAvailable = false; - boolean isGTKAvailable = false; - for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { - if (ALLOY.equals(info.getName())) { - isAlloyAvailable = true; - } - if (GTK.equals(info.getName())) { - isGTKAvailable = true; - } - } - final String osPrefix = SystemInfo.isMac ? "OSX" : SystemInfo.isWindows ? "Windows" : "Linux"; - - if (SystemInfo.isMac) { - myLafs.put(new UIManager.LookAndFeelInfo(AQUA, "com.apple.laf.AquaLookAndFeel"), IconLoader.getIcon("/lafs/OSXAqua.png")); - } - else { - if (isAlloyAvailable) { - myLafs.put(new UIManager.LookAndFeelInfo(ALLOY, "com.incors.plaf.alloy.AlloyIdea"), - IconLoader.getIcon("/lafs/" + osPrefix + "Alloy.png")); - } - else { - myLafs.put(new IntelliJLookAndFeelInfo(), IconLoader.getIcon("/lafs/" + osPrefix + "IntelliJ.png")); - } - } - - myLafs.put(new DarculaLookAndFeelInfo(), IconLoader.getIcon("/lafs/" + osPrefix + "Darcula.png")); - - if (SystemInfo.isLinux && isGTKAvailable) { - myLafs.put(new UIManager.LookAndFeelInfo(GTK, "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"), - IconLoader.getIcon("/lafs/" + osPrefix + "GTK.png")); - } - - myVertical = myLafs.size() > 2; - JPanel buttonPanel = new JPanel(myVertical ? new GridLayout(myLafs.size(), 1, 5, 5) : new GridLayout(1, myLafs.size(), 5, 5)); - ButtonGroup group = new ButtonGroup(); - boolean isFirst = true; - for (Map.Entry entry : myLafs.entrySet()) { - JPanel p = new JPanel(new BorderLayout()); - JRadioButton radioButton = new JRadioButton(entry.getKey().getName(), isFirst); - isFirst = false; - group.add(radioButton); - p.add(radioButton, BorderLayout.NORTH); - Icon icon = entry.getValue(); - buttonPanel.add(new JLabel(myVertical ? - new ImageIcon(IconUtil.toImage(icon) - .getScaledInstance(icon.getIconWidth() / 3, icon.getIconHeight() / 3, Image.SCALE_AREA_AVERAGING)) - : icon)); - } - setLayout(new BorderLayout()); - add(buttonPanel, BorderLayout.CENTER); - if (myVertical) { - add(myPreviewLabel, BorderLayout.EAST); - } - } - - @NotNull - @Override - String getTitle() { - return "Set UI Theme"; - } - - @NotNull - @Override - String getID() { - return "UI Themes"; - } - - @NotNull - @Override - String getFooter() { - return "UI theme can be changed later in " + CommonBundle.settingsTitle() + " | Appearance."; - } -} diff --git a/platform/platform-impl/src/com/intellij/ide/startupWizardV2/PluginsPage.java b/platform/platform-impl/src/com/intellij/ide/startupWizardV2/PluginsPage.java deleted file mode 100644 index 1e27ad49ea7a..000000000000 --- a/platform/platform-impl/src/com/intellij/ide/startupWizardV2/PluginsPage.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.ide.startupWizardV2; - -import com.intellij.openapi.application.ApplicationNamesInfo; -import org.jetbrains.annotations.NotNull; - -public class PluginsPage extends AbstractWizardPage { - @NotNull - @Override - String getID() { - return "Default plugins"; - } - - @NotNull - @Override - String getTitle() { - return "Tune " + ApplicationNamesInfo.getInstance().getProductName() + " to your tasks"; - } - - @NotNull - @Override - String getHeader() { - return ApplicationNamesInfo.getInstance().getProductName() + " has a lot of tools enabled by default. You can set only the ones you need or leave them all."; - } -} diff --git a/platform/platform-impl/src/com/intellij/ide/startupWizardV2/StartupWizard2.java b/platform/platform-impl/src/com/intellij/ide/startupWizardV2/StartupWizard2.java deleted file mode 100644 index 89cbfbf71fbc..000000000000 --- a/platform/platform-impl/src/com/intellij/ide/startupWizardV2/StartupWizard2.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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.ide.startupWizardV2; - -import com.intellij.openapi.application.ApplicationNamesInfo; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.ui.VerticalFlowLayout; -import com.intellij.openapi.util.IconLoader; -import com.intellij.ui.JBCardLayout; -import com.intellij.ui.components.JBScrollPane; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Arrays; -import java.util.List; - -public class StartupWizard2 extends DialogWrapper implements ActionListener { - - private final JLabel myNavLabel = new JLabel(); - private final JLabel myHeaderLabel = new JLabel(); - private final JLabel myFooterLabel = new JLabel(); - private final JBCardLayout myCardLayout = new JBCardLayout(); - private final JPanel myContentPanel = new JPanel(myCardLayout); - - private final JButton mySkipButton = new JButton(); - private final JButton myBackwardButton = new JButton(); - private final JButton myForwardButton = new JButton(); - - private List myPages = Arrays.asList(new LafPage(), new KeymapPage(), new PluginsPage(), new FeaturedPluginsPage()); - private int myIndex = -1; - - public StartupWizard2() { - super(null, true, true); - IconLoader.activate(); - getPeer().setAppIcons(); - setResizable(false); - setTitle("Customize" + ApplicationNamesInfo.getInstance().getProductName()); - init(); - showPage(0); - } - - @Override - protected void dispose() { - super.dispose(); - IconLoader.deactivate(); - } - - @Override - public Dimension getPreferredSize() { - return new Dimension(700, 700); - } - - @Override - public void actionPerformed(ActionEvent event) { - if (event.getSource() == mySkipButton) { - doOKAction(); - } - if (event.getSource() == myBackwardButton) { - showPage(myIndex - 1); - } - if (event.getSource() == myForwardButton) { - if (myIndex == myPages.size() - 1) { - doOKAction(); - } - else { - showPage(myIndex + 1); - } - } - } - - private void showPage(int index) { - myIndex = index; - AbstractWizardPage page = myPages.get(index); - myCardLayout.swipe(myContentPanel, page.getID(), JBCardLayout.SwipeDirection.AUTO); - updateNavLabel(); - myHeaderLabel.setText("

" + page.getTitle() + "

" + page.getHeader() + ""); - myFooterLabel.setText("" + page.getFooter() + ""); - mySkipButton.setText(myIndex>0?"Skip All and Set Defaults" : "Skip Remaining and Set Defaults"); - myBackwardButton.setVisible(myIndex>0); - if (myIndex > 0) { - myBackwardButton.setText("Back to " + myPages.get(myIndex-1).getID()); - } - myForwardButton.setText(myIndex < myPages.size() - 1 ? "Next: " + myPages.get(myIndex+1).getID() : "Start using " + ApplicationNamesInfo - .getInstance().getFullProductName()); - } - - private void updateNavLabel() { - StringBuilder sb = new StringBuilder(""); - for (int i = 0; i < myPages.size(); i++) { - AbstractWizardPage wizardPage = myPages.get(i); - if (i > 0 && i < myPages.size() - 1) sb.append(" → "); - if (i == myIndex) sb.append(""); - sb.append(wizardPage.getID()); - if (i == myIndex) sb.append(""); - } - sb.append(""); - myNavLabel.setText(sb.toString()); - } - - - @Nullable - @Override - protected JComponent createCenterPanel() { - for (AbstractWizardPage page : myPages) { - myContentPanel.add(page, page.getID()); - } - JPanel mainPanel = new JPanel(new VerticalFlowLayout()); - mainPanel.add(myNavLabel); - mainPanel.add(myHeaderLabel); - mainPanel.add( - new JBScrollPane(myContentPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER)); - mainPanel.add(myFooterLabel); - return mainPanel; - } - - @Nullable - @Override - protected JComponent createSouthPanel() { - JPanel result = new JPanel(new GridBagLayout()); - result.setBorder(new EmptyBorder(5, 5, 5, 5)); - GridBagConstraints gbc = new GridBagConstraints(); - gbc.gridy = 0; - result.add(mySkipButton, gbc); - result.add(myBackwardButton, gbc); - gbc.weightx = 1; - result.add(Box.createHorizontalGlue(), gbc); - gbc.weightx = 0; - result.add(myForwardButton, gbc); - - mySkipButton.addActionListener(this); - myBackwardButton.addActionListener(this); - myForwardButton.addActionListener(this); - - return result; - } -} From d197ca8ba013de52285c1ab8c56a00cefbb1616c Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Tue, 6 May 2014 14:41:49 +0400 Subject: [PATCH 17/35] reformat only changed text checkboxes are enabled (IDEA-121171) --- .../actions/FormatChangedTextUtil.java | 8 ++++++++ .../codeInsight/actions/LayoutCodeDialog.java | 3 +-- .../actions/LayoutProjectCodeDialog.java | 16 ++++++++++++++-- .../codeInsight/actions/ReformatFilesDialog.form | 14 +++++++++++--- .../codeInsight/actions/ReformatFilesDialog.java | 9 ++++++++- 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java index a296689352ec..bf77a3022a0e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java @@ -125,6 +125,14 @@ public class FormatChangedTextUtil { return false; } + public static boolean hasChanges(@NotNull VirtualFile[] files, @NotNull Project project) { + for (VirtualFile file : files) { + if (hasChanges(file, project)) + return true; + } + return false; + } + /** * Allows to answer if any file that belongs to the given module has changes in comparison with VCS. * diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java index 41977e2e7015..cbf36e1f4b33 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java @@ -187,8 +187,7 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions myCbArrangeEntries.setEnabled(true); myCbArrangeEntries.setSelected(myRearrangeEntriesSelected); - //TODO enable it when getting changed ranges will be fixed - myCbOnlyVcsChangedRegions.setEnabled(false); + myCbOnlyVcsChangedRegions.setEnabled(myDirectory != null && FormatChangedTextUtil.hasChanges(myDirectory)); myCbOnlyVcsChangedRegions.setSelected(false); myDoNotAskMeCheckBox.setEnabled(false); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java index 7c581c5220dc..aa4aadc9a083 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java @@ -34,11 +34,13 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi private static @NonNls final String HELP_ID = "editing.codeReformatting"; private final String myText; + private final boolean myEnableOnlyVCSChangedTextCb; private final boolean mySuggestOptimizeImports; private final Project myProject; private JCheckBox myCbOptimizeImports; + private JCheckBox myCbOnlyVcsChangedRegions; private JCheckBox myCbRearrangeEntries; public LayoutProjectCodeDialog(@NotNull Project project, @@ -51,6 +53,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi myText = text; mySuggestOptimizeImports = suggestOptimizeImports; myProject = project; + myEnableOnlyVCSChangedTextCb = enableOnlyVCSChangedTextCb; setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text")); setTitle(title); @@ -63,16 +66,22 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi return new JLabel(myText); } - JPanel panel = new JPanel(new GridLayout(3, 1)); + JPanel panel = new JPanel(new GridLayout(4, 1)); myCbOptimizeImports = new JCheckBox(CodeInsightBundle.message("reformat.option.optimize.imports")); myCbRearrangeEntries = new JCheckBox(CodeInsightBundle.message("reformat.option.rearrange.entries")); + myCbOnlyVcsChangedRegions = new JCheckBox(CodeInsightBundle.message("reformat.option.vcs.changed.region")); panel.add(new JLabel(myText)); panel.add(myCbOptimizeImports); panel.add(myCbRearrangeEntries); + panel.add(myCbOnlyVcsChangedRegions); myCbOptimizeImports.setSelected(PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false)); myCbRearrangeEntries.setSelected(LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject)); + myCbOnlyVcsChangedRegions.setEnabled(myEnableOnlyVCSChangedTextCb); + myCbOnlyVcsChangedRegions.setSelected( + myEnableOnlyVCSChangedTextCb && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false) + ); return panel; } @@ -99,6 +108,9 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi if (mySuggestOptimizeImports) { PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(isOptimizeImports())); LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries()); + if (myEnableOnlyVCSChangedTextCb) { + PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myCbOnlyVcsChangedRegions.isSelected())); + } } } @@ -107,7 +119,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi } public boolean isProcessOnlyChangedText() { - return false; + return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected(); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.form b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.form index 4a2cb037cb1f..97a3afccbb10 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.form +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.form @@ -3,12 +3,12 @@ - + - + @@ -32,9 +32,17 @@
+ + + + + + + + - + diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java index 0ed05536303b..26a158e027f4 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java @@ -29,6 +29,7 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO @NotNull private Project myProject; private JPanel myPanel; private JCheckBox myOptimizeImports; + private JCheckBox myOnlyChangedText; private JCheckBox myRearrangeEntriesCb; public ReformatFilesDialog(@NotNull Project project, @NotNull VirtualFile[] files) { @@ -36,6 +37,11 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO myProject = project; setTitle(CodeInsightBundle.message("dialog.reformat.files.title")); myOptimizeImports.setSelected(isOptmizeImportsOptionOn()); + boolean canTargetVcsChanges = FormatChangedTextUtil.hasChanges(files, project); + myOnlyChangedText.setEnabled(canTargetVcsChanges); + myOnlyChangedText.setSelected( + canTargetVcsChanges && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false) + ); myOptimizeImports.setSelected(isOptmizeImportsOptionOn()); myRearrangeEntriesCb.setSelected(LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject)); init(); @@ -53,7 +59,7 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO @Override public boolean isProcessOnlyChangedText() { - return false; + return myOnlyChangedText.isEnabled() && myOnlyChangedText.isSelected(); } @Override @@ -65,6 +71,7 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO protected void doOKAction() { super.doOKAction(); PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(myOptimizeImports.isSelected())); + PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myOnlyChangedText.isSelected())); LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries()); } From e01a5af3c25b7ffbdc00e907858e36cb9ed8063f Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 6 May 2014 12:39:52 +0200 Subject: [PATCH 18/35] initial --- .../src/com/intellij/openapi/util/Couple.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 platform/util-rt/src/com/intellij/openapi/util/Couple.java diff --git a/platform/util-rt/src/com/intellij/openapi/util/Couple.java b/platform/util-rt/src/com/intellij/openapi/util/Couple.java new file mode 100644 index 000000000000..c078c8a0afff --- /dev/null +++ b/platform/util-rt/src/com/intellij/openapi/util/Couple.java @@ -0,0 +1,29 @@ +/* + * 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.util; + +/** + * @author Konstantin Bulenkov + */ +public class Couple extends Pair { + public Couple(T first, T second) { + super(first, second); + } + + public static Couple newOne(T first, T second) { + return new Couple(first, second); + } +} From 06778a8198005b006072e036474273b76204fd7b Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 6 May 2014 12:43:33 +0200 Subject: [PATCH 19/35] cleanup --- .../ide/actions/SearchEverywhereAction.java | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java index ace169021f27..6e4994bb846f 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java @@ -152,10 +152,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA private Component myContextComponent; private CalcThread myCalcThread; private static AtomicBoolean ourShiftIsPressed = new AtomicBoolean(false); - private static AtomicBoolean shift1Pressed = new AtomicBoolean(false); - private static AtomicBoolean shift1Released = new AtomicBoolean(false); - private static AtomicBoolean shift2Pressed = new AtomicBoolean(false); - private static AtomicBoolean shift2Released = new AtomicBoolean(false); + private final static Couple ourPressed = Couple.newOne(new AtomicBoolean(false), new AtomicBoolean(false)); + private final static Couple ourReleased = Couple.newOne(new AtomicBoolean(false), new AtomicBoolean(false)); private static AtomicBoolean ourOtherKeyWasPressed = new AtomicBoolean(false); private static AtomicLong ourLastTimePressed = new AtomicLong(0); private static AtomicBoolean showAll = new AtomicBoolean(false); @@ -185,7 +183,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA return false; } ourOtherKeyWasPressed.set(false); - if (shift1Pressed.get() && System.currentTimeMillis() - ourLastTimePressed.get() > 500) { + if (ourPressed.first.get() && System.currentTimeMillis() - ourLastTimePressed.get() > 500) { resetState(); } handleShift((KeyEvent)event); @@ -203,37 +201,37 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA } private void resetState() { - shift1Pressed.set(false); - shift1Released.set(false); - shift2Pressed.set(false); - shift2Released.set(false); + ourPressed.first.set(false); + ourPressed.second.set(false); + ourReleased.first.set(false); + ourReleased.second.set(false); } private void handleShift(KeyEvent event) { - if (shift1Pressed.get() && System.currentTimeMillis() - ourLastTimePressed.get() > 300) { + if (ourPressed.first.get() && System.currentTimeMillis() - ourLastTimePressed.get() > 300) { resetState(); return; } if (event.getID() == KeyEvent.KEY_PRESSED) { - if (!shift1Pressed.get()) { + if (!ourPressed.first.get()) { resetState(); - shift1Pressed.set(true); + ourPressed.first.set(true); ourLastTimePressed.set(System.currentTimeMillis()); return; } else { - if (shift1Pressed.get() && shift1Released.get()) { - shift2Pressed.set(true); + if (ourPressed.first.get() && ourReleased.first.get()) { + ourPressed.second.set(true); ourLastTimePressed.set(System.currentTimeMillis()); return; } } } else if (event.getID() == KeyEvent.KEY_RELEASED) { - if (shift1Pressed.get() && !shift1Released.get()) { - shift1Released.set(true); + if (ourPressed.first.get() && !ourReleased.first.get()) { + ourReleased.first.set(true); ourLastTimePressed.set(System.currentTimeMillis()); return; - } else if (shift1Pressed.get() && shift1Released.get() && shift2Pressed.get()) { + } else if (ourPressed.first.get() && ourReleased.first.get() && ourPressed.second.get()) { resetState(); run(event); return; From 815a632c87d6d4b2534b4b0d4b6d5f73a8038fed Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Tue, 6 May 2014 12:48:23 +0200 Subject: [PATCH 20/35] for given fragment: calc hash code once and do not use wrapper CharSequenceSubSequence for interning store CharSequence into Map of int -> CharSequence+ --- .../psi/impl/source/CharTableImpl.java | 153 ++++++++++++++---- 1 file changed, 125 insertions(+), 28 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java index 179d344711ae..01f1d17eab93 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java @@ -16,13 +16,12 @@ package com.intellij.psi.impl.source; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.CommonClassNames; import com.intellij.util.CharTable; -import com.intellij.util.containers.OpenTHashSet; import com.intellij.util.text.CharArrayUtil; -import com.intellij.util.text.CharSequenceHashingStrategy; -import com.intellij.util.text.CharSequenceSubSequence; import com.intellij.util.text.StringFactory; +import gnu.trove.TIntObjectHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,55 +33,62 @@ import java.lang.reflect.Modifier; */ public class CharTableImpl implements CharTable { private static final int INTERN_THRESHOLD = 40; // 40 or more characters long tokens won't be interned. - private static final CharSequenceHashingStrategy HASHER = CharSequenceHashingStrategy.CASE_SENSITIVE; - private static final OpenTHashSet STATIC_ENTRIES = newStaticSet(); - private final OpenTHashSet entries = new OpenTHashSet(10, 0.9f, HASHER); + private static final StringHashToCharSequencesMap STATIC_ENTRIES = newStaticSet(); + private final StringHashToCharSequencesMap entries = new StringHashToCharSequencesMap(10, 0.9f); @NotNull @Override public CharSequence intern(@NotNull final CharSequence text) { - if (text.length() > INTERN_THRESHOLD) return createSequence(text); + CharSequence result; + if (text.length() > INTERN_THRESHOLD) result = createSequence(text); + else result = doIntern(text); - return doIntern(text); + return result; } @NotNull - public CharSequence doIntern(@NotNull CharSequence text) { - CharSequence interned = getStaticInterned(text); + private CharSequence doIntern(@NotNull CharSequence text, int startOffset, int endOffset) { + int hashCode = subSequenceHashCode(text, startOffset, endOffset); + CharSequence interned = STATIC_ENTRIES.getSubSequenceWithHashCode(hashCode, text, startOffset, endOffset); if (interned != null) { return interned; } synchronized(entries) { - interned = entries.get(text); - if (interned != null) { - return interned; - } - // We need to create separate string just to prevent referencing all character data when original is string or char sequence over string - final CharSequence entry = createSequence(text); - boolean added = entries.add(entry); - assert added; - - return entry; + return entries.getOrAddSubSequenceWithHashCode(hashCode, text, startOffset, endOffset); } } + @NotNull + public CharSequence doIntern(@NotNull CharSequence text) { + return doIntern(text, 0, text.length()); + } + @NotNull @Override public CharSequence intern(@NotNull final CharSequence baseText, final int startOffset, final int endOffset) { - if (endOffset - startOffset == baseText.length()) return intern(baseText); - return intern(new CharSequenceSubSequence(baseText, startOffset, endOffset)); + CharSequence result; + if (endOffset - startOffset == baseText.length()) result = intern(baseText); + else if (endOffset - startOffset > INTERN_THRESHOLD) result = createSequence(baseText, startOffset, endOffset); + else result = doIntern(baseText, startOffset, endOffset); + + return result; } @NotNull private static String createSequence(@NotNull CharSequence text) { + return createSequence(text, 0, text.length()); + } + + @NotNull + private static String createSequence(@NotNull CharSequence text, int startOffset, int endOffset) { if (text instanceof String) { - return (String)text; + return ((String)text).substring(startOffset, endOffset); } - char[] buf = new char[text.length()]; - CharArrayUtil.getChars(text, buf, 0); + char[] buf = new char[endOffset - startOffset]; + CharArrayUtil.getChars(text, buf, startOffset, 0, buf.length); return StringFactory.createShared(buf); // this way the .toString() doesn't create another instance (as opposed to new CharArrayCharSequence()) } @@ -96,9 +102,9 @@ public class CharTableImpl implements CharTable { STATIC_ENTRIES.add(text); } } - - private static OpenTHashSet newStaticSet() { - final OpenTHashSet r = new OpenTHashSet(10, 0.9f, HASHER); + + private static StringHashToCharSequencesMap newStaticSet() { + final StringHashToCharSequencesMap r = new StringHashToCharSequencesMap(10, 0.9f); r.add("==" ); r.add("!=" ); r.add("||" ); @@ -214,4 +220,95 @@ public class CharTableImpl implements CharTable { staticIntern(typeName); } } + + private static class StringHashToCharSequencesMap extends TIntObjectHashMap { + StringHashToCharSequencesMap(int capacity, float loadFactor) { + super(capacity, loadFactor); + } + + CharSequence get(CharSequence sequence, int startOffset, int endOffset) { + return getSubSequenceWithHashCode(subSequenceHashCode(sequence, startOffset, endOffset), sequence, startOffset, endOffset); + } + + CharSequence getSubSequenceWithHashCode(int hashCode, CharSequence sequence, int startOffset, int endOffset) { + Object o = get(hashCode); + if (o == null) return null; + if (o instanceof CharSequence) { + if (charSequenceSubSequenceEquals((CharSequence)o, sequence, startOffset, endOffset)) { + return (CharSequence)o; + } + return null; + } else if (o instanceof CharSequence[]) { + for(CharSequence cs:(CharSequence[])o) { + if (charSequenceSubSequenceEquals(cs, sequence, startOffset, endOffset)) { + return cs; + } + } + } else { + assert false:o.getClass(); + } + return null; + } + + private static boolean charSequenceSubSequenceEquals(CharSequence cs, CharSequence baseSequence, int startOffset, int endOffset) { + if (cs.length() != endOffset - startOffset) return false; + if (cs == baseSequence && startOffset == 0) return true; + for(int i = 0, len = cs.length(); i < len; ++i) { + if (cs.charAt(i) != baseSequence.charAt(startOffset + i)) return false; + } + return true; + } + + CharSequence get(CharSequence sequence) { + return get(sequence, 0, sequence.length()); + } + + CharSequence add(CharSequence sequence) { + return add(sequence, 0, sequence.length()); + } + + CharSequence add(CharSequence sequence, int startOffset, int endOffset) { + int hashCode = subSequenceHashCode(sequence, startOffset, endOffset); + return getOrAddSubSequenceWithHashCode(hashCode, sequence, startOffset, endOffset); + } + + private CharSequence getOrAddSubSequenceWithHashCode(int hashCode, CharSequence sequence, int startOffset, int endOffset) { + int index = index(hashCode); + String addedSequence = null; + + if (index < 0) { + put(hashCode, addedSequence = createSequence(sequence, startOffset, endOffset)); + } else { + Object value = _values[index]; + if (value instanceof CharSequence) { + CharSequence existingSequence = (CharSequence)value; + if (charSequenceSubSequenceEquals(existingSequence, sequence, startOffset, endOffset)) { + return existingSequence; + } + put(hashCode, new CharSequence[] {existingSequence, addedSequence = createSequence(sequence, startOffset, endOffset)}); + } else if (value instanceof CharSequence[]) { + CharSequence[] existingSequenceArray = (CharSequence[])value; + for(CharSequence cs:existingSequenceArray) { + if (charSequenceSubSequenceEquals(cs, sequence, startOffset, endOffset)) { + return cs; + } + } + CharSequence[] newSequenceArray = new CharSequence[existingSequenceArray.length + 1]; + System.arraycopy(existingSequenceArray, 0, newSequenceArray, 0, existingSequenceArray.length); + newSequenceArray[existingSequenceArray.length] = addedSequence = createSequence(sequence, startOffset, endOffset); + put(hashCode, newSequenceArray); + } else { + assert false:value.getClass(); + } + } + return addedSequence; + } + } + + private static int subSequenceHashCode(CharSequence sequence, int startOffset, int endOffset) { + if (startOffset == 0 && endOffset == sequence.length()) { + return StringUtil.stringHashCode(sequence); + } + return StringUtil.stringHashCode(sequence, startOffset, endOffset); + } } From b967e4a75735b997528f20d0758833f911f4e313 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Tue, 6 May 2014 12:51:45 +0200 Subject: [PATCH 21/35] removed extra unneeded delegate --- .../src/com/intellij/util/io/PersistentHashMap.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/PersistentHashMap.java b/platform/util/src/com/intellij/util/io/PersistentHashMap.java index 00a10d958bbf..b81b02fa975a 100644 --- a/platform/util/src/com/intellij/util/io/PersistentHashMap.java +++ b/platform/util/src/com/intellij/util/io/PersistentHashMap.java @@ -188,18 +188,7 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } private SLRUCache createAppendCache(final KeyDescriptor keyDescriptor) { - final EqualityPolicy hashingStrategy = new EqualityPolicy() { - @Override - public int getHashCode(Key object) { - return keyDescriptor.getHashCode(object); - } - - @Override - public boolean isEqual(Key val1, Key val2) { - return keyDescriptor.isEqual(val1, val2); - } - }; - return new SLRUCache(16 * 1024, 4 * 1024, hashingStrategy) { + return new SLRUCache(16 * 1024, 4 * 1024, keyDescriptor) { @Override @NotNull public BufferExposingByteArrayOutputStream createValue(final Key key) { From ea5506c02e600ebf658bdb670a11fffb7677849f Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 6 May 2014 12:53:12 +0200 Subject: [PATCH 22/35] WEB-10560 Debugger: second Mute Breakpoints invocation doesn't work --- .../backend/src/org/jetbrains/debugger/BreakpointBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/BreakpointBase.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/BreakpointBase.java index 90974e03e594..2335b0973c26 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/BreakpointBase.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/BreakpointBase.java @@ -78,7 +78,7 @@ public abstract class BreakpointBase extends Breakpoint { return this; } enabled = value; - dirty = true; + dirty = true; return this; } From 09f502992b62650d3e89ceb86f2f7968b7b0ff4c Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 5 May 2014 17:37:56 +0400 Subject: [PATCH 23/35] [log] Fail safer if no refs were found at some head commit Returning a NullVirtualFile won't help, because it just fails later in the DataGetter in attempt to load commit details from the VCS. Returning the first root is better: it will suit in most cases (one-repo case), although it can easily fail in multi-repo case. --- .../src/com/intellij/vcs/log/ui/VcsLogColorManagerImpl.java | 4 ---- .../intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java | 2 -- .../src/com/intellij/vcs/log/ui/tables/EmptyTableModel.java | 4 ++-- .../src/com/intellij/vcs/log/ui/tables/GraphTableModel.java | 3 ++- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogColorManagerImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogColorManagerImpl.java index 8f674e6f7f9d..decc60c9c587 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogColorManagerImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogColorManagerImpl.java @@ -5,7 +5,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.JBColor; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; -import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel; import org.jetbrains.annotations.NotNull; import java.awt.*; @@ -60,9 +59,6 @@ public class VcsLogColorManagerImpl implements VcsLogColorManager { @NotNull @Override public Color getRootColor(@NotNull VirtualFile root) { - if (root == AbstractVcsLogTableModel.FAKE_ROOT) { - return getDefaultRootColor(); - } Color color = myRoots2Colors.get(root); if (color == null) { LOG.error("No color record for root " + root + ". All roots: " + myRoots2Colors); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java index d18c645f4ed7..262fefbbc212 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java @@ -23,8 +23,6 @@ import java.util.concurrent.atomic.AtomicBoolean; public abstract class AbstractVcsLogTableModel extends AbstractTableModel { - public static final VirtualFile FAKE_ROOT = NullVirtualFile.INSTANCE; - public static final int ROOT_COLUMN = 0; public static final int COMMIT_COLUMN = 1; public static final int AUTHOR_COLUMN = 2; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/EmptyTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/EmptyTableModel.java index ec8528e092f1..575be9e5e183 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/EmptyTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/EmptyTableModel.java @@ -22,8 +22,8 @@ import com.intellij.vcs.log.VcsShortCommitDetails; import com.intellij.vcs.log.data.DataPack; import com.intellij.vcs.log.data.LoadMoreStage; import com.intellij.vcs.log.data.VcsLogDataHolder; -import com.intellij.vcs.log.ui.render.GraphCommitCell; import com.intellij.vcs.log.ui.VcsLogUiImpl; +import com.intellij.vcs.log.ui.render.GraphCommitCell; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -44,7 +44,7 @@ public class EmptyTableModel extends AbstractVcsLogTableModel { @NotNull @Override public VirtualFile getRoot(int rowIndex) { - return FAKE_ROOT; + throw new AssertionError("Root shouldn't be requested for empty table model. row: " + rowIndex); } @NotNull diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java index 2438acec675c..63320a63404b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java @@ -61,7 +61,8 @@ public class GraphTableModel extends AbstractVcsLogTableModel { Collection refs = myDataPack.getRefsModel().refsToCommit(head); if (refs.isEmpty()) { LOG.error("No references pointing to head " + head + " identified for commit at row " + rowIndex); - return FAKE_ROOT; + // take the first root: it is the right choice in one-repo case, though it will likely fail in multi-repo case + return myDataPack.getLogProviders().keySet().iterator().next(); } return refs.iterator().next().getRoot(); } From 95468ea05158b7b072e8e1b16023ffb745300d6e Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 5 May 2014 18:31:52 +0400 Subject: [PATCH 24/35] [log] Don't report the error too often --- .../vcs/log/graph/GraphColorManagerImpl.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java index d53a8fdc703a..851e1c57cf1a 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java @@ -20,6 +20,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.JBColor; import com.intellij.util.NotNullFunction; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.hash.LinkedHashMap; import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsLogRefManager; import com.intellij.vcs.log.VcsRef; @@ -39,6 +40,14 @@ public class GraphColorManagerImpl implements GraphColorManager { @NotNull private final NotNullFunction myHashGetter; @NotNull private final Map myRefManagers; + @NotNull private final LinkedHashMap myErrorWasReported = new LinkedHashMap(10) { + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > 100; + } + }; + public GraphColorManagerImpl(@NotNull RefsModel refsModel, @NotNull NotNullFunction hashGetter, @NotNull Map refManagers) { myRefsModel = refsModel; @@ -61,7 +70,10 @@ public class GraphColorManagerImpl implements GraphColorManager { private boolean checkEmptiness(@NotNull Collection refs, int head) { if (refs.isEmpty()) { - LOG.error("No references found at head " + head + " which corresponds to hash " + myHashGetter.fun(head)); + if (!myErrorWasReported.containsKey(head)) { + myErrorWasReported.put(head, head); + LOG.error("No references found at head " + head + " which corresponds to hash " + myHashGetter.fun(head)); + } return false; } return true; From 172a3f9675076d4a89f566e27a922dfa31c2a0be Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 5 May 2014 16:24:00 +0400 Subject: [PATCH 25/35] [git] Don't log error in case of empty config file - it is allowed --- plugins/git4idea/src/git4idea/repo/GitConfig.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/repo/GitConfig.java b/plugins/git4idea/src/git4idea/repo/GitConfig.java index 0080bf613583..a88e7754b78e 100644 --- a/plugins/git4idea/src/git4idea/repo/GitConfig.java +++ b/plugins/git4idea/src/git4idea/repo/GitConfig.java @@ -135,6 +135,13 @@ public class GitConfig { */ @NotNull static GitConfig read(@NotNull GitPlatformFacade platformFacade, @NotNull File configFile) { + GitConfig emptyConfig = new GitConfig(Collections.emptyList(), Collections.emptyList(), + Collections.emptyList()); + if (!configFile.exists()) { + LOG.info("No .git/config file at " + configFile.getPath()); + return emptyConfig; + } + Ini ini = new Ini(); ini.getConfig().setMultiOption(true); // duplicate keys (e.g. url in [remote]) ini.getConfig().setTree(false); // don't need tree structure: it corrupts url in section name (e.g. [url "http://github.com/"] @@ -143,7 +150,7 @@ public class GitConfig { } catch (IOException e) { LOG.error(new RepoStateException("Couldn't load .git/config file at " + configFile.getPath(), e)); - return new GitConfig(Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); + return emptyConfig; } IdeaPluginDescriptor plugin = platformFacade.getPluginByClassName(GitConfig.class.getName()); From 899e7e343404c151da486e1c66b25f338c7790e8 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 5 May 2014 16:13:31 +0400 Subject: [PATCH 26/35] [git] IDEA-124052 Support remote refs w/o a correspondent remote + test --- .../src/git4idea/branch/GitBranchUtil.java | 8 ++++--- .../git4idea/src/git4idea/repo/GitRemote.java | 12 +++++----- .../repo/GitRepositoryReaderNewTest.java | 24 +++++++++++++++++++ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java b/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java index a41a1727f48f..6e178b9cbc0f 100644 --- a/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java +++ b/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java @@ -228,7 +228,11 @@ public class GitBranchUtil { String branchName = stdName.substring(slash + 1); GitRemote remote = findRemoteByName(remoteName, remotes); if (remote == null) { - return null; + // user may remove the remote section from .git/config, but leave remote refs untouched in .git/refs/remotes + LOG.info(String.format("No remote found with the name [%s]. All remotes: %s", remoteName, remotes)); + GitRemote fakeRemote = new GitRemote(remoteName, ContainerUtil.emptyList(), Collections.emptyList(), + Collections.emptyList(), Collections.emptyList()); + return new GitStandardRemoteBranch(fakeRemote, branchName, hash); } return new GitStandardRemoteBranch(remote, branchName, hash); } @@ -241,8 +245,6 @@ public class GitBranchUtil { return remote; } } - // user may remove the remote section from .git/config, but leave remote refs untouched in .git/refs/remotes - LOG.info(String.format("No remote found with the name [%s]. All remotes: %s", remoteName, remotes)); return null; } diff --git a/plugins/git4idea/src/git4idea/repo/GitRemote.java b/plugins/git4idea/src/git4idea/repo/GitRemote.java index a0695d281bd7..b2e289ce7d40 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRemote.java +++ b/plugins/git4idea/src/git4idea/repo/GitRemote.java @@ -39,7 +39,7 @@ import java.util.List; *

*

* GitRemote instance constructed by {@link GitConfig#read(GitPlatformFacade, File)}} has all these rules applied. - * Thus, for example, if only one {@code url} and no {@code pushUrls} are defined for the remote, + * Thus, for example, if only one {@code url} and no {@code pushUrls} are defined for the remote, * both {@link #getUrls()} and {@link #getPushUrls()} will return this url.
* This is made to avoid urls transformation logic from the code using GitRemote, leaving it all in GitConfig parsing. *

@@ -47,14 +47,14 @@ import java.util.List; * Same applies to fetch and push specs: {@link #getPushRefSpecs()} returns the spec, * even if there are no separate record in {@code .git/config} *

- * + * *

* NB: Not all remote preferences (defined in {@code .git/config} are stored in the object. * If some additional data is needed, add the field, getter, constructor parameter and populate it in {@link GitConfig}. *

- * + * *

Remotes are compared (via equals, hashcode and compareTo) only by names.

- * + * * @author Kirill Likhodedov */ public final class GitRemote implements Comparable { @@ -80,8 +80,8 @@ public final class GitRemote implements Comparable { @NotNull final List myFetchRefSpecs; @NotNull private final List myPushRefSpecs; - GitRemote(@NotNull String name, @NotNull List urls, @NotNull Collection pushUrls, - @NotNull List fetchRefSpecs, @NotNull List pushRefSpecs) { + public GitRemote(@NotNull String name, @NotNull List urls, @NotNull Collection pushUrls, + @NotNull List fetchRefSpecs, @NotNull List pushRefSpecs) { myName = name; myUrls = urls; myPushUrls = pushUrls; diff --git a/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderNewTest.java b/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderNewTest.java index 89f382806658..9570cbdc06fe 100644 --- a/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderNewTest.java +++ b/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderNewTest.java @@ -16,10 +16,14 @@ package git4idea.repo; import com.intellij.dvcs.repo.Repository; +import com.intellij.openapi.util.Condition; +import com.intellij.util.containers.ContainerUtil; import git4idea.GitLocalBranch; +import git4idea.GitRemoteBranch; import git4idea.test.GitSingleRepoTest; import java.io.File; +import java.util.Collection; import static git4idea.test.GitExecutor.git; import static git4idea.test.GitScenarios.commit; @@ -46,4 +50,24 @@ public class GitRepositoryReaderNewTest extends GitSingleRepoTest { assertEquals("State value is incorrect", Repository.State.REBASING, state); } + // inspired by IDEA-124052 + public void test_remote_reference_without_remote() { + final String INVALID_REMOTE = "invalid-remote"; + final String INVALID_REMOTE_BRANCH = "master"; + git("update-ref refs/remotes/" + INVALID_REMOTE + "/" + INVALID_REMOTE_BRANCH + " HEAD"); + + File gitDir = new File(myRepo.getRoot().getPath(), ".git"); + GitRepositoryReader reader = new GitRepositoryReader(gitDir); + GitConfig config = GitConfig.read(myPlatformFacade, new File(gitDir, "config")); + Collection remotes = config.parseRemotes(); + + Collection remoteBranches = reader.readBranches(remotes).getRemoteBranches(); + assertTrue("Remote branch not found", ContainerUtil.exists(remoteBranches, new Condition() { + @Override + public boolean value(GitRemoteBranch branch) { + return branch.getNameForLocalOperations().equals(INVALID_REMOTE + "/" + INVALID_REMOTE_BRANCH); + } + })); + } + } From 609426440d2382bf932dc6c77ec5b33ff02d61b1 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 6 May 2014 13:23:01 +0400 Subject: [PATCH 27/35] Cleanup (unneeded interface) --- .../openapi/vfs/impl/jar/JarFileSystemImpl.java | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java index e86ea895cd9b..6c7f26d6ecea 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java @@ -18,7 +18,6 @@ package com.intellij.openapi.vfs.impl.jar; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileAttributes; import com.intellij.openapi.util.io.FileUtil; @@ -44,7 +43,7 @@ import java.util.List; import java.util.Map; import java.util.Set; -public class JarFileSystemImpl extends JarFileSystem implements ApplicationComponent { +public class JarFileSystemImpl extends JarFileSystem { private static final class JarFileSystemImplLock { } private static final JarFileSystemImplLock LOCK = new JarFileSystemImplLock(); @@ -125,18 +124,6 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo return null; } - @Override - @NotNull - public String getComponentName() { - return "JarFileSystem"; - } - - @Override - public void initComponent() { } - - @Override - public void disposeComponent() { } - @Override public void setNoCopyJarForPath(String pathInJar) { if (myNoCopyJarPaths == null || pathInJar == null) return; From 32ae79905cb025f6bc213a925f1f4e58e9d6b8f7 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Tue, 6 May 2014 15:53:25 +0400 Subject: [PATCH 28/35] IDEA-123956 Anonymous class formatting moves all args to the next line [CR-IC-5212] --- .../psi/formatter/java/AbstractJavaBlock.java | 19 ++++++++------ .../psi/formatter/java/JavaFormatterTest.java | 5 ++-- .../formatter/java/JavaFormatterWrapTest.java | 25 +++++++++++++++---- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java index b1d4c675d8b2..bcd6ac6cd602 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java @@ -480,7 +480,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo if (nodeType == JavaElementType.POLYADIC_EXPRESSION) nodeType = JavaElementType.BINARY_EXPRESSION; if (childType == JavaTokenType.LBRACE && nodeType == JavaElementType.ARRAY_INITIALIZER_EXPRESSION) { - final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.ARRAY_INITIALIZER_WRAP), false); + final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.ARRAY_INITIALIZER_WRAP), true); child = processParenthesisBlock(JavaTokenType.LBRACE, JavaTokenType.RBRACE, result, child, @@ -488,7 +488,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo mySettings.ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION); } else if (childType == JavaTokenType.LBRACE && nodeType == JavaElementType.ANNOTATION_ARRAY_INITIALIZER) { - final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.ARRAY_INITIALIZER_WRAP), false); + final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.ARRAY_INITIALIZER_WRAP), true); child = processParenthesisBlock(JavaTokenType.LBRACE, JavaTokenType.RBRACE, result, child, @@ -496,7 +496,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo mySettings.ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION); } else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.EXPRESSION_LIST) { - final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.CALL_PARAMETERS_WRAP), false); + final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.CALL_PARAMETERS_WRAP), true); if (mySettings.PREFER_PARAMETERS_WRAP) { wrap.ignoreParentWraps(); } @@ -507,19 +507,19 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.PARAMETER_LIST) { // There is a possible case that particular annotated method definition is too long. We may wrap either after annotation // or after opening lbrace then. Our strategy is to wrap after annotation whenever possible. - Wrap wrap = Wrap.createWrap(getWrapType(mySettings.METHOD_PARAMETERS_WRAP), false); + Wrap wrap = Wrap.createWrap(getWrapType(mySettings.METHOD_PARAMETERS_WRAP), true); child = processParenthesisBlock(result, child, WrappingStrategy.createDoNotWrapCommaStrategy(wrap), mySettings.ALIGN_MULTILINE_PARAMETERS); } else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.RESOURCE_LIST) { - Wrap wrap = Wrap.createWrap(getWrapType(mySettings.RESOURCE_LIST_WRAP), false); + Wrap wrap = Wrap.createWrap(getWrapType(mySettings.RESOURCE_LIST_WRAP), true); child = processParenthesisBlock(result, child, WrappingStrategy.createDoNotWrapCommaStrategy(wrap), mySettings.ALIGN_MULTILINE_RESOURCES); } else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.ANNOTATION_PARAMETER_LIST) { - Wrap wrap = Wrap.createWrap(getWrapType(mySettings.CALL_PARAMETERS_WRAP), false); + Wrap wrap = Wrap.createWrap(getWrapType(mySettings.CALL_PARAMETERS_WRAP), true); child = processParenthesisBlock(result, child, WrappingStrategy.createDoNotWrapCommaStrategy(wrap), mySettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS); @@ -915,6 +915,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo ASTNode prev = child; boolean afterAnonymousClass = false; final boolean enforceIndent = shouldEnforceIndentToChildren(); + boolean currentChildIsFirstToWrap = true; while (child != null) { isAfterIncomplete = isAfterIncomplete || child.getElementType() == TokenType.ERROR_ELEMENT || child.getElementType() == JavaElementType.EMPTY_EXPRESSION; @@ -934,7 +935,11 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo final IElementType elementType = child.getElementType(); Indent indentToUse = enforceIndent ? internalIndentEnforcedToChildren : internalIndent; AlignmentStrategy alignmentStrategyToUse = canUseAnonymousClassAlignment(child) ? anonymousClassStrategy : alignmentStrategy; - processChild(result, child, alignmentStrategyToUse.getAlignment(elementType), wrappingStrategy.getWrap(elementType), indentToUse); + + Wrap wrap = currentChildIsFirstToWrap ? Wrap.createWrap(WrapType.NONE, true) : wrappingStrategy.getWrap(elementType); + currentChildIsFirstToWrap = false; + processChild(result, child, alignmentStrategyToUse.getAlignment(elementType), wrap, indentToUse); + if (to == null) {//process only one statement return child; } diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java index c00db0fc77ad..09cba9382896 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java @@ -931,13 +931,12 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest { getSettings().getRootSettings().RIGHT_MARGIN = 20; getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED; doTextTest("class Foo {\n" + " void foo() {\n" + " fooFooFooFoo(1);" + " }\n" + "}", - "class Foo {\n" + " void foo() {\n" + " fooFooFooFoo(\n" + " 1);\n" + " }\n" + "}"); + "class Foo {\n" + " void foo() {\n" + " fooFooFooFoo(1);\n" + " }\n" + "}"); getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM; doTextTest("class Foo {\n" + " void foo() {\n" + " fooFooFooFoo(1,2);" + " }\n" + "}", "class Foo {\n" + " void foo() {\n" + - " fooFooFooFoo(\n" + - " 1,\n" + + " fooFooFooFoo(1,\n" + " 2);\n" + " }\n" + "}"); diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java index 512a7ef3c158..ab4a73af30bc 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java @@ -47,8 +47,7 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest { "class Foo {\n" + "}", - "@AttributeOverrides({\n" + - " @AttributeOverride(name = \"id\", column = @Column(name = \"recovery_id\")),\n" + + "@AttributeOverrides({@AttributeOverride(name = \"id\", column = @Column(name = \"recovery_id\")),\n" + " @AttributeOverride(name = \"transactionReference\", column = @Column(name = \"deal_reference\")),\n" + " @AttributeOverride(name = \"eventDate\", column = @Column(name = \"recovery_date\")),\n" + " @AttributeOverride(name = \"amount\", column = @Column(name = \"recovery_amount\")),\n" + @@ -391,9 +390,8 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest { String literal = "\"" + StringUtil.repeatSymbol('A', 128) + "\""; before = "processingEnv.getMessenger().printMessage(Diagnostic.Kind.ERROR, call(" + literal + "));\n"; after = "processingEnv.getMessenger().printMessage(\n" + - " Diagnostic.Kind.ERROR, call(\n" + - " " + literal + "\n" + - " )\n" + + " Diagnostic.Kind.ERROR,\n" + + " call(" + literal + ")\n" + ");\n"; doMethodTest(before, after); @@ -448,4 +446,21 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest { " public @TA String m();\n" + "}"); } + + public void testIDEA123956() { + doMethodTest( + "final BaseAnalysisActionDialog dialog = new BaseAnalysisActionDialog(" + + "AnalysisScopeBundle.message(\"specify.analysis.scope\", InspectionsBundle.message(\"inspection.action.title\")),\n" + + " AnalysisScopeBundle.message(\"analysis.scope.title\", InspectionsBundle.message(\"inspection.action.noun\")),\n" + + " project, analysisScope, module != null ? module.getName() : null,\n" + + " true, AnalysisUIOptions.getInstance(project), psiElement) {\n" + + "}", + "final BaseAnalysisActionDialog dialog = new BaseAnalysisActionDialog(" + + "AnalysisScopeBundle.message(\"specify.analysis.scope\", InspectionsBundle.message(\"inspection.action.title\")),\n" + + " AnalysisScopeBundle.message(\"analysis.scope.title\", InspectionsBundle.message(\"inspection.action.noun\")),\n" + + " project, analysisScope, module != null ? module.getName() : null,\n" + + " true, AnalysisUIOptions.getInstance(project), psiElement) {\n" + + "}" + ); + } } From 85f28232ffc9a58c674b64521785c0464936ebd2 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 6 May 2014 13:52:09 +0200 Subject: [PATCH 29/35] remove alarm. Make SE faster --- .../ide/actions/SearchEverywhereAction.java | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java index 6e4994bb846f..30e1bac9316d 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java @@ -424,16 +424,9 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA @Override protected void textChanged(DocumentEvent e) { final String pattern = editor.getText(); - final int len = pattern.trim().length(); - myAlarm.cancelAllRequests(); - myAlarm.addRequest(new Runnable() { - @Override - public void run() { - if (editor.hasFocus()) { - rebuildList(pattern); - } - } - }, len == 1 ? 400 : len == 2 ? 300 : len == 3 ? 250 : 30); + if (editor.hasFocus()) { + rebuildList(pattern); + } } }); editor.addFocusListener(new FocusAdapter() { @@ -1019,7 +1012,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA final int width = myMainPanel.getPreferredSize().width; if (width > myPopupActualWidth) { myPopupActualWidth = width; - schedulePopupUpdate(); + //schedulePopupUpdate(); } return myMainPanel; } From a32723b041c683a0197bc8f6e055fce12a5ee81d Mon Sep 17 00:00:00 2001 From: Andrey Starovoyt Date: Tue, 6 May 2014 16:09:43 +0400 Subject: [PATCH 30/35] postfix template description inspection + tests --- plugins/devkit/resources/META-INF/plugin.xml | 7 + .../PostfixTemplateDescriptionNotFound.html | 5 + plugins/devkit/src/DevKitBundle.properties | 3 + .../DescriptionNotFoundInspectionBase.java | 135 ++++++++++++++++ ...ntentionDescriptionNotFoundInspection.java | 112 +++---------- ...TemplateDescriptionNotFoundInspection.java | 86 ++++++++++ .../quickfix/CreateHtmlDescriptionFix.java | 149 ++++++++++-------- ...eatePostfixTemplateHtmlDescriptionFix.java | 39 +++++ .../postfixTemplates/MyQuickFixTemplate.java | 6 + .../postfixTemplates/MyTemplate.java | 6 + .../MyTemplateWithDescription.java | 6 + .../MyTemplateWithoutBeforeAfter.java | 6 + .../after.java.template | 1 + .../before.java.template | 1 + .../description.html | 1 + .../description.html | 1 + .../PostfixTemplateInspectionTest.java | 61 +++++++ 17 files changed, 471 insertions(+), 154 deletions(-) create mode 100644 plugins/devkit/resources/inspectionDescriptions/PostfixTemplateDescriptionNotFound.html create mode 100644 plugins/devkit/src/inspections/DescriptionNotFoundInspectionBase.java create mode 100644 plugins/devkit/src/inspections/PostfixTemplateDescriptionNotFoundInspection.java create mode 100644 plugins/devkit/src/inspections/quickfix/CreatePostfixTemplateHtmlDescriptionFix.java create mode 100644 plugins/devkit/testData/codeInsight/postfixTemplates/MyQuickFixTemplate.java create mode 100644 plugins/devkit/testData/codeInsight/postfixTemplates/MyTemplate.java create mode 100644 plugins/devkit/testData/codeInsight/postfixTemplates/MyTemplateWithDescription.java create mode 100644 plugins/devkit/testData/codeInsight/postfixTemplates/MyTemplateWithoutBeforeAfter.java create mode 100644 plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithDescription/after.java.template create mode 100644 plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithDescription/before.java.template create mode 100644 plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithDescription/description.html create mode 100644 plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithoutBeforeAfter/description.html create mode 100644 plugins/devkit/testSources/codeInsight/PostfixTemplateInspectionTest.java diff --git a/plugins/devkit/resources/META-INF/plugin.xml b/plugins/devkit/resources/META-INF/plugin.xml index b05c49186f4f..d0d12d3744f7 100644 --- a/plugins/devkit/resources/META-INF/plugin.xml +++ b/plugins/devkit/resources/META-INF/plugin.xml @@ -66,6 +66,13 @@ bundle="org.jetbrains.idea.devkit.DevKitBundle" groupKey="inspections.group.name" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.idea.devkit.inspections.IntentionDescriptionNotFoundInspection"/> + + +Checks if postfix template (completion) has a description. + + diff --git a/plugins/devkit/src/DevKitBundle.properties b/plugins/devkit/src/DevKitBundle.properties index 07d3b2914baf..6799f6d2415f 100644 --- a/plugins/devkit/src/DevKitBundle.properties +++ b/plugins/devkit/src/DevKitBundle.properties @@ -147,6 +147,9 @@ inspections.component.not.registered.option.ignore.non.public=Ignore non-public inspections.component.not.registered.quickfix.family=Register Component inspections.component.not.registered.quickfix.name=Register {0} inspections.component.not.registered.quickfix.error=Cannot Register {0} + +inspections.component.postfix.template.not.found.description.name=Postfix template Description Checker + InspectionUseGrayColor=Use Gray ant.build.jar.comment=Build archive for plugin ''{0}'' ant.build.jar.description=Build plugin archive for module ''{0}'' diff --git a/plugins/devkit/src/inspections/DescriptionNotFoundInspectionBase.java b/plugins/devkit/src/inspections/DescriptionNotFoundInspectionBase.java new file mode 100644 index 000000000000..d1a2fac52685 --- /dev/null +++ b/plugins/devkit/src/inspections/DescriptionNotFoundInspectionBase.java @@ -0,0 +1,135 @@ +/* + * 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.jetbrains.idea.devkit.inspections; + + +import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.devkit.inspections.quickfix.CreateHtmlDescriptionFix; +import org.jetbrains.idea.devkit.util.PsiUtil; + +abstract class DescriptionNotFoundInspectionBase extends DevKitInspectionBase { + + @Override + public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) { + final Project project = aClass.getProject(); + final PsiIdentifier nameIdentifier = aClass.getNameIdentifier(); + final Module module = ModuleUtilCore.findModuleForPsiElement(aClass); + + if (nameIdentifier == null || module == null || !PsiUtil.isInstantiable(aClass)) return null; + + final PsiClass base = JavaPsiFacade.getInstance(project).findClass(getClassName(), GlobalSearchScope.allScope(project)); + + if (base == null || !aClass.isInheritor(base, true)) return null; + + String descriptionDir = getDescriptionDirName(aClass); + if (StringUtil.isEmptyOrSpaces(descriptionDir)) { + return null; + } + + for (PsiDirectory description : getDescriptionsDirs(module)) { + PsiDirectory dir = description.findSubdirectory(descriptionDir); + if (dir == null) continue; + final PsiFile descr = dir.findFile("description.html"); + if (descr != null) { + if (!hasBeforeAndAfterTemplate(dir.getVirtualFile())) { + PsiElement problem = aClass.getNameIdentifier(); + ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(problem == null ? nameIdentifier : problem, + getHasNotBeforeAfterError(), + isOnTheFly, + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false); + return new ProblemDescriptor[]{problemDescriptor}; + } + + return null; + } + } + + + final PsiElement problem = aClass.getNameIdentifier(); + final ProblemDescriptor problemDescriptor = manager + .createProblemDescriptor(problem == null ? nameIdentifier : problem, + getHasNotDescriptionError(), isOnTheFly, new LocalQuickFix[]{getFix(module, descriptionDir)}, + ProblemHighlightType.GENERIC_ERROR_OR_WARNING); + return new ProblemDescriptor[]{problemDescriptor}; + } + + protected CreateHtmlDescriptionFix getFix(Module module, String descriptionDir) { + return new CreateHtmlDescriptionFix(descriptionDir, module, true); + } + + @Nullable + private static String getDescriptionDirName(PsiClass aClass) { + String descriptionDir = ""; + PsiClass each = aClass; + while (each != null) { + String name = each.getName(); + if (StringUtil.isEmptyOrSpaces(name)) { + return null; + } + descriptionDir = name + descriptionDir; + each = each.getContainingClass(); + } + return descriptionDir; + } + + private static boolean hasBeforeAndAfterTemplate(@NotNull VirtualFile dir) { + boolean hasBefore = false; + boolean hasAfter = false; + + for (VirtualFile file : dir.getChildren()) { + String name = file.getName(); + if (name.endsWith(".template")) { + if (name.startsWith("before.")) { + hasBefore = true; + } + else if (name.startsWith("after.")) { + hasAfter = true; + } + } + } + + return hasBefore && hasAfter; + } + + @Override + public boolean isEnabledByDefault() { + return true; + } + + @NotNull + protected abstract String getClassName(); + + @NotNull + protected abstract String getHasNotDescriptionError(); + + @NotNull + protected abstract String getHasNotBeforeAfterError(); + + @NotNull + protected abstract PsiDirectory[] getDescriptionsDirs(@NotNull Module module); +} diff --git a/plugins/devkit/src/inspections/IntentionDescriptionNotFoundInspection.java b/plugins/devkit/src/inspections/IntentionDescriptionNotFoundInspection.java index e424c70f1106..bed14c0092a7 100644 --- a/plugins/devkit/src/inspections/IntentionDescriptionNotFoundInspection.java +++ b/plugins/devkit/src/inspections/IntentionDescriptionNotFoundInspection.java @@ -15,118 +15,57 @@ */ package org.jetbrains.idea.devkit.inspections; -import com.intellij.codeInspection.InspectionManager; -import com.intellij.codeInspection.LocalQuickFix; -import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtil; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiPackage; import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.devkit.inspections.quickfix.CreateHtmlDescriptionFix; -import org.jetbrains.idea.devkit.util.PsiUtil; /** * @author Konstantin Bulenkov */ -public class IntentionDescriptionNotFoundInspection extends DevKitInspectionBase{ +public class IntentionDescriptionNotFoundInspection extends DescriptionNotFoundInspectionBase { @NonNls private static final String INTENTION = "com.intellij.codeInsight.intention.IntentionAction"; @NonNls private static final String INSPECTION_DESCRIPTIONS = "intentionDescriptions"; - @Override - public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) { - final Project project = aClass.getProject(); - final PsiIdentifier nameIdentifier = aClass.getNameIdentifier(); - final Module module = ModuleUtil.findModuleForPsiElement(aClass); - - if (nameIdentifier == null || module == null || !PsiUtil.isInstantiable(aClass)) return null; - - final PsiClass base = JavaPsiFacade.getInstance(project).findClass(INTENTION, GlobalSearchScope.allScope(project)); - - if (base == null || ! aClass.isInheritor(base, true)) return null; - - String descriptionDir = getDescriptionDirName(aClass); - if (StringUtil.isEmptyOrSpaces(descriptionDir)) { - return null; - } - - for (PsiDirectory description : getIntentionDescriptionsDirs(module)) { - PsiDirectory dir = description.findSubdirectory(descriptionDir); - if (dir == null) continue; - final PsiFile descr = dir.findFile("description.html"); - if (descr != null) { - if (!hasBeforeAndAfterTemplate(dir.getVirtualFile())) { - PsiElement problem = aClass.getNameIdentifier(); - ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(problem == null ? nameIdentifier : problem, - "Intention must have 'before.*.template' and 'after.*.template' beside 'description.html'", - isOnTheFly, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false); - return new ProblemDescriptor[]{problemDescriptor}; - } - - return null; - } - } - - - final PsiElement problem = aClass.getNameIdentifier(); - final ProblemDescriptor problemDescriptor = manager - .createProblemDescriptor(problem == null ? nameIdentifier : problem, - "Intention does not have a description", isOnTheFly, new LocalQuickFix[]{new CreateHtmlDescriptionFix(descriptionDir, module, true)}, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING); - return new ProblemDescriptor[]{problemDescriptor}; + protected CreateHtmlDescriptionFix getFix(Module module, String descriptionDir) { + return new CreateHtmlDescriptionFix(descriptionDir, module, true); } - @Nullable - private static String getDescriptionDirName(PsiClass aClass) { - String descriptionDir = ""; - PsiClass each = aClass; - while (each != null) { - String name = each.getName(); - if (StringUtil.isEmptyOrSpaces(name)) { - return null; - } - descriptionDir = name + descriptionDir; - each = each.getContainingClass(); - } - return descriptionDir; + @NotNull + protected String getClassName() { + return INTENTION; } - private static boolean hasBeforeAndAfterTemplate(@NotNull VirtualFile dir) { - boolean hasBefore = false; - boolean hasAfter = false; + @NotNull + protected String getHasNotDescriptionError() { + return "Intention does not have a description"; + } - for (VirtualFile file : dir.getChildren()) { - String name = file.getName(); - if (name.endsWith(".template")) { - if (name.startsWith("before.")) { - hasBefore = true; - } - else if (name.startsWith("after.")) { - hasAfter = true; - } - } - } - - return hasBefore && hasAfter; + @NotNull + protected String getHasNotBeforeAfterError() { + return "Intention must have 'before.*.template' and 'after.*.template' beside 'description.html'"; } public static PsiDirectory[] getIntentionDescriptionsDirs(Module module) { final PsiPackage aPackage = JavaPsiFacade.getInstance(module.getProject()).findPackage(INSPECTION_DESCRIPTIONS); if (aPackage != null) { return aPackage.getDirectories(GlobalSearchScope.moduleWithDependenciesScope(module)); - } else { + } + else { return PsiDirectory.EMPTY_ARRAY; } } + @NotNull + protected PsiDirectory[] getDescriptionsDirs(@NotNull Module module) { + return getIntentionDescriptionsDirs(module); + } + @Nls @NotNull public String getDisplayName() { @@ -137,9 +76,4 @@ public class IntentionDescriptionNotFoundInspection extends DevKitInspectionBase public String getShortName() { return "IntentionDescriptionNotFoundInspection"; } - - @Override - public boolean isEnabledByDefault() { - return true; - } } diff --git a/plugins/devkit/src/inspections/PostfixTemplateDescriptionNotFoundInspection.java b/plugins/devkit/src/inspections/PostfixTemplateDescriptionNotFoundInspection.java new file mode 100644 index 000000000000..b839c873df9b --- /dev/null +++ b/plugins/devkit/src/inspections/PostfixTemplateDescriptionNotFoundInspection.java @@ -0,0 +1,86 @@ +/* + * 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.jetbrains.idea.devkit.inspections; + +import com.intellij.openapi.module.Module; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiPackage; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.devkit.DevKitBundle; +import org.jetbrains.idea.devkit.inspections.quickfix.CreateHtmlDescriptionFix; +import org.jetbrains.idea.devkit.inspections.quickfix.CreatePostfixTemplateHtmlDescriptionFix; + + +public class PostfixTemplateDescriptionNotFoundInspection extends DescriptionNotFoundInspectionBase { + + private static final String POSTFIX_TEMPLATES = "postfixTemplates"; + + @NotNull + @Override + protected PsiDirectory[] getDescriptionsDirs(@NotNull Module module) { + return getPostfixTemplateDirectories(module); + } + + @Override + protected CreateHtmlDescriptionFix getFix(Module module, String descriptionDir) { + return new CreatePostfixTemplateHtmlDescriptionFix(descriptionDir, module); + } + + @NotNull + public static PsiDirectory[] getPostfixTemplateDirectories(Module module) { + final PsiPackage aPackage = JavaPsiFacade.getInstance(module.getProject()).findPackage(POSTFIX_TEMPLATES); + if (aPackage != null) { + return aPackage.getDirectories(GlobalSearchScope.moduleWithDependenciesScope(module)); + } + else { + return PsiDirectory.EMPTY_ARRAY; + } + } + + @NotNull + @Override + protected String getHasNotDescriptionError() { + return "Postfix template does not have a description"; + } + + @NotNull + @Override + protected String getHasNotBeforeAfterError() { + return "Postfix template must have 'before.*.template' and 'after.*.template' beside 'description.html'"; + } + + @NotNull + @Override + protected String getClassName() { + return "com.intellij.codeInsight.template.postfix.templates.PostfixTemplate"; + } + + @Nls + @NotNull + @Override + public String getDisplayName() { + return DevKitBundle.message("inspections.component.postfix.template.not.found.description.name"); + } + + @NotNull + @Override + public String getShortName() { + return "PostfixTemplateDescriptionNotFound"; + } +} diff --git a/plugins/devkit/src/inspections/quickfix/CreateHtmlDescriptionFix.java b/plugins/devkit/src/inspections/quickfix/CreateHtmlDescriptionFix.java index e8f498dd28ea..6dcd46c99254 100644 --- a/plugins/devkit/src/inspections/quickfix/CreateHtmlDescriptionFix.java +++ b/plugins/devkit/src/inspections/quickfix/CreateHtmlDescriptionFix.java @@ -57,75 +57,15 @@ import java.util.List; * @author Konstantin Bulenkov */ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable { - private final String myFilename; - private final Module myModule; @NonNls private static final String TEMPLATE_NAME = "InspectionDescription.html"; + private final String myFilename; + protected final Module myModule; private final boolean isIntention; public CreateHtmlDescriptionFix(String filename, Module module, boolean isIntention) { myModule = module; this.isIntention = isIntention; - myFilename = isIntention ? filename : filename + ".html"; - } - - @NotNull - public String getName() { - return DevKitBundle.message("create.description.file"); - } - - @NotNull - public String getFamilyName() { - return "DevKit"; - } - - public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - final PsiDirectory[] dirs; - if (isIntention) { - dirs = IntentionDescriptionNotFoundInspection.getIntentionDescriptionsDirs(myModule); - } - else { - dirs = InspectionDescriptionNotFoundInspection.getInspectionDescriptionsDirs(myModule); - } - final List virtualFiles = getPotentialRoots(myModule, dirs); - final VirtualFile[] roots = prepare(VfsUtil.toVirtualFileArray(virtualFiles)); - if (roots.length == 1) { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - createDescription(roots[0]); - } - }); - - } - else { - List options = new ArrayList(); - for (VirtualFile file : roots) { - String path = file.getPresentableUrl() + File.separator + getDescriptionFolderName() + File.separator + myFilename; - if (isIntention) { - path += File.separator + "description.html"; - } - options.add(path); - } - final JBList files = new JBList(ArrayUtil.toStringArray(options)); - files.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - final JBPopup popup = JBPopupFactory.getInstance() - .createListPopupBuilder(files) - .setTitle(DevKitBundle.message("select.target.location.of.description", myFilename)) - .setItemChoosenCallback(new Runnable() { - public void run() { - final int index = files.getSelectedIndex(); - if (0 <= index && index < roots.length) { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - createDescription(roots[index]); - } - }); - } - } - }).createPopup(); - final Editor editor = FileEditorManager.getInstance(myModule.getProject()).getSelectedTextEditor(); - if (editor == null) return; - popup.showInBestPositionFor(editor); - } + myFilename = getNormalizedFileName(filename); } private static List getPotentialRoots(Module module, PsiDirectory[] dirs) { @@ -147,6 +87,80 @@ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable { } } + private String getNormalizedFileName(String filename) { + return isIntention ? filename : filename + ".html"; + } + + @NotNull + public String getName() { + return DevKitBundle.message("create.description.file"); + } + + @NotNull + public String getFamilyName() { + return "DevKit"; + } + + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + final PsiDirectory[] dirs; + dirs = getDirectories(); + final List virtualFiles = getPotentialRoots(myModule, dirs); + final VirtualFile[] roots = prepare(VfsUtil.toVirtualFileArray(virtualFiles)); + if (roots.length == 1) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + createDescription(roots[0]); + } + }); + } + else { + List options = new ArrayList(); + for (VirtualFile file : roots) { + String path = getPath(file); + options.add(path); + } + final JBList files = new JBList(ArrayUtil.toStringArray(options)); + files.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + final JBPopup popup = JBPopupFactory.getInstance() + .createListPopupBuilder(files) + .setTitle(DevKitBundle.message("select.target.location.of.description", myFilename)) + .setItemChoosenCallback(new Runnable() { + public void run() { + final int index = files.getSelectedIndex(); + if (0 <= index && index < roots.length) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + createDescription(roots[index]); + } + }); + } + } + }).createPopup(); + final Editor editor = FileEditorManager.getInstance(myModule.getProject()).getSelectedTextEditor(); + if (editor == null) return; + popup.showInBestPositionFor(editor); + } + } + + private String getPath(VirtualFile file) { + String path = file.getPresentableUrl() + File.separator + getDescriptionFolderName() + File.separator + myFilename; + if (isIntention) { + path += File.separator + "description.html"; + } + return path; + } + + protected PsiDirectory[] getDirectories() { + PsiDirectory[] dirs; + if (isIntention) { + dirs = IntentionDescriptionNotFoundInspection.getIntentionDescriptionsDirs(myModule); + } + else { + dirs = InspectionDescriptionNotFoundInspection.getInspectionDescriptionsDirs(myModule); + } + return dirs; + } + private void createDescription(VirtualFile root) { if (!root.isDirectory()) return; final PsiManager psiManager = PsiManager.getInstance(myModule.getProject()); @@ -169,7 +183,8 @@ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable { } } final FileTemplate descrTemplate = FileTemplateManager.getInstance().getJ2eeTemplate(TEMPLATE_NAME); - final PsiElement template = FileTemplateUtil.createFromTemplate(descrTemplate, isIntention? "description.html" : myFilename, null, descrRoot); + final PsiElement template = + FileTemplateUtil.createFromTemplate(descrTemplate, getNewFileName(), null, descrRoot); if (template instanceof PsiFile) { final VirtualFile file = ((PsiFile)template).getVirtualFile(); if (file != null) { @@ -181,6 +196,10 @@ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable { } } + private String getNewFileName() { + return isIntention ? "description.html" : myFilename; + } + public Icon getIcon(int flags) { return new LayeredIcon(AllIcons.FileTypes.Html, AllIcons.Actions.New); } @@ -205,7 +224,7 @@ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable { return false; } - private String getDescriptionFolderName() { + protected String getDescriptionFolderName() { return isIntention ? "intentionDescriptions" : "inspectionDescriptions"; } } diff --git a/plugins/devkit/src/inspections/quickfix/CreatePostfixTemplateHtmlDescriptionFix.java b/plugins/devkit/src/inspections/quickfix/CreatePostfixTemplateHtmlDescriptionFix.java new file mode 100644 index 000000000000..1e1f9f779f31 --- /dev/null +++ b/plugins/devkit/src/inspections/quickfix/CreatePostfixTemplateHtmlDescriptionFix.java @@ -0,0 +1,39 @@ +/* + * 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.jetbrains.idea.devkit.inspections.quickfix; + +import com.intellij.openapi.module.Module; +import com.intellij.psi.PsiDirectory; +import org.jetbrains.idea.devkit.inspections.PostfixTemplateDescriptionNotFoundInspection; + + +public class CreatePostfixTemplateHtmlDescriptionFix extends CreateHtmlDescriptionFix { + + public CreatePostfixTemplateHtmlDescriptionFix(String filename, Module module) { + super(filename, module, true); + } + + @Override + protected PsiDirectory[] getDirectories() { + return PostfixTemplateDescriptionNotFoundInspection.getPostfixTemplateDirectories(myModule); + } + + @Override + protected String getDescriptionFolderName() { + return "postfixTemplates"; + } +} diff --git a/plugins/devkit/testData/codeInsight/postfixTemplates/MyQuickFixTemplate.java b/plugins/devkit/testData/codeInsight/postfixTemplates/MyQuickFixTemplate.java new file mode 100644 index 000000000000..de936e4550f6 --- /dev/null +++ b/plugins/devkit/testData/codeInsight/postfixTemplates/MyQuickFixTemplate.java @@ -0,0 +1,6 @@ +import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate; + +public class MyQuickFixTemplate extends PostfixTemplate { + + +} diff --git a/plugins/devkit/testData/codeInsight/postfixTemplates/MyTemplate.java b/plugins/devkit/testData/codeInsight/postfixTemplates/MyTemplate.java new file mode 100644 index 000000000000..e20fbb6be2df --- /dev/null +++ b/plugins/devkit/testData/codeInsight/postfixTemplates/MyTemplate.java @@ -0,0 +1,6 @@ +import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate; + +public class MyTemplate extends PostfixTemplate { + + +} diff --git a/plugins/devkit/testData/codeInsight/postfixTemplates/MyTemplateWithDescription.java b/plugins/devkit/testData/codeInsight/postfixTemplates/MyTemplateWithDescription.java new file mode 100644 index 000000000000..02b9c8928fac --- /dev/null +++ b/plugins/devkit/testData/codeInsight/postfixTemplates/MyTemplateWithDescription.java @@ -0,0 +1,6 @@ +import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate; + +public class MyTemplateWithDescription extends PostfixTemplate { + + +} diff --git a/plugins/devkit/testData/codeInsight/postfixTemplates/MyTemplateWithoutBeforeAfter.java b/plugins/devkit/testData/codeInsight/postfixTemplates/MyTemplateWithoutBeforeAfter.java new file mode 100644 index 000000000000..9e0ae10e8905 --- /dev/null +++ b/plugins/devkit/testData/codeInsight/postfixTemplates/MyTemplateWithoutBeforeAfter.java @@ -0,0 +1,6 @@ +import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate; + +public class MyTemplateWithoutBeforeAfter extends PostfixTemplate{ + + + } diff --git a/plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithDescription/after.java.template b/plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithDescription/after.java.template new file mode 100644 index 000000000000..675fbd2b9292 --- /dev/null +++ b/plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithDescription/after.java.template @@ -0,0 +1 @@ +test after diff --git a/plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithDescription/before.java.template b/plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithDescription/before.java.template new file mode 100644 index 000000000000..6fbfb79f92a9 --- /dev/null +++ b/plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithDescription/before.java.template @@ -0,0 +1 @@ +test before diff --git a/plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithDescription/description.html b/plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithDescription/description.html new file mode 100644 index 000000000000..6b0d347bb279 --- /dev/null +++ b/plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithDescription/description.html @@ -0,0 +1 @@ +test description diff --git a/plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithoutBeforeAfter/description.html b/plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithoutBeforeAfter/description.html new file mode 100644 index 000000000000..6b0d347bb279 --- /dev/null +++ b/plugins/devkit/testData/codeInsight/postfixTemplates/postfixTemplates/MyTemplateWithoutBeforeAfter/description.html @@ -0,0 +1 @@ +test description diff --git a/plugins/devkit/testSources/codeInsight/PostfixTemplateInspectionTest.java b/plugins/devkit/testSources/codeInsight/PostfixTemplateInspectionTest.java new file mode 100644 index 000000000000..6b655725985d --- /dev/null +++ b/plugins/devkit/testSources/codeInsight/PostfixTemplateInspectionTest.java @@ -0,0 +1,61 @@ +/* + * 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.jetbrains.idea.devkit.codeInsight; + +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.openapi.application.PluginPathManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; +import org.jetbrains.idea.devkit.inspections.PostfixTemplateDescriptionNotFoundInspection; + +public class PostfixTemplateInspectionTest extends JavaCodeInsightFixtureTestCase { + + @Override + protected String getBasePath() { + return PluginPathManager.getPluginHomePathRelative("devkit") + "/testData/codeInsight/postfixTemplates"; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + myFixture.enableInspections(PostfixTemplateDescriptionNotFoundInspection.class); + myFixture.addClass("package com.intellij.codeInsight.template.postfix.templates; public class PostfixTemplate {}"); + } + + public void testHighlightingForDescription() { + myFixture.testHighlighting("MyTemplate.java"); + } + + public void testNoHighlighting() { + myFixture.copyDirectoryToProject("postfixTemplates", "postfixTemplates"); + myFixture.testHighlighting("MyTemplateWithDescription.java"); + } + + public void testHighlightingForBeforeAfter() { + myFixture.copyDirectoryToProject("postfixTemplates", "postfixTemplates"); + myFixture.testHighlighting("MyTemplateWithoutBeforeAfter.java"); + } + + public void testQuickFix() { + myFixture.configureByFiles("MyQuickFixTemplate.java"); + IntentionAction item = myFixture.findSingleIntention("Create Description File"); + myFixture.launchAction(item); + + VirtualFile path = myFixture.findFileInTempDir("postfixTemplates/MyQuickFixTemplate/description.html"); + assertNotNull(path); + assertTrue(path.exists()); + } +} From 6a76a7e59ec31656fa547c8ebf50b8457d2a85cb Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 6 May 2014 14:36:09 +0400 Subject: [PATCH 31/35] ignore deleted custom repositories (IDEA-124796) --- .../src/com/intellij/ide/plugins/PluginManagerMain.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java index bce1a97ccdae..456e7fcfd19b 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java @@ -69,6 +69,7 @@ import javax.xml.parsers.SAXParserFactory; import java.awt.*; import java.awt.event.MouseEvent; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.net.URL; import java.util.*; @@ -329,6 +330,9 @@ public abstract class PluginManagerMain implements Disposable { } catch (ProcessCanceledException ignore) { } + catch (FileNotFoundException e) { + LOG.info(e); + } catch (Exception e) { LOG.info(e); errorMessages.add(e.getMessage()); From 51e7e1c65687d99a8f1d56ebd17648bb4f7f4a13 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 6 May 2014 14:57:16 +0400 Subject: [PATCH 32/35] compiler configuration: distinguish compilable resources (IDEA-124599) --- .../compiler/CompilerConfigurationImpl.java | 12 +++++++++- .../compiler/actions/CompileAction.java | 22 +++++-------------- .../compiler/CompilerConfiguration.java | 2 ++ .../execution/junit/TestClassFilter.java | 3 ++- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java b/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java index f7ed9c255bf8..8369bb136d1a 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java @@ -53,6 +53,8 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.packaging.artifacts.Artifact; +import com.intellij.packaging.impl.artifacts.ArtifactBySourceFileFinder; import com.intellij.util.ArrayUtil; import com.intellij.util.messages.MessageBusConnection; import org.apache.oro.text.regex.*; @@ -978,7 +980,15 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements } return extensionsString.toString(); } - + + public boolean isCompilableResourceFile(final Project project, final VirtualFile file) { + if (!isResourceFile(file)) { + return false; + } + final Collection artifacts = ArtifactBySourceFileFinder.getInstance(project).findArtifacts(file); + return artifacts.isEmpty(); + } + private static class CompiledPattern { @NotNull final Pattern fileName; @Nullable final Pattern dir; diff --git a/java/compiler/impl/src/com/intellij/compiler/actions/CompileAction.java b/java/compiler/impl/src/com/intellij/compiler/actions/CompileAction.java index 800adaa1b5f6..38f230f92997 100644 --- a/java/compiler/impl/src/com/intellij/compiler/actions/CompileAction.java +++ b/java/compiler/impl/src/com/intellij/compiler/actions/CompileAction.java @@ -26,14 +26,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.packaging.artifacts.Artifact; -import com.intellij.packaging.impl.artifacts.ArtifactBySourceFileFinder; import com.intellij.psi.*; import java.util.ArrayList; -import java.util.Collection; import java.util.List; public class CompileAction extends CompileActionBase { @@ -108,7 +105,8 @@ public class CompileAction extends CompileActionBase { else if (files.length == 1) { final VirtualFile file = files[0]; FileType fileType = file.getFileType(); - if (CompilerManager.getInstance(project).isCompilableFileType(fileType) || isCompilableResourceFile(project, compilerConfiguration, file)) { + if (CompilerManager.getInstance(project).isCompilableFileType(fileType) || compilerConfiguration + .isCompilableResourceFile(project, file)) { elementDescription = "'" + file.getName() + "'"; } else { @@ -135,7 +133,7 @@ public class CompileAction extends CompileActionBase { } private static String createPresentationText(String elementDescription) { - StringBuffer buffer = new StringBuffer(40); + StringBuilder buffer = new StringBuilder(40); buffer.append(ActionsBundle.actionText(IdeActions.ACTION_COMPILE)).append(" "); int length = elementDescription.length(); if (length > 23) { @@ -175,20 +173,12 @@ public class CompileAction extends CompileActionBase { } else { FileType fileType = file.getFileType(); - if (!(compilerManager.isCompilableFileType(fileType) || isCompilableResourceFile(project, compilerConfiguration, file))) { + if (!(compilerManager.isCompilableFileType(fileType) || compilerConfiguration.isCompilableResourceFile(project, file))) { continue; } } filesToCompile.add(file); } - return VfsUtil.toVirtualFileArray(filesToCompile); - } - - private static boolean isCompilableResourceFile(final Project project, final CompilerConfiguration compilerConfiguration, final VirtualFile file) { - if (!compilerConfiguration.isResourceFile(file)) { - return false; - } - final Collection artifacts = ArtifactBySourceFileFinder.getInstance(project).findArtifacts(file); - return artifacts.isEmpty(); + return VfsUtilCore.toVirtualFileArray(filesToCompile); } } \ No newline at end of file diff --git a/java/compiler/openapi/src/com/intellij/compiler/CompilerConfiguration.java b/java/compiler/openapi/src/com/intellij/compiler/CompilerConfiguration.java index 9aa97cf0e089..364379490852 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/CompilerConfiguration.java +++ b/java/compiler/openapi/src/com/intellij/compiler/CompilerConfiguration.java @@ -54,6 +54,8 @@ public abstract class CompilerConfiguration { public abstract boolean isResourceFile(String path); + public abstract boolean isCompilableResourceFile(Project project, VirtualFile file); + public abstract void addResourceFilePattern(String namePattern) throws MalformedPatternException; public abstract boolean isAddNotNullAssertions(); diff --git a/plugins/junit/src/com/intellij/execution/junit/TestClassFilter.java b/plugins/junit/src/com/intellij/execution/junit/TestClassFilter.java index 9f9fb7bd054e..d8f78b4d6b6b 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestClassFilter.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestClassFilter.java @@ -59,7 +59,8 @@ public class TestClassFilter implements ClassFilter.ClassFilterWithScope { (aClass.isInheritor(myBase, true) || JUnitUtil.isTestClass(aClass))) { final CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(getProject()); final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(aClass); - return !compilerConfiguration.isExcludedFromCompilation(virtualFile) && !compilerConfiguration.isResourceFile(virtualFile); + return !compilerConfiguration.isExcludedFromCompilation(virtualFile) && + (!compilerConfiguration.isResourceFile(virtualFile) || compilerConfiguration.isCompilableResourceFile(myProject, virtualFile)); } return false; } From 6f548f2a25564b6b64c43c52060cd3378acff2af Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 6 May 2014 15:20:09 +0400 Subject: [PATCH 33/35] skip tests under resources roots --- .../src/com/intellij/execution/junit/TestClassFilter.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/junit/src/com/intellij/execution/junit/TestClassFilter.java b/plugins/junit/src/com/intellij/execution/junit/TestClassFilter.java index d8f78b4d6b6b..2631df75d0ac 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestClassFilter.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestClassFilter.java @@ -23,6 +23,7 @@ import com.intellij.ide.util.ClassFilter; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; @@ -30,6 +31,7 @@ import com.intellij.psi.PsiManager; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiUtilCore; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; import java.util.ArrayList; import java.util.List; @@ -59,8 +61,9 @@ public class TestClassFilter implements ClassFilter.ClassFilterWithScope { (aClass.isInheritor(myBase, true) || JUnitUtil.isTestClass(aClass))) { final CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(getProject()); final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(aClass); - return !compilerConfiguration.isExcludedFromCompilation(virtualFile) && - (!compilerConfiguration.isResourceFile(virtualFile) || compilerConfiguration.isCompilableResourceFile(myProject, virtualFile)); + if (virtualFile == null) return false; + return !compilerConfiguration.isExcludedFromCompilation(virtualFile) && + !ProjectRootManager.getInstance(myProject).getFileIndex().isUnderSourceRootOfType(virtualFile, JavaModuleSourceRootTypes.RESOURCES); } return false; } From f0ac2bd244f0c89ec41f233d25f43d2faf1269a3 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 6 May 2014 16:05:59 +0400 Subject: [PATCH 34/35] unnecessarily qualified statically imported elements: do not ignore chained calls (IDEA-124806) --- ...ualifiedStaticallyImportedElementInspection.java | 2 +- .../chainedMethodCall/expected.xml | 8 ++++++++ .../chainedMethodCall/src/Test.java | 13 +++++++++++++ .../{ => simple}/expected.xml | 0 .../{ => simple/src}/C.java | 0 ...fiedStaticallyImportedElementInspectionTest.java | 6 +++++- 6 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/chainedMethodCall/expected.xml create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/chainedMethodCall/src/Test.java rename plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/{ => simple}/expected.xml (100%) rename plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/{ => simple/src}/C.java (100%) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspection.java index e33db815bd49..7c6d5a999ecb 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspection.java @@ -94,7 +94,7 @@ public class UnnecessarilyQualifiedStaticallyImportedElementInspection extends B if (!(qualifier instanceof PsiJavaCodeReferenceElement)) { return; } - if (PsiTreeUtil.getParentOfType(reference, PsiReferenceExpression.class, PsiImportStatementBase.class) != null) { + if (PsiTreeUtil.getParentOfType(reference, PsiImportStatementBase.class) != null) { return; } if (UnnecessarilyQualifiedStaticUsageInspection.isGenericReference(reference, (PsiJavaCodeReferenceElement)qualifier)) return; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/chainedMethodCall/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/chainedMethodCall/expected.xml new file mode 100644 index 000000000000..4944dce1ffa2 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/chainedMethodCall/expected.xml @@ -0,0 +1,8 @@ + + + Test.java + 7 + Unnecessarily qualified statically imported element + Statically imported element 'foo' is unnecessarily qualified with <code>A</code> #loc + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/chainedMethodCall/src/Test.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/chainedMethodCall/src/Test.java new file mode 100644 index 000000000000..a731da90bd2f --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/chainedMethodCall/src/Test.java @@ -0,0 +1,13 @@ +package p; + +import static p.A.foo; + +class StaticImport { + void example() { + A.foo().toString(); + } +} + +class A { + static Object foo() {return null;} +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/simple/expected.xml similarity index 100% rename from plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/expected.xml rename to plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/simple/expected.xml diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/C.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/simple/src/C.java similarity index 100% rename from plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/C.java rename to plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/simple/src/C.java diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspectionTest.java index df7f28b474b9..9dfaba52517a 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspectionTest.java @@ -21,7 +21,7 @@ public class UnnecessarilyQualifiedStaticallyImportedElementInspectionTest extends IGInspectionTestCase { public void test() throws Exception { - doTest("com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element", + doTest("com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/simple", new UnnecessarilyQualifiedStaticallyImportedElementInspection()); } @@ -33,6 +33,10 @@ public class UnnecessarilyQualifiedStaticallyImportedElementInspectionTest doTest(getTestName(true)); } + public void testChainedMethodCall() throws Exception { + doTest(getTestName(true)); + } + private void doTest(String testName) throws Exception { doTest("com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/" + testName, new UnnecessarilyQualifiedStaticallyImportedElementInspection()); From 6c5b4239138553791f8e34791f0132e968b828fa Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Tue, 6 May 2014 16:26:10 +0400 Subject: [PATCH 35/35] revert IDEA-123956 Anonymous class formatting moves all args to the next line (32ae79905cb025f6bc213a925f1f4e58e9d6b8f7) --- .../psi/formatter/java/AbstractJavaBlock.java | 19 ++++++-------- .../psi/formatter/java/JavaFormatterTest.java | 5 ++-- .../formatter/java/JavaFormatterWrapTest.java | 25 ++++--------------- 3 files changed, 15 insertions(+), 34 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java index bcd6ac6cd602..b1d4c675d8b2 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java @@ -480,7 +480,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo if (nodeType == JavaElementType.POLYADIC_EXPRESSION) nodeType = JavaElementType.BINARY_EXPRESSION; if (childType == JavaTokenType.LBRACE && nodeType == JavaElementType.ARRAY_INITIALIZER_EXPRESSION) { - final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.ARRAY_INITIALIZER_WRAP), true); + final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.ARRAY_INITIALIZER_WRAP), false); child = processParenthesisBlock(JavaTokenType.LBRACE, JavaTokenType.RBRACE, result, child, @@ -488,7 +488,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo mySettings.ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION); } else if (childType == JavaTokenType.LBRACE && nodeType == JavaElementType.ANNOTATION_ARRAY_INITIALIZER) { - final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.ARRAY_INITIALIZER_WRAP), true); + final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.ARRAY_INITIALIZER_WRAP), false); child = processParenthesisBlock(JavaTokenType.LBRACE, JavaTokenType.RBRACE, result, child, @@ -496,7 +496,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo mySettings.ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION); } else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.EXPRESSION_LIST) { - final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.CALL_PARAMETERS_WRAP), true); + final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.CALL_PARAMETERS_WRAP), false); if (mySettings.PREFER_PARAMETERS_WRAP) { wrap.ignoreParentWraps(); } @@ -507,19 +507,19 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.PARAMETER_LIST) { // There is a possible case that particular annotated method definition is too long. We may wrap either after annotation // or after opening lbrace then. Our strategy is to wrap after annotation whenever possible. - Wrap wrap = Wrap.createWrap(getWrapType(mySettings.METHOD_PARAMETERS_WRAP), true); + Wrap wrap = Wrap.createWrap(getWrapType(mySettings.METHOD_PARAMETERS_WRAP), false); child = processParenthesisBlock(result, child, WrappingStrategy.createDoNotWrapCommaStrategy(wrap), mySettings.ALIGN_MULTILINE_PARAMETERS); } else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.RESOURCE_LIST) { - Wrap wrap = Wrap.createWrap(getWrapType(mySettings.RESOURCE_LIST_WRAP), true); + Wrap wrap = Wrap.createWrap(getWrapType(mySettings.RESOURCE_LIST_WRAP), false); child = processParenthesisBlock(result, child, WrappingStrategy.createDoNotWrapCommaStrategy(wrap), mySettings.ALIGN_MULTILINE_RESOURCES); } else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.ANNOTATION_PARAMETER_LIST) { - Wrap wrap = Wrap.createWrap(getWrapType(mySettings.CALL_PARAMETERS_WRAP), true); + Wrap wrap = Wrap.createWrap(getWrapType(mySettings.CALL_PARAMETERS_WRAP), false); child = processParenthesisBlock(result, child, WrappingStrategy.createDoNotWrapCommaStrategy(wrap), mySettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS); @@ -915,7 +915,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo ASTNode prev = child; boolean afterAnonymousClass = false; final boolean enforceIndent = shouldEnforceIndentToChildren(); - boolean currentChildIsFirstToWrap = true; while (child != null) { isAfterIncomplete = isAfterIncomplete || child.getElementType() == TokenType.ERROR_ELEMENT || child.getElementType() == JavaElementType.EMPTY_EXPRESSION; @@ -935,11 +934,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo final IElementType elementType = child.getElementType(); Indent indentToUse = enforceIndent ? internalIndentEnforcedToChildren : internalIndent; AlignmentStrategy alignmentStrategyToUse = canUseAnonymousClassAlignment(child) ? anonymousClassStrategy : alignmentStrategy; - - Wrap wrap = currentChildIsFirstToWrap ? Wrap.createWrap(WrapType.NONE, true) : wrappingStrategy.getWrap(elementType); - currentChildIsFirstToWrap = false; - processChild(result, child, alignmentStrategyToUse.getAlignment(elementType), wrap, indentToUse); - + processChild(result, child, alignmentStrategyToUse.getAlignment(elementType), wrappingStrategy.getWrap(elementType), indentToUse); if (to == null) {//process only one statement return child; } diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java index 09cba9382896..c00db0fc77ad 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java @@ -931,12 +931,13 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest { getSettings().getRootSettings().RIGHT_MARGIN = 20; getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED; doTextTest("class Foo {\n" + " void foo() {\n" + " fooFooFooFoo(1);" + " }\n" + "}", - "class Foo {\n" + " void foo() {\n" + " fooFooFooFoo(1);\n" + " }\n" + "}"); + "class Foo {\n" + " void foo() {\n" + " fooFooFooFoo(\n" + " 1);\n" + " }\n" + "}"); getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM; doTextTest("class Foo {\n" + " void foo() {\n" + " fooFooFooFoo(1,2);" + " }\n" + "}", "class Foo {\n" + " void foo() {\n" + - " fooFooFooFoo(1,\n" + + " fooFooFooFoo(\n" + + " 1,\n" + " 2);\n" + " }\n" + "}"); diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java index ab4a73af30bc..512a7ef3c158 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java @@ -47,7 +47,8 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest { "class Foo {\n" + "}", - "@AttributeOverrides({@AttributeOverride(name = \"id\", column = @Column(name = \"recovery_id\")),\n" + + "@AttributeOverrides({\n" + + " @AttributeOverride(name = \"id\", column = @Column(name = \"recovery_id\")),\n" + " @AttributeOverride(name = \"transactionReference\", column = @Column(name = \"deal_reference\")),\n" + " @AttributeOverride(name = \"eventDate\", column = @Column(name = \"recovery_date\")),\n" + " @AttributeOverride(name = \"amount\", column = @Column(name = \"recovery_amount\")),\n" + @@ -390,8 +391,9 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest { String literal = "\"" + StringUtil.repeatSymbol('A', 128) + "\""; before = "processingEnv.getMessenger().printMessage(Diagnostic.Kind.ERROR, call(" + literal + "));\n"; after = "processingEnv.getMessenger().printMessage(\n" + - " Diagnostic.Kind.ERROR,\n" + - " call(" + literal + ")\n" + + " Diagnostic.Kind.ERROR, call(\n" + + " " + literal + "\n" + + " )\n" + ");\n"; doMethodTest(before, after); @@ -446,21 +448,4 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest { " public @TA String m();\n" + "}"); } - - public void testIDEA123956() { - doMethodTest( - "final BaseAnalysisActionDialog dialog = new BaseAnalysisActionDialog(" + - "AnalysisScopeBundle.message(\"specify.analysis.scope\", InspectionsBundle.message(\"inspection.action.title\")),\n" + - " AnalysisScopeBundle.message(\"analysis.scope.title\", InspectionsBundle.message(\"inspection.action.noun\")),\n" + - " project, analysisScope, module != null ? module.getName() : null,\n" + - " true, AnalysisUIOptions.getInstance(project), psiElement) {\n" + - "}", - "final BaseAnalysisActionDialog dialog = new BaseAnalysisActionDialog(" + - "AnalysisScopeBundle.message(\"specify.analysis.scope\", InspectionsBundle.message(\"inspection.action.title\")),\n" + - " AnalysisScopeBundle.message(\"analysis.scope.title\", InspectionsBundle.message(\"inspection.action.noun\")),\n" + - " project, analysisScope, module != null ? module.getName() : null,\n" + - " true, AnalysisUIOptions.getInstance(project), psiElement) {\n" + - "}" - ); - } }