From 39f15eda94ab840c92ecd02d1baf4c2cb7f7f080 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Wed, 10 Jan 2018 15:42:32 +0300 Subject: [PATCH 01/33] IDEA-184208 Console horizontal scroll position lost on output support auto-scrolling when long text line (without breaks) is printed --- .../intellij/openapi/editor/ex/util/EditorUtil.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java index cf7018954b48..17182f533b84 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java @@ -602,16 +602,18 @@ public final class EditorUtil { scrollToTheEnd(editor, false); } - public static void scrollToTheEnd(@NotNull Editor editor, boolean verticalScrollOnly) { + public static void scrollToTheEnd(@NotNull Editor editor, boolean preferVerticalScroll) { editor.getSelectionModel().removeSelection(); - int lastLine = Math.max(0, editor.getDocument().getLineCount() - 1); + Document document = editor.getDocument(); + int lastLine = Math.max(0, document.getLineCount() - 1); if (editor.getCaretModel().getLogicalPosition().line == lastLine) { - editor.getCaretModel().moveToOffset(editor.getDocument().getTextLength()); + editor.getCaretModel().moveToOffset(document.getTextLength()); } else { editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(lastLine, 0)); } ScrollingModel scrollingModel = editor.getScrollingModel(); - if (verticalScrollOnly) { + if (preferVerticalScroll && document.getLineStartOffset(lastLine) == document.getLineEndOffset(lastLine)) { + // don't move 'focus' to empty last line int scrollOffset; if (editor instanceof EditorEx) { JScrollBar verticalScrollBar = ((EditorEx)editor).getScrollPane().getVerticalScrollBar(); From 67a86a23494ad88faebef45134ae756e3be0186d Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Wed, 10 Jan 2018 16:28:43 +0300 Subject: [PATCH 02/33] IDEA-184560 Java decompiler doesn't use stored parameter names --- .../java/decompiler/code/CodeConstants.java | 5 +- .../java/decompiler/main/ClassWriter.java | 25 +++- .../main/extern/IFernflowerPreferences.java | 6 +- .../struct/attr/StructGeneralAttribute.java | 8 +- .../attr/StructMethodParametersAttribute.java | 56 ++++++++ .../java/decompiler/SingleClassesTest.java | 5 +- .../pkg/TestMethodParametersAttr$1Local.class | Bin 0 -> 729 bytes .../pkg/TestMethodParametersAttr$C1.class | Bin 0 -> 677 bytes .../pkg/TestMethodParametersAttr$C2.class | Bin 0 -> 627 bytes .../pkg/TestMethodParametersAttr$C3.class | Bin 0 -> 624 bytes .../pkg/TestMethodParametersAttr$C4.class | Bin 0 -> 488 bytes .../pkg/TestMethodParametersAttr$I1.class | Bin 0 -> 306 bytes .../pkg/TestMethodParametersAttr.class | Bin 0 -> 981 bytes .../results/TestMethodParametersAttr.dec | 125 ++++++++++++++++++ .../src/pkg/TestMethodParametersAttr.java | 56 ++++++++ 15 files changed, 279 insertions(+), 7 deletions(-) create mode 100644 plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructMethodParametersAttribute.java create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr$1Local.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr$C1.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr$C2.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr$C3.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr$C4.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr$I1.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr.class create mode 100644 plugins/java-decompiler/engine/testData/results/TestMethodParametersAttr.dec create mode 100644 plugins/java-decompiler/engine/testData/src/pkg/TestMethodParametersAttr.java diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/CodeConstants.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/CodeConstants.java index 4ff5daa2cf66..a8f9f3667250 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/CodeConstants.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/CodeConstants.java @@ -1,4 +1,6 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ package org.jetbrains.java.decompiler.code; @SuppressWarnings({"unused", "SpellCheckingInspection"}) @@ -70,6 +72,7 @@ public interface CodeConstants { int ACC_SYNTHETIC = 0x1000; int ACC_ANNOTATION = 0x2000; int ACC_ENUM = 0x4000; + int ACC_MANDATED = 0x8000; // ---------------------------------------------------------------------- // CLASS FLAGS diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java index 210529f5362c..8d862c81c547 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ package org.jetbrains.java.decompiler.main; @@ -697,6 +697,15 @@ public class ClassWriter { } } + List methodParameters = null; + if (DecompilerContext.getOption(IFernflowerPreferences.USE_METHOD_PARAMETERS)) { + StructMethodParametersAttribute attr = + (StructMethodParametersAttribute)mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_METHOD_PARAMETERS); + if (attr != null) { + methodParameters = attr.getEntries(); + } + } + int index = isEnum && init ? 3 : thisVar ? 1 : 0; int start = isEnum && init ? 2 : 0; for (int i = start; i < md.params.length; i++) { @@ -707,7 +716,10 @@ public class ClassWriter { appendParameterAnnotations(buffer, mt, paramCount); - if (methodWrapper.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarTypeProcessor.VAR_EXPLICIT_FINAL) { + if (methodParameters != null && paramCount < methodParameters.size()) { + appendModifiers(buffer, methodParameters.get(paramCount).myAccessFlags, CodeConstants.ACC_FINAL, isInterface, 0); + } + else if (methodWrapper.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarTypeProcessor.VAR_EXPLICIT_FINAL) { buffer.append("final "); } @@ -741,7 +753,14 @@ public class ClassWriter { } buffer.append(' '); - String parameterName = methodWrapper.varproc.getVarName(new VarVersionPair(index, 0)); + + String parameterName; + if (methodParameters != null && paramCount < methodParameters.size()) { + parameterName = methodParameters.get(paramCount).myName; + } + else { + parameterName = methodWrapper.varproc.getVarName(new VarVersionPair(index, 0)); + } buffer.append(parameterName == null ? "param" + index : parameterName); // null iff decompiled with errors paramCount++; diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java index cda288b96a57..3c0fac5fb416 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java @@ -1,4 +1,6 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ package org.jetbrains.java.decompiler.main.extern; import org.jetbrains.java.decompiler.util.InterpreterUtil; @@ -25,6 +27,7 @@ public interface IFernflowerPreferences { String SYNTHETIC_NOT_SET = "nns"; String UNDEFINED_PARAM_TYPE_OBJECT = "uto"; String USE_DEBUG_VAR_NAMES = "udv"; + String USE_METHOD_PARAMETERS = "ump"; String REMOVE_EMPTY_RANGES = "rer"; String FINALLY_DEINLINE = "fdi"; String IDEA_NOT_NULL_ANNOTATION = "inn"; @@ -67,6 +70,7 @@ public interface IFernflowerPreferences { defaults.put(SYNTHETIC_NOT_SET, "0"); defaults.put(UNDEFINED_PARAM_TYPE_OBJECT, "1"); defaults.put(USE_DEBUG_VAR_NAMES, "1"); + defaults.put(USE_METHOD_PARAMETERS, "1"); defaults.put(REMOVE_EMPTY_RANGES, "1"); defaults.put(FINALLY_DEINLINE, "1"); defaults.put(IDEA_NOT_NULL_ANNOTATION, "1"); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructGeneralAttribute.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructGeneralAttribute.java index 8cc8bdb27c1b..eb69af4b7965 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructGeneralAttribute.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructGeneralAttribute.java @@ -1,4 +1,6 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ package org.jetbrains.java.decompiler.struct.attr; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; @@ -33,6 +35,7 @@ public class StructGeneralAttribute { public static final String ATTRIBUTE_SYNTHETIC = "Synthetic"; public static final String ATTRIBUTE_DEPRECATED = "Deprecated"; public static final String ATTRIBUTE_LINE_NUMBER_TABLE = "LineNumberTable"; + public static final String ATTRIBUTE_METHOD_PARAMETERS = "MethodParameters"; private String name; @@ -81,6 +84,9 @@ public class StructGeneralAttribute { else if (ATTRIBUTE_LINE_NUMBER_TABLE.equals(name)) { attr = new StructLineNumberTableAttribute(); } + else if (ATTRIBUTE_METHOD_PARAMETERS.equals(name)) { + attr = new StructMethodParametersAttribute(); + } else { // unsupported attribute return null; diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructMethodParametersAttribute.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructMethodParametersAttribute.java new file mode 100644 index 000000000000..08133a9707c7 --- /dev/null +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructMethodParametersAttribute.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ +package org.jetbrains.java.decompiler.struct.attr; + +import org.jetbrains.java.decompiler.struct.consts.ConstantPool; +import org.jetbrains.java.decompiler.util.DataInputFullStream; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/* + u1 parameters_count; + { u2 name_index; + u2 access_flags; + } parameters[parameters_count]; +*/ +public class StructMethodParametersAttribute extends StructGeneralAttribute { + private List myEntries; + + @Override + public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException { + int len = data.readUnsignedByte(); + List entries; + if (len > 0) { + entries = new ArrayList<>(len); + + for (int i = 0; i < len; i++) { + int nameIndex = data.readUnsignedShort(); + String name = nameIndex != 0 ? pool.getPrimitiveConstant(nameIndex).getString() : null; + int access_flags = data.readUnsignedShort(); + entries.add(new Entry(name, access_flags)); + } + } + else { + entries = Collections.emptyList(); + } + myEntries = Collections.unmodifiableList(entries); + } + + public List getEntries() { + return myEntries; + } + + public static class Entry { + public final String myName; + public final int myAccessFlags; + + public Entry(String name, int accessFlags) { + myName = name; + myAccessFlags = accessFlags; + } + } +} diff --git a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java index 9c971c3e06ac..15da93c15fc3 100644 --- a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -1,4 +1,6 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ package org.jetbrains.java.decompiler; import org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler; @@ -45,6 +47,7 @@ public class SingleClassesTest { @Test public void testDeprecations() { doTest("pkg/TestDeprecations"); } @Test public void testExtendsList() { doTest("pkg/TestExtendsList"); } @Test public void testMethodParameters() { doTest("pkg/TestMethodParameters"); } + @Test public void testMethodParametersAttr() { doTest("pkg/TestMethodParametersAttr"); } @Test public void testCodeConstructs() { doTest("pkg/TestCodeConstructs"); } @Test public void testConstants() { doTest("pkg/TestConstants"); } @Test public void testEnum() { doTest("pkg/TestEnum"); } diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr$1Local.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr$1Local.class new file mode 100644 index 0000000000000000000000000000000000000000..8cfb527cfc5cfa743544180a9df5f46c2a5446c5 GIT binary patch literal 729 zcma)4T}#_w6n;+AG;0=Z=G5ut$GTN$yJ6=xuQr5HCKl=ktn~hE`l69EktFWgzvRUj zc(EU_A2s&8v3OAs8p!!R&w0*C{{FlB1K=~>RAJ$ji!wGGY&zHyRPu{3YkUyw^v60# zCRbsk)6PI=`LWI~lJS{J)kNny&A#P%`h^W&!#KmR5G7d{pWh=p*!J)mbq_Ww9vsvK z?K!SGB};||w-c%OymLCb)IlzIJ4ZiH6`3<~*=B1<1{S|CAii&i&?@nD@PxWb>xkN- zcH8fMLE67jx-Dv4$_j+Cfv1!PhgI-Uqc)a7GkF(2o)Kk)~4_GCg?*IS* literal 0 HcmV?d00001 diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr$C1.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr$C1.class new file mode 100644 index 0000000000000000000000000000000000000000..9acce02b6cbbe46715b9fa66ec99400bc8e36e8a GIT binary patch literal 677 zcma)3$x6de6g{_7Y^*lcd8i5wvgiaA(ODda$80!peK$T8luILZ)XPmlsupy#Am4C(ef8LD>F`dqJVpwQ zpsl>73SHw5gDJyFkf>D!xw`M`u;!^K(u|EXbF)?@(PY2MeyIzbzpF6ZBdOAW8|w}P z_HFPOw)HvJ7Zm^7f3K^aR1Rrmaf&ybv8yo zz&cNt;uXbl%zRo2{uailv$QU#lhpRk?ki;H4T+aQjZK+>P%dDc(%`TPIpnF0WzbCC zhJz`h6liA?NIyFam~R?0!y!lX%vkx0y*R+0`$_&{3ucMPE3+kS9Me5Fkn@3S+PnAL=a=G8)($o1@(NtY8W-y!@gIy0pAswH`v7lO|(GhMG^gUn5YE#7OMyPJo zx#yAxLJ1jPDJ6HD+Brj_Upr!8b%xwe5wQd6k%De80x}dHGh`m3fpo<+(HYAB;SYQK ziQ6!-YGI9Gce;&e4Lw)&dH7hpYxjh!=-P_@o$VkxBkBZ@g zR5Bw?s=U@(?Faq^+p`lM?DnepOMlCFvB^2V8`)_sIoglKRK;||tp#@e>wP?y&(eX3 zriCqmgW1;M4Jx0P%KXW@kH!>hfxQ{L<}M8W*XmS}$AUkXmB(3dZXUftys$7}actG_ r3~koVcLC;Du@eheWYVcjyibjmf1@r#11oi}Rm^j?x!%A!Y_t6ZG@)!= literal 0 HcmV?d00001 diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr$I1.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr$I1.class new file mode 100644 index 0000000000000000000000000000000000000000..6b52d993d8f8425e551472af52992d4941f5b215 GIT binary patch literal 306 zcma)%%WA?<5QhJWiAiIs=>xd3NV_q#TWh1zb?$OUlx1%#bQdO)Mg=$-t?O`Vq6{^}t xt6k2iAx!?E*9SyT{sb&r4u>tdBbh^xo|N3{l7~>}hmMAip?F_-!T^tb?*gdJM$!NP literal 0 HcmV?d00001 diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestMethodParametersAttr.class new file mode 100644 index 0000000000000000000000000000000000000000..3549300662c2ede40f25f7914888ea060453140b GIT binary patch literal 981 zcma)4+fLg+5IvJPaT?MBX`n3y8g3yM)Q~_Qsv@K+QYB02MIz#TldQnVv61cYUp!Un z10T?jLYz(72xyVK($1OLJ##!W>)*G(ZU7u&FOM{~Y;4=uu~8AEI){RSg%wl z`W{b;lY~`1Q<8YwA@I!*Nr@r+5LS3l>7Eu;#C8&($ zn2e^U{Illw{)HaIf=YtKZ8Q61M7ENM=x_*$h#ih78Ig+hB+axYFN_VO_=}lkaWA6C z_$9rM;KL9z^`DSyIw_QBvpfa~OSH>V0`V0iQt=vZc)wzNVPMwVnc@dVM)4oD(mgeq zsR>r^tF1CKhqakn!zlevZE2!bm|kL?8u(k$I$hu$%Dgl^KB=+$Kx5ipilZ_OY;p!b ho7Q5Kv2w79IZp2xF`vz0j#yx^&xtR{o#$Qv?f~PG#$Esb literal 0 HcmV?d00001 diff --git a/plugins/java-decompiler/engine/testData/results/TestMethodParametersAttr.dec b/plugins/java-decompiler/engine/testData/results/TestMethodParametersAttr.dec new file mode 100644 index 000000000000..ba00341fd402 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/TestMethodParametersAttr.dec @@ -0,0 +1,125 @@ +package decompiler; + +public class TestMethodParametersAttr { + TestMethodParametersAttr(int p01) { + }// 19 + + void m1(int p02) { + }// 20 + + static void m2(int p03) { + }// 21 + + void local() { + class Local { + Local(final int this$0) { + }// 36 + + void m(int p32) { + }// 37 + } + + }// 39 + + abstract static class C4 { + abstract void m1(int p51); + + abstract void m2(final int p52); + } + + abstract class C3 { + abstract void m1(int p51); + + abstract void m2(final int p52); + } + + interface I1 { + void m1(int p41); + + void m2(final int p42); + } + + static class C2 { + C2(int p21) { + }// 29 + + void m1(int p22) { + }// 30 + + static void m2(int p23) { + }// 31 + } + + class C1 { + C1(final int this$0) { + }// 24 + + void m(int p12) { + }// 25 + } +} + +class 'decompiler/TestMethodParametersAttr' { + method ' (I)V' { + 4 4 + } + + method 'm1 (I)V' { + 0 7 + } + + method 'm2 (I)V' { + 0 10 + } + + method 'local ()V' { + 0 21 + } +} + +class 'decompiler/TestMethodParametersAttr$1Local' { + method ' (Ldecompiler/TestMethodParametersAttr;I)V' { + 9 15 + } + + method 'm (I)V' { + 0 18 + } +} + +class 'decompiler/TestMethodParametersAttr$C2' { + method ' (I)V' { + 4 43 + } + + method 'm1 (I)V' { + 0 46 + } + + method 'm2 (I)V' { + 0 49 + } +} + +class 'decompiler/TestMethodParametersAttr$C1' { + method ' (Ldecompiler/TestMethodParametersAttr;I)V' { + 9 54 + } + + method 'm (I)V' { + 0 57 + } +} + +Lines mapping: +19 <-> 5 +20 <-> 8 +21 <-> 11 +24 <-> 55 +25 <-> 58 +29 <-> 44 +30 <-> 47 +31 <-> 50 +36 <-> 16 +37 <-> 19 +39 <-> 22 diff --git a/plugins/java-decompiler/engine/testData/src/pkg/TestMethodParametersAttr.java b/plugins/java-decompiler/engine/testData/src/pkg/TestMethodParametersAttr.java new file mode 100644 index 000000000000..b98fc0b3acb7 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/pkg/TestMethodParametersAttr.java @@ -0,0 +1,56 @@ +/* + * 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 decompiler; + +// compile with java 8: javap -parameters TestMethodParametersAttr.java +public class TestMethodParametersAttr { + TestMethodParametersAttr(int p01) { } + void m1(int p02) { } + static void m2(int p03) { } + + class C1 { + C1(int p11) { } + void m(int p12) { } + } + + static class C2 { + C2(int p21) { } + void m1(int p22) { } + static void m2(int p23) { } + } + + void local() { + class Local { + Local(int p31) { } + void m(int p32) { } + } + } + + interface I1 { + void m1(int p41); + void m2(final int p42); + } + + abstract class C3 { + abstract void m1(int p51); + abstract void m2(final int p52); + } + + static abstract class C4 { + abstract void m1(int p51); + abstract void m2(final int p52); + } +} \ No newline at end of file From d663c0af1fe6c0f3c1b8de68f7e4cf90e81609b0 Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Wed, 10 Jan 2018 16:44:01 +0300 Subject: [PATCH 03/33] IDEA-184560 Java decompiler doesn't use stored parameter names - fixed param idx --- .../org/jetbrains/java/decompiler/main/ClassWriter.java | 8 ++++---- .../engine/testData/results/TestMethodParametersAttr.dec | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java index 8d862c81c547..5d9066868869 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -716,8 +716,8 @@ public class ClassWriter { appendParameterAnnotations(buffer, mt, paramCount); - if (methodParameters != null && paramCount < methodParameters.size()) { - appendModifiers(buffer, methodParameters.get(paramCount).myAccessFlags, CodeConstants.ACC_FINAL, isInterface, 0); + if (methodParameters != null && i < methodParameters.size()) { + appendModifiers(buffer, methodParameters.get(i).myAccessFlags, CodeConstants.ACC_FINAL, isInterface, 0); } else if (methodWrapper.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarTypeProcessor.VAR_EXPLICIT_FINAL) { buffer.append("final "); @@ -755,8 +755,8 @@ public class ClassWriter { buffer.append(' '); String parameterName; - if (methodParameters != null && paramCount < methodParameters.size()) { - parameterName = methodParameters.get(paramCount).myName; + if (methodParameters != null && i < methodParameters.size()) { + parameterName = methodParameters.get(i).myName; } else { parameterName = methodWrapper.varproc.getVarName(new VarVersionPair(index, 0)); diff --git a/plugins/java-decompiler/engine/testData/results/TestMethodParametersAttr.dec b/plugins/java-decompiler/engine/testData/results/TestMethodParametersAttr.dec index ba00341fd402..a48380b577c6 100644 --- a/plugins/java-decompiler/engine/testData/results/TestMethodParametersAttr.dec +++ b/plugins/java-decompiler/engine/testData/results/TestMethodParametersAttr.dec @@ -12,7 +12,7 @@ public class TestMethodParametersAttr { void local() { class Local { - Local(final int this$0) { + Local(int p31) { }// 36 void m(int p32) { @@ -51,7 +51,7 @@ public class TestMethodParametersAttr { } class C1 { - C1(final int this$0) { + C1(int p11) { }// 24 void m(int p12) { From fb27ac66643912b611c824d3520c33d6686a8f11 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 10 Jan 2018 13:36:37 +0100 Subject: [PATCH 04/33] print thread dump when leak is detected in tests maybe this'll help with diagnosing leaks via ProgressManager.threadsUnderIndicator --- .../testFramework/src/com/intellij/testFramework/LeakHunter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/testFramework/src/com/intellij/testFramework/LeakHunter.java b/platform/testFramework/src/com/intellij/testFramework/LeakHunter.java index dd3ff8dfa771..814e4c0a7a02 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LeakHunter.java +++ b/platform/testFramework/src/com/intellij/testFramework/LeakHunter.java @@ -65,6 +65,7 @@ public class LeakHunter { backLink; System.out.println(message); System.out.println(";-----"); + UsefulTestCase.printThreadDump(); throw new AssertionError(message); }); From 80875741b8cb92371205b205c91d1d7d6ee5999e Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 10 Jan 2018 14:36:01 +0100 Subject: [PATCH 05/33] IDEA-174659 Autocomplete generic parameters according to type restriction --- .../completion/PreferByKindWeigher.java | 35 ++++++++++++++++--- .../PreferExpectedTypeArguments.java | 8 +++++ .../NormalCompletionOrderingTest.groovy | 4 +++ 3 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normalSorting/PreferExpectedTypeArguments.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java index 7bb994ddea86..4f228d0c875f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java @@ -35,6 +35,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Set; import java.util.function.Function; @@ -115,16 +116,40 @@ public class PreferByKindWeigher extends LookupElementWeigher { return psiClass -> preferClassIf(InheritanceUtil.isInheritor(psiClass, CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE)); } - if (psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiAnnotation.class).accepts(position)) { - final PsiAnnotation annotation = PsiTreeUtil.getParentOfType(position, PsiAnnotation.class); - assert annotation != null; - final PsiAnnotation.TargetType[] targets = AnnotationTargetUtil.getTargetsForLocation(annotation.getOwner()); - return psiClass -> preferClassIf(psiClass.isAnnotationType() && AnnotationTargetUtil.findAnnotationTarget(psiClass, targets) != null); + PsiElement parent = position.getParent(); + if (parent instanceof PsiJavaCodeReferenceElement) { + PsiElement refParent = parent.getParent(); + if (refParent instanceof PsiAnnotation) { + PsiAnnotation.TargetType[] targets = AnnotationTargetUtil.getTargetsForLocation(((PsiAnnotation)refParent).getOwner()); + return psiClass -> preferClassIf(psiClass.isAnnotationType() && AnnotationTargetUtil.findAnnotationTarget(psiClass, targets) != null); + } + if (refParent instanceof PsiTypeElement) { + List bounds = getTypeBounds((PsiTypeElement)refParent); + return psiClass -> preferClassIf(ContainerUtil.exists(bounds, bound -> InheritanceUtil.isInheritorOrSelf(psiClass, bound, true))); + } } return aClass -> MyResult.classNameOrGlobalStatic; } + private static List getTypeBounds(PsiTypeElement typeElement) { + PsiElement typeParent = typeElement.getParent(); + if (typeParent instanceof PsiReferenceParameterList) { + int index = Arrays.asList(((PsiReferenceParameterList)typeParent).getTypeParameterElements()).indexOf(typeElement); + PsiElement listParent = typeParent.getParent(); + if (index >= 0 && listParent instanceof PsiJavaCodeReferenceElement) { + PsiElement target = ((PsiJavaCodeReferenceElement)listParent).resolve(); + if (target instanceof PsiClass) { + PsiTypeParameter[] typeParameters = ((PsiClass)target).getTypeParameters(); + if (index < typeParameters.length) { + return ContainerUtil.mapNotNull(typeParameters[index].getExtendsListTypes(), PsiUtil::resolveClassInType); + } + } + } + } + return Collections.emptyList(); + } + static boolean isExceptionPosition(PsiElement position) { return IN_CATCH_TYPE.accepts(position) || IN_MULTI_CATCH_TYPE.accepts(position) || INSIDE_METHOD_THROWS_CLAUSE.accepts(position) || diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/PreferExpectedTypeArguments.java b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferExpectedTypeArguments.java new file mode 100644 index 000000000000..66f973fb6fe4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferExpectedTypeArguments.java @@ -0,0 +1,8 @@ +public class BlaExecutor implements BasicExecutor> { +} + +interface BasicExecutor { +} + +class BlaOperation extends Exception { +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionOrderingTest.groovy index c701a284ecf2..e435ff793d02 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionOrderingTest.groovy @@ -845,4 +845,8 @@ class Foo { checkPreferredItems 0, 'IllegalArgumentException', 'IllegalAccessException', 'IllegalStateException' } + void testPreferExpectedTypeArguments() { + checkPreferredItems 0, 'BlaOperation' + } + } From 6344776383ec548dd6888aa92e6ebc5e372c269a Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 10 Jan 2018 14:44:03 +0100 Subject: [PATCH 06/33] another attempt to fix flaky JavaAutoPopupTest --- .../java/codeInsight/completion/JavaAutoPopupTest.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/JavaAutoPopupTest.groovy index 4073e8557807..c08662c140ca 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/JavaAutoPopupTest.groovy @@ -1775,6 +1775,7 @@ class Foo { myFixture.addClass("package foo.bar.goo; class Foo {}") myFixture.configureByText "a.java", "class Foo { { foo.b } }" def items = myFixture.completeBasic() + joinCompletion() if (items != null) { // completion took a bit longer, and the single item wasn't inserted automatically assert myFixture.lookupElementStrings == ['bar'] myFixture.type('\n') From bd93a780b878e400263a1eeff1c6e9e73d138635 Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Wed, 10 Jan 2018 14:49:26 +0100 Subject: [PATCH 07/33] preserve imports specified in test templates during optimize on-the-fly IDEA-90048;IDEA-131092 --- .../impl/analysis/ImportsHighlightUtil.java | 5 ++++ .../analysis/PostHighlightingVisitor.java | 8 +++++-- .../createTest/JavaTestGenerator.java | 24 ++++++++++++++++++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ImportsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ImportsHighlightUtil.java index 0f01b0b5a978..83cc13c98a3f 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ImportsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ImportsHighlightUtil.java @@ -17,12 +17,17 @@ package com.intellij.codeInsight.daemon.impl.analysis; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; +import com.intellij.openapi.util.Key; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiImportStaticStatement; import com.intellij.psi.PsiJavaCodeReferenceElement; import com.intellij.util.ObjectUtils; +import java.util.Set; + public class ImportsHighlightUtil { + public static final Key> IMPORTS_FROM_TEMPLATE = Key.create("IMPORT_FROM_FILE_TEMPLATE"); + static HighlightInfo checkStaticOnDemandImportResolvesToClass(PsiImportStaticStatement statement) { if (statement.isOnDemand() && statement.resolveTargetClass() == null) { PsiJavaCodeReferenceElement ref = statement.getImportReference(); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/PostHighlightingVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/PostHighlightingVisitor.java index 4244fe5c1c1e..2253caaed122 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/PostHighlightingVisitor.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/PostHighlightingVisitor.java @@ -30,6 +30,7 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.PomNamedTarget; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.*; @@ -532,14 +533,17 @@ class PostHighlightingVisitor { } private HighlightInfo registerRedundantImport(@NotNull PsiImportStatementBase importStatement, @NotNull HighlightDisplayKey unusedImportKey) { - String description = InspectionsBundle.message("unused.import.statement"); + VirtualFile file = PsiUtilCore.getVirtualFile(myFile); + Set imports = file != null ? file.getCopyableUserData(ImportsHighlightUtil.IMPORTS_FROM_TEMPLATE) : null; + boolean predefinedImport = imports != null && imports.contains(importStatement.getText()); + String description = !predefinedImport ? InspectionsBundle.message("unused.import.statement") : "Unused import (specified in template)"; HighlightInfo info = HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.UNUSED_IMPORT).range(importStatement).descriptionAndTooltip(description) .create(); QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createOptimizeImportsFix(false), unusedImportKey); QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createEnableOptimizeImportsOnTheFlyFix(), unusedImportKey); - myHasRedundantImports = true; + if (!predefinedImport) myHasRedundantImports = true; return info; } } diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/JavaTestGenerator.java b/java/java-impl/src/com/intellij/testIntegration/createTest/JavaTestGenerator.java index bb3d40acf407..19670da00abd 100644 --- a/java/java-impl/src/com/intellij/testIntegration/createTest/JavaTestGenerator.java +++ b/java/java-impl/src/com/intellij/testIntegration/createTest/JavaTestGenerator.java @@ -18,6 +18,7 @@ package com.intellij.testIntegration.createTest; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.CodeInsightUtil; import com.intellij.codeInsight.FileModificationService; +import com.intellij.codeInsight.daemon.impl.analysis.ImportsHighlightUtil; import com.intellij.codeInsight.template.Template; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateDescriptor; @@ -31,10 +32,12 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.GlobalSearchScopesCore; +import com.intellij.psi.util.PsiUtilCore; import com.intellij.refactoring.util.classMembers.MemberInfo; import com.intellij.testIntegration.TestFramework; import com.intellij.testIntegration.TestIntegrationUtils; @@ -70,7 +73,8 @@ public class JavaTestGenerator implements TestGenerator { addSuperClass(targetClass, project, superClassName); } - Editor editor = CodeInsightUtil.positionCursorAtLBrace(project, targetClass.getContainingFile(), targetClass); + PsiFile file = targetClass.getContainingFile(); + Editor editor = CodeInsightUtil.positionCursorAtLBrace(project, file, targetClass); addTestMethods(editor, targetClass, d.getTargetClass(), @@ -78,6 +82,24 @@ public class JavaTestGenerator implements TestGenerator { d.getSelectedMethods(), d.shouldGeneratedBefore(), d.shouldGeneratedAfter()); + + if (file instanceof PsiJavaFile) { + PsiImportList list = ((PsiJavaFile)file).getImportList(); + if (list != null) { + PsiImportStatementBase[] importStatements = list.getAllImportStatements(); + if (importStatements.length > 0) { + VirtualFile virtualFile = PsiUtilCore.getVirtualFile(list); + if (virtualFile != null) { + Set imports = new HashSet<>(); + for (PsiImportStatementBase base : importStatements) { + imports.add(base.getText()); + } + virtualFile.putCopyableUserData(ImportsHighlightUtil.IMPORTS_FROM_TEMPLATE, imports); + } + } + } + } + return targetClass; } catch (IncorrectOperationException e) { From 3099caa87295782d945a18f4eebe7a2d2720d10c Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Wed, 10 Jan 2018 12:53:44 +0300 Subject: [PATCH 08/33] PyCharm doesn't allow to finish input (PY-27881) Update communication after console view creation and add check for nullability --- .../python/console/PydevConsoleCommunication.java | 10 ++++++---- .../python/console/PydevConsoleRunnerImpl.java | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java index ce636e5447a8..ac3535b99bd9 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java @@ -108,7 +108,7 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl private PythonDebugConsoleCommunication myDebugCommunication; private boolean myNeedsMore = false; - private PythonConsoleView myConsoleView; + private @Nullable PythonConsoleView myConsoleView; private List myFrameListeners = ContainerUtil.createLockFreeCopyOnWriteList(); /** @@ -234,7 +234,9 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl return execNotifyAboutMagic(params); } else if ("ShowConsole".equals(method)) { - myConsoleView.setConsoleEnabled(true); + if (myConsoleView != null) { + myConsoleView.setConsoleEnabled(true); + } return ""; } else { @@ -401,7 +403,7 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl return; //TODO: handle text input and other cases } nextResponse = null; - if (waitingForInput && myConsoleView.isInitialized()) { + if (waitingForInput && myConsoleView != null && myConsoleView.isInitialized()) { inputReceived = command.getText(); waitingForInput = false; //the thread that we started in the last exec is still alive if we were waiting for an input. @@ -791,7 +793,7 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl } } - public void setConsoleView(PythonConsoleView consoleView) { + public void setConsoleView(@Nullable PythonConsoleView consoleView) { myConsoleView = consoleView; } diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunnerImpl.java b/python/src/com/jetbrains/python/console/PydevConsoleRunnerImpl.java index a2fd4a56d806..c5d19c763988 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleRunnerImpl.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleRunnerImpl.java @@ -607,8 +607,9 @@ public class PydevConsoleRunnerImpl implements PydevConsoleRunner { // Init console view myConsoleView = createConsoleView(); if (myConsoleView != null) { - ((JComponent)myConsoleView).setBorder(new SideBorder(JBColor.border(), SideBorder.LEFT)); + myConsoleView.setBorder(new SideBorder(JBColor.border(), SideBorder.LEFT)); } + myPydevConsoleCommunication.setConsoleView(myConsoleView); myProcessHandler = createProcessHandler(process); myConsoleExecuteActionHandler = createExecuteActionHandler(); From 7bfec71a7eb6fb7d5e1b26190d73518a3f552aad Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 9 Jan 2018 17:14:04 +0100 Subject: [PATCH 09/33] send stats about pause indexing --- .../openapi/wm/impl/status/InfoAndProgressPanel.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java index d6044cc1b12b..908735128074 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java @@ -1,9 +1,12 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ package com.intellij.openapi.wm.impl.status; import com.intellij.icons.AllIcons; import com.intellij.ide.PowerSaveMode; import com.intellij.idea.ActionsBundle; +import com.intellij.internal.statistic.customUsageCollectors.actions.ActionsCollector; import com.intellij.notification.EventLog; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionGroup; @@ -687,6 +690,7 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge ProgressSuspender suspender = Objects.requireNonNull(getSuspender()); suspender.setSuspended(!suspender.isSuspended()); updateProgressNow(); + ActionsCollector.getInstance().record(suspender.isSuspended() ? "Progress Paused" : "Progress Resumed"); }).setFillBg(false); suspendButton.setVisible(false); From 51047aa9f771894b80f64dbb840d969605d235f8 Mon Sep 17 00:00:00 2001 From: Ivan Bessonov Date: Wed, 10 Jan 2018 18:14:55 +0300 Subject: [PATCH 10/33] IDEA-183887 maven - proper handling of working directory in Select Maven Goal dialog --- .../execution/MavenRunnerParametersPanel.java | 11 ++++------ .../tasks/MavenBeforeRunTasksProvider.java | 21 ++++++++++++++++++- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParametersPanel.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParametersPanel.java index 85518fbf0818..0bcaa0d1e2f6 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParametersPanel.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParametersPanel.java @@ -20,12 +20,10 @@ import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.execution.configurations.ParametersList; import com.intellij.icons.AllIcons; import com.intellij.openapi.externalSystem.service.execution.cmd.ParametersListLexer; -import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.FixedSizeButton; import com.intellij.openapi.ui.LabeledComponent; import com.intellij.openapi.ui.TextFieldWithBrowseButton; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.EditorTextField; import com.intellij.ui.PanelWithAnchor; import com.intellij.ui.components.JBLabel; @@ -33,7 +31,6 @@ import com.intellij.util.TextFieldCompletionProvider; import com.intellij.util.execution.ParametersListUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.utils.MavenUtil; import javax.swing.*; import java.util.LinkedHashMap; @@ -117,10 +114,10 @@ public class MavenRunnerParametersPanel implements PanelWithAnchor { data.setWorkingDirPath(workingDirComponent.getComponent().getText()); List commandLine = ParametersListUtil.parse(goalsComponent.getComponent().getText()); - int pomFileNameIndex = commandLine.indexOf("-f"); - if (pomFileNameIndex != -1) { - if (pomFileNameIndex + 1 < commandLine.size()) { - data.setPomFileName(commandLine.remove(pomFileNameIndex + 1)); + int pomFileNameIndex = 1 + commandLine.indexOf("-f"); + if (pomFileNameIndex != 0) { + if (pomFileNameIndex < commandLine.size()) { + data.setPomFileName(commandLine.remove(pomFileNameIndex)); } commandLine.remove(pomFileNameIndex); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java index 0f9c318fba53..bd1fdbbfa28c 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java @@ -30,6 +30,7 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.PathUtil; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.execution.ParametersListUtil; import icons.MavenIcons; @@ -38,6 +39,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.execution.MavenEditGoalDialog; import org.jetbrains.idea.maven.execution.MavenRunner; import org.jetbrains.idea.maven.execution.MavenRunnerParameters; +import org.jetbrains.idea.maven.model.MavenConstants; import org.jetbrains.idea.maven.model.MavenExplicitProfiles; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; @@ -91,6 +93,11 @@ public class MavenBeforeRunTasksProvider extends BeforeRunTaskProvider commandLine = ParametersListUtil.parse(goals); + int pomFileNameIndex = 1 + commandLine.indexOf("-f"); + if (pomFileNameIndex != 0 && pomFileNameIndex < commandLine.size()) { + return commandLine.get(pomFileNameIndex); + } + } + return MavenConstants.POM_XML; + } } From bc2cbc9b73cbaca5670f30f7482b2ccc182be087 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 10 Jan 2018 11:43:34 +0300 Subject: [PATCH 11/33] resource bundles: fix npe while accessing invalid property node (EA-114674 - NPE: ResourceBundleEditor.) --- ...rceBundlePropertyStructureViewElement.java | 29 +++++++++---------- .../editor/ResourceBundleEditor.java | 23 +++++---------- ...ResourceBundleFromEditorRenameHandler.java | 18 ++---------- 3 files changed, 23 insertions(+), 47 deletions(-) diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java index 53cb8793d1b3..875256b3263c 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java @@ -1,17 +1,5 @@ /* - * 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. + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ package com.intellij.lang.properties.editor; @@ -29,6 +17,7 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Pair; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.PlatformIcons; import org.jetbrains.annotations.NotNull; @@ -41,6 +30,7 @@ public class ResourceBundlePropertyStructureViewElement implements StructureView private static final TextAttributesKey GROUP_KEY; public static final String PROPERTY_GROUP_KEY_TEXT = ""; + @NotNull private final IProperty myProperty; private String myPresentableName; @@ -53,12 +43,19 @@ public class ResourceBundlePropertyStructureViewElement implements StructureView private volatile InspectedPropertyProblems myInspectedPropertyProblems; - public ResourceBundlePropertyStructureViewElement(IProperty property) { + public ResourceBundlePropertyStructureViewElement(@NotNull IProperty property) { myProperty = property; } + @Nullable public IProperty getProperty() { - return myProperty.getPsiElement().isValid() ? myProperty : null; + return getPsiElement() != null ? myProperty : null; + } + + @Nullable + public PsiElement getPsiElement() { + PsiElement element = myProperty.getPsiElement(); + return element.isValid() ? element : null; } @NotNull @@ -124,7 +121,7 @@ public class ResourceBundlePropertyStructureViewElement implements StructureView final TextAttributesKey baseAttrKey = (myPresentableName != null && myPresentableName.isEmpty()) ? GROUP_KEY : PropertiesHighlighter.PROPERTY_KEY; final TextAttributes baseAttrs = colorsScheme.getAttributes(baseAttrKey); - if (getProperty().getPsiElement().isValid()) { + if (getPsiElement() != null) { if (myInspectedPropertyProblems != null) { TextAttributes highlightingAttributes = myInspectedPropertyProblems.getTextAttributes(colorsScheme); if (highlightingAttributes != null) { diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java index 2c5201c8cef9..63d2a20bb164 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java @@ -1,17 +1,5 @@ /* - * Copyright 2000-2016 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. + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ package com.intellij.lang.properties.editor; @@ -205,8 +193,11 @@ public class ResourceBundleEditor extends UserDataHolderBase implements Document TreeElement[] children = myStructureViewComponent.getTreeModel().getRoot().getChildren(); if (children.length != 0) { TreeElement child = children[0]; - String propName = ((ResourceBundlePropertyStructureViewElement)child).getProperty().getUnescapedKey(); - setState(new ResourceBundleEditorState(propName)); + IProperty property = ((ResourceBundlePropertyStructureViewElement)child).getProperty(); + if (property != null) { + String propName = property.getUnescapedKey(); + setState(new ResourceBundleEditorState(propName)); + } } myDataProviderPanel = new DataProviderPanel(splitPanel); @@ -302,7 +293,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements Document while (!toCheck.isEmpty()) { TreeElement element = toCheck.pop(); PsiElement value = element instanceof ResourceBundlePropertyStructureViewElement - ? ((ResourceBundlePropertyStructureViewElement)element).getProperty().getPsiElement() + ? ((ResourceBundlePropertyStructureViewElement)element).getPsiElement() : null; if (value != null) { final IProperty property = PropertiesImplUtil.getProperty(value); diff --git a/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java b/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java index 5f024813582f..8f09df86e8ee 100644 --- a/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java +++ b/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java @@ -1,17 +1,5 @@ /* - * 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. + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ /** @@ -82,7 +70,7 @@ public class ResourceBundleFromEditorRenameHandler implements RenameHandler { group.getPresentableName(), group.getPrefix().length() - group.getPresentableName().length()); } else if (selectedElement instanceof ResourceBundlePropertyStructureViewElement) { - final PsiElement psiElement = ((ResourceBundlePropertyStructureViewElement)selectedElement).getProperty().getPsiElement(); + final PsiElement psiElement = ((ResourceBundlePropertyStructureViewElement)selectedElement).getPsiElement(); ResourceBundleRenameUtil.renameResourceBundleKey(psiElement, project); } else if (selectedElement instanceof ResourceBundleFileStructureViewElement) { ResourceBundleRenameUtil.renameResourceBundleBaseName(((ResourceBundleFileStructureViewElement)selectedElement).getValue(), project); @@ -104,7 +92,7 @@ public class ResourceBundleFromEditorRenameHandler implements RenameHandler { return ((PropertiesStructureViewElement)treeElement).getValue().getPsiElement(); } if (treeElement instanceof ResourceBundlePropertyStructureViewElement) { - return ((ResourceBundlePropertyStructureViewElement)treeElement).getProperty().getPsiElement(); + return ((ResourceBundlePropertyStructureViewElement)treeElement).getPsiElement(); } return null; }); From be42ae25d9a87420ba0118b80d42b820b5974c60 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 10 Jan 2018 11:48:57 +0300 Subject: [PATCH 12/33] resource bundles: fix npe while accessing invalid property node (EA-114673 - NPE: ResourceBundleEditor.setStructureViewSelection) --- .../lang/properties/PropertiesImplUtil.java | 9 ++++--- .../editor/PropertiesCopyHandler.java | 15 ++--------- .../editor/ResourceBundleEditor.java | 15 +++++------ .../rename/RenamePropertyProcessor.java | 25 ++++++------------- 4 files changed, 21 insertions(+), 43 deletions(-) diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java index 5f442ddb9855..202b9d635f82 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java @@ -1,6 +1,6 @@ -// Copyright 2000-2017 JetBrains s.r.o. -// Use of this source code is governed by the Apache 2.0 license that can be -// found in the LICENSE file. +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ package com.intellij.lang.properties; import com.intellij.lang.properties.psi.PropertiesFile; @@ -180,7 +180,8 @@ public class PropertiesImplUtil extends PropertiesUtil { return true; } - public static IProperty getProperty(PsiElement element) { + @Nullable + public static IProperty getProperty(@Nullable PsiElement element) { if (element instanceof IProperty) { return (IProperty)element; } diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/PropertiesCopyHandler.java b/plugins/properties/src/com/intellij/lang/properties/editor/PropertiesCopyHandler.java index 1f420f9fcf97..26d1e7a55fcc 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/PropertiesCopyHandler.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/PropertiesCopyHandler.java @@ -1,17 +1,5 @@ /* - * Copyright 2000-2015 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. + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ package com.intellij.lang.properties.editor; @@ -96,6 +84,7 @@ public class PropertiesCopyHandler extends CopyHandlerDelegateBase { @Override public void doCopy(PsiElement[] elements, PsiDirectory defaultTargetDirectory) { final IProperty representative = PropertiesImplUtil.getProperty(elements[0]); + if (representative == null) return; final String key = representative.getKey(); if (key == null) { return; diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java index 63d2a20bb164..7e60c062936a 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java @@ -295,15 +295,12 @@ public class ResourceBundleEditor extends UserDataHolderBase implements Document PsiElement value = element instanceof ResourceBundlePropertyStructureViewElement ? ((ResourceBundlePropertyStructureViewElement)element).getPsiElement() : null; - if (value != null) { - final IProperty property = PropertiesImplUtil.getProperty(value); - if (propertyName.equals(property.getUnescapedKey())) { - myStructureViewComponent.select(property, true); - selectionChanged(); - return; - } - } - else { + final IProperty property = PropertiesImplUtil.getProperty(value); + if (property != null && propertyName.equals(property.getUnescapedKey())) { + myStructureViewComponent.select(property, true); + selectionChanged(); + return; + } else { for (TreeElement treeElement : element.getChildren()) { toCheck.push(treeElement); } diff --git a/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/RenamePropertyProcessor.java b/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/RenamePropertyProcessor.java index 7078958d5986..927f0c020b8d 100644 --- a/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/RenamePropertyProcessor.java +++ b/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/RenamePropertyProcessor.java @@ -1,17 +1,5 @@ /* - * 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. + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ package com.intellij.lang.properties.refactoring.rename; @@ -33,6 +21,7 @@ import org.jetbrains.annotations.NotNull; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; public class RenamePropertyProcessor extends RenamePsiElementProcessor { @Override @@ -44,15 +33,17 @@ public class RenamePropertyProcessor extends RenamePsiElementProcessor { @Override public void prepareRenaming(final PsiElement element, final String newName, final Map allRenames) { - ResourceBundle resourceBundle = PropertiesImplUtil.getProperty(element).getPropertiesFile().getResourceBundle(); + ResourceBundle resourceBundle = Objects.requireNonNull(PropertiesImplUtil.getProperty(element)).getPropertiesFile().getResourceBundle(); final Map allRenamesCopy = new LinkedHashMap<>(allRenames); allRenames.clear(); allRenamesCopy.forEach((key, value) -> { final IProperty property = PropertiesImplUtil.getProperty(key); - final List properties = PropertiesUtil.findAllProperties(resourceBundle, property.getUnescapedKey()); - for (final IProperty toRename : properties) { - allRenames.put(toRename.getPsiElement(), value); + if (property != null) { + final List properties = PropertiesUtil.findAllProperties(resourceBundle, property.getUnescapedKey()); + for (final IProperty toRename : properties) { + allRenames.put(toRename.getPsiElement(), value); + } } }); } From 55c8407e58c16932362f90105e84ed22745ab3e8 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 10 Jan 2018 13:32:44 +0300 Subject: [PATCH 13/33] add logging for (EA-114577 - assert: AnalysisScope.displayProjectRelativePath) --- .../src/com/intellij/slicer/SliceHandler.java | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/slicer/SliceHandler.java b/platform/lang-impl/src/com/intellij/slicer/SliceHandler.java index 3a81c2c9b471..6f3fee6f1622 100644 --- a/platform/lang-impl/src/com/intellij/slicer/SliceHandler.java +++ b/platform/lang-impl/src/com/intellij/slicer/SliceHandler.java @@ -1,17 +1,5 @@ /* - * Copyright 2000-2016 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. + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ package com.intellij.slicer; @@ -21,6 +9,7 @@ import com.intellij.analysis.BaseAnalysisActionDialog; import com.intellij.codeInsight.CodeInsightActionHandler; import com.intellij.codeInsight.TargetElementUtil; import com.intellij.codeInsight.hint.HintManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; @@ -34,6 +23,7 @@ import org.jetbrains.annotations.Nullable; * @author cdr */ public class SliceHandler implements CodeInsightActionHandler { + private static final Logger LOG = Logger.getInstance(SliceHandler.class); private final boolean myDataFlowToThis; public SliceHandler(boolean dataFlowToThis) { @@ -48,6 +38,12 @@ public class SliceHandler implements CodeInsightActionHandler { return; } + if (!expression.isPhysical()) { + PsiFile expressionFile = expression.getContainingFile(); + LOG.error("Analyzed entity should be physical. " + + "Analyzed element: " + expression.getText() + " (class = " + expression.getClass() + "), file = " + file + + " expression file = " + expressionFile + " (class = " + expressionFile.getClass() + ")"); + } SliceManager sliceManager = SliceManager.getInstance(project); sliceManager.slice(expression,myDataFlowToThis, this); } From ae41503b388349b434b91b7ce63626923064b468 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 10 Jan 2018 13:36:41 +0300 Subject: [PATCH 14/33] do not invoke vfs refresh in idea open api class finder (EA-113940) --- .../intellij/structuralsearch/IdeaOpenApiClassFinder.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/IdeaOpenApiClassFinder.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/IdeaOpenApiClassFinder.java index f952ac5bb23e..2b87077c1d9d 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/IdeaOpenApiClassFinder.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/IdeaOpenApiClassFinder.java @@ -1,4 +1,6 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ package com.intellij.structuralsearch; import com.intellij.openapi.application.PathManager; @@ -31,7 +33,7 @@ public class IdeaOpenApiClassFinder extends NonClasspathClassFinder { .map(PathManager::getJarPathForClass) .filter(Objects::nonNull) .map(File::new) - .map(lfs::refreshAndFindFileByIoFile) + .map(lfs::findFileByIoFile) .collect(Collectors.toList()); } From 08955bb3a36c1344bc6fc7ea3ed5aab3ccc866d7 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 10 Jan 2018 13:40:59 +0300 Subject: [PATCH 15/33] resource bundle editor: fix NPE while accessing invalid property node (EA-114554 - NPE: ResourceBundleEditorHighlighter$ResourceBundleEditorHighlightingPass.collectInformation) --- .../ResourceBundleEditorHighlighter.java | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditorHighlighter.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditorHighlighter.java index 01f0f069cbb0..865958983bf0 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditorHighlighter.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditorHighlighter.java @@ -1,17 +1,5 @@ /* - * Copyright 2000-2016 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. + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ package com.intellij.lang.properties.editor; @@ -101,9 +89,10 @@ public class ResourceBundleEditorHighlighter implements BackgroundEditorHighligh while (!queue.isEmpty()) { final TreeElement treeElement = queue.pullFirst(); if (treeElement instanceof ResourceBundlePropertyStructureViewElement) { - ResourceBundlePropertyStructureViewElement node = (ResourceBundlePropertyStructureViewElement)treeElement; - final String key = node.getProperty().getKey(); - LOG.assertTrue(key != null); + IProperty property = ((ResourceBundlePropertyStructureViewElement)treeElement).getProperty(); + if (property == null) continue; + final String key = property.getKey(); + if (key == null) continue; SortedSet highlightTypes = new TreeSet<>(Comparator.comparing(t -> t.getSeverity(null))); List> allDescriptors = new SmartList<>(); @@ -124,7 +113,7 @@ public class ResourceBundleEditorHighlighter implements BackgroundEditorHighligh } } } - node.setInspectedPropertyProblems(allDescriptors.isEmpty() + ((ResourceBundlePropertyStructureViewElement)treeElement).setInspectedPropertyProblems(allDescriptors.isEmpty() ? null : new InspectedPropertyProblems(allDescriptors.toArray(new Pair[allDescriptors.size()]), highlightTypes)); From 89e0ae46221174f35040060c56daf6abeeb2ef1b Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 10 Jan 2018 17:38:12 +0300 Subject: [PATCH 16/33] offline inspection results for injected code are always invalid (IDEA-184655) --- .../OfflineDescriptorResolveResult.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineDescriptorResolveResult.java b/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineDescriptorResolveResult.java index f62f3fc88962..acae0abd8b1a 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineDescriptorResolveResult.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineDescriptorResolveResult.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ package com.intellij.codeInspection.offlineViewer; @@ -16,10 +16,12 @@ import com.intellij.codeInspection.reference.RefEntity; import com.intellij.codeInspection.reference.RefModule; import com.intellij.codeInspection.ui.InspectionToolPresentation; import com.intellij.lang.Language; +import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -140,7 +142,20 @@ class OfflineDescriptorResolveResult { final PsiElementVisitor visitor = localTool.buildVisitor(holder, true, session); localTool.inspectionStarted(session, false); final PsiElement[] elementsInRange = getElementsIntersectingRange(containingFile, startOffset, endOffset); + InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(context.getProject()); for (PsiElement element : elementsInRange) { + List> injectedPsiFiles = injectedLanguageManager.getInjectedPsiFiles(element); + if (injectedPsiFiles != null) { + for (Pair file : injectedPsiFiles) { + file.getFirst().accept(new PsiRecursiveElementWalkingVisitor() { + @Override + public void visitElement(PsiElement element) { + element.accept(visitor); + super.visitElement(element); + } + }); + } + } element.accept(visitor); } localTool.inspectionFinished(session, holder); From 0312d06939a7422968c6ef563c152d3052c06634 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Wed, 10 Jan 2018 18:44:06 +0300 Subject: [PATCH 17/33] Build view: merge frequent edt events --- .../intellij/build/BuildTreeConsoleView.java | 17 +++++++---------- .../impl/src/com/intellij/build/BuildView.java | 7 +++---- .../com/intellij/build/MultipleBuildsView.java | 14 +++++++++++--- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java b/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java index c6149106cccf..ce334d150056 100644 --- a/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java +++ b/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java @@ -31,10 +31,10 @@ import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns; import com.intellij.ui.treeStructure.treetable.TreeColumnInfo; import com.intellij.ui.treeStructure.treetable.TreeTable; import com.intellij.ui.treeStructure.treetable.TreeTableTree; -import com.intellij.util.Alarm; import com.intellij.util.EditSourceOnDoubleClickHandler; import com.intellij.util.EditSourceOnEnterKeyHandler; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.TransferToEDTQueue; import com.intellij.util.text.DateFormatUtil; import com.intellij.util.ui.ColumnInfo; import com.intellij.util.ui.UIUtil; @@ -70,7 +70,6 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon private final SimpleTreeBuilder myBuilder; private final Map nodesMap = ContainerUtil.newConcurrentMap(); private final ExecutionNodeProgressAnimator myProgressAnimator; - private Set myRequests = Collections.synchronizedSet(new HashSet()); private final Project myProject; private final SimpleTreeStructure myTreeStructure; @@ -79,7 +78,8 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon private final String myWorkingDir; private volatile int myTimeColumnWidth; private final AtomicBoolean myDisposed = new AtomicBoolean(); - private final Alarm myUpdateTreeAlarm; + private final TransferToEDTQueue myLaterInvocator = + TransferToEDTQueue.createRunnableMerger("BuildTreeConsoleView later invocator"); public BuildTreeConsoleView(Project project, BuildDescriptor buildDescriptor) { myProject = project; @@ -209,7 +209,6 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon myPanel.add(myThreeComponentsSplitter, BorderLayout.CENTER); myProgressAnimator = new ExecutionNodeProgressAnimator(this); - myUpdateTreeAlarm = new Alarm(this); } private ExecutionNode getRootElement() { @@ -418,16 +417,14 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon } void scheduleUpdate(ExecutionNode executionNode) { - final Update update = new Update(executionNode) { + SimpleNode node = executionNode.getParent() == null ? executionNode : executionNode.getParent(); + final Update update = new Update(node) { @Override public void run() { - myRequests.remove(this); - myBuilder.queueUpdateFrom(executionNode, false, true); + myBuilder.queueUpdateFrom(node, false, true); } }; - if (myRequests.add(update)) { - myUpdateTreeAlarm.addRequest(update, 100); - } + myLaterInvocator.offerIfAbsent(update); } private ExecutionNode createMessageParentNodes(MessageEvent messageEvent, ExecutionNode parentNode) { diff --git a/java/compiler/impl/src/com/intellij/build/BuildView.java b/java/compiler/impl/src/com/intellij/build/BuildView.java index 23c6a772e73b..7c7eb47ce98f 100644 --- a/java/compiler/impl/src/com/intellij/build/BuildView.java +++ b/java/compiler/impl/src/com/intellij/build/BuildView.java @@ -38,7 +38,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.ui.UIUtil; +import com.intellij.util.containers.TransferToEDTQueue; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -61,6 +61,7 @@ public class BuildView extends CompositeView implements BuildP private final AtomicBoolean isBuildStartEventProcessed = new AtomicBoolean(); private final List myAfterStartEvents = ContainerUtil.createConcurrentList(); private final ViewManager myViewManager; + private final TransferToEDTQueue myLaterInvocator = TransferToEDTQueue.createRunnableMerger("BuildView later invocator"); public BuildView(Project project, BuildDescriptor buildDescriptor, String selectionStateKey, ViewManager viewManager) { this(project, null, buildDescriptor, selectionStateKey, viewManager); @@ -113,9 +114,7 @@ public class BuildView extends CompositeView implements BuildP String eventViewName = BuildTreeConsoleView.class.getName(); BuildTreeConsoleView eventView = getView(eventViewName, BuildTreeConsoleView.class); if (eventView != null) { - UIUtil.invokeLaterIfNeeded(() -> { - eventView.onEvent(event); - }); + myLaterInvocator.offer(() -> eventView.onEvent(event)); } } } diff --git a/java/compiler/impl/src/com/intellij/build/MultipleBuildsView.java b/java/compiler/impl/src/com/intellij/build/MultipleBuildsView.java index 11c0119cf5ad..de5ceccae6d8 100644 --- a/java/compiler/impl/src/com/intellij/build/MultipleBuildsView.java +++ b/java/compiler/impl/src/com/intellij/build/MultipleBuildsView.java @@ -35,6 +35,7 @@ import com.intellij.ui.content.impl.ContentImpl; import com.intellij.util.Alarm; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.TransferToEDTQueue; import com.intellij.util.ui.EdtInvocationManager; import com.intellij.util.ui.EmptyIcon; import com.intellij.util.ui.JBUI; @@ -69,6 +70,8 @@ public class MultipleBuildsView implements BuildProgressListener, Disposable { private final AbstractViewManager myViewManager; private volatile Content myContent; private volatile DefaultActionGroup myToolbarActions; + private volatile boolean myDisposed; + private final TransferToEDTQueue myLaterInvocator; public MultipleBuildsView(Project project, BuildContentManager buildContentManager, @@ -102,11 +105,16 @@ public class MultipleBuildsView implements BuildProgressListener, Disposable { myViewMap = ContainerUtil.newConcurrentMap(); myBuildsMap = ContainerUtil.newConcurrentMap(); myProgressWatcher = new ProgressWatcher(); + + myLaterInvocator = new TransferToEDTQueue<>("Multiple builds view queue", runnable -> { + runnable.run(); + return true; + }, o -> myDisposed); } @Override public void dispose() { - + myDisposed = true; } public Content getContent() { @@ -255,7 +263,7 @@ public class MultipleBuildsView implements BuildProgressListener, Disposable { if (myContent == null) { myPostponedRunnables.addAll(runOnEdt); if (isInitializeStarted.compareAndSet(false, true)) { - UIUtil.invokeLaterIfNeeded(() -> { + myLaterInvocator.offer(() -> { myBuildsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); myBuildsList.addListSelectionListener(new ListSelectionListener() { @Override @@ -311,7 +319,7 @@ public class MultipleBuildsView implements BuildProgressListener, Disposable { } } else { - UIUtil.invokeLaterIfNeeded(() -> { + myLaterInvocator.offer(() -> { for (Runnable runnable : runOnEdt) { runnable.run(); } From 02a5fb9483704d9fcf0e0d1e2bfaa7417ceea5fc Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Wed, 10 Jan 2018 18:45:23 +0300 Subject: [PATCH 18/33] Tree table: merge frequent edt events --- .../ui/treeStructure/treetable/TreeTableModelAdapter.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableModelAdapter.java b/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableModelAdapter.java index 6558ab3f7d2b..712c7d6812f9 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableModelAdapter.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableModelAdapter.java @@ -15,6 +15,7 @@ */ package com.intellij.ui.treeStructure.treetable; +import com.intellij.util.containers.TransferToEDTQueue; import javax.swing.*; import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeExpansionListener; @@ -38,6 +39,8 @@ import java.util.concurrent.atomic.AtomicInteger; public class TreeTableModelAdapter extends AbstractTableModel { private final AtomicInteger modificationStamp = new AtomicInteger(); + private final TransferToEDTQueue laterInvocator = + TransferToEDTQueue.createRunnableMerger("TreeTableModelAdapter later invocator"); private final JTree tree; private final TreeTableModel treeTableModel; @@ -128,8 +131,7 @@ public class TreeTableModelAdapter extends AbstractTableModel { */ protected void delayedFireTableDataChanged() { long stamp = modificationStamp.incrementAndGet(); - //noinspection SSBasedInspection - SwingUtilities.invokeLater(() -> { + laterInvocator.offer(() -> { if (stamp != modificationStamp.get()) return; fireTableDataChanged(); }); From 73876f9749fd1175263c016e40b8a2fafe1a4d8e Mon Sep 17 00:00:00 2001 From: "Irina.Chernushina" Date: Wed, 10 Jan 2018 16:45:40 +0100 Subject: [PATCH 19/33] vue.js: do not highlight "closing tag matches nothing", reuse from html - for iview framework, they have custom tag Col, and there is single tag col in html -> was highlighted as error --- .../HtmlClosingTagErrorFilter.java | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/xml/xml-analysis-impl/src/com/intellij/codeInsight/highlighting/HtmlClosingTagErrorFilter.java b/xml/xml-analysis-impl/src/com/intellij/codeInsight/highlighting/HtmlClosingTagErrorFilter.java index 2225b2ba968e..f9229eb5924d 100644 --- a/xml/xml-analysis-impl/src/com/intellij/codeInsight/highlighting/HtmlClosingTagErrorFilter.java +++ b/xml/xml-analysis-impl/src/com/intellij/codeInsight/highlighting/HtmlClosingTagErrorFilter.java @@ -1,17 +1,5 @@ /* - * 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. + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ package com.intellij.codeInsight.highlighting; @@ -39,15 +27,18 @@ public class HtmlClosingTagErrorFilter extends HighlightErrorFilter { if (psiFile == null || psiFile.getViewProvider().getBaseLanguage() != HTMLLanguage.INSTANCE && HTMLLanguage.INSTANCE != element.getLanguage()) return true; + return !skip(element); + } + + public static boolean skip(@NotNull PsiErrorElement element) { final PsiElement[] children = element.getChildren(); if (children.length > 0) { if (children[0] instanceof XmlToken && XmlTokenType.XML_END_TAG_START == ((XmlToken)children[0]).getTokenType()) { if (XmlErrorMessages.message("xml.parsing.closing.tag.matches.nothing").equals(element.getErrorDescription())) { - return false; + return true; } } } - - return true; + return false; } } From 11d3d18ca2051e046fa6a281082f7df64a285e33 Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Wed, 10 Jan 2018 18:57:52 +0300 Subject: [PATCH 20/33] EA-114560 - NPE: SpringBootApplicationLifecycleManagerImpl.getDebugSession --- .../src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java index 42bb68bc61f4..fe52e3a55e54 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java @@ -46,7 +46,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -251,8 +250,7 @@ public class XDebuggerManagerImpl extends XDebuggerManager implements Persistent @Override @NotNull public XDebugSession[] getDebugSessions() { - final Collection sessions = mySessions.values(); - return sessions.toArray(new XDebugSessionImpl[sessions.size()]); + return mySessions.values().toArray(new XDebugSessionImpl[0]); } @Override From 4d641ed9aad957b5056fa84a6787a9f73e347108 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Wed, 10 Jan 2018 19:15:49 +0300 Subject: [PATCH 21/33] git: tests fix - add vfs refresh --- plugins/git4idea/tests/git4idea/log/GitSha1Test.kt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/log/GitSha1Test.kt b/plugins/git4idea/tests/git4idea/log/GitSha1Test.kt index 431de0267991..bf46b38a50f9 100644 --- a/plugins/git4idea/tests/git4idea/log/GitSha1Test.kt +++ b/plugins/git4idea/tests/git4idea/log/GitSha1Test.kt @@ -18,7 +18,12 @@ package git4idea.log import com.intellij.openapi.vcs.Executor.cd import com.intellij.openapi.vcs.Executor.touch import com.intellij.openapi.vcs.changes.patch.BlobIndexUtil -import git4idea.test.* +import com.intellij.openapi.vfs.LocalFileSystem +import git4idea.test.GitSingleRepoTest +import git4idea.test.add +import git4idea.test.addCommit +import git4idea.test.createFileStructure +import java.nio.file.Paths class GitSha1Test : GitSingleRepoTest() { var A_FILE = "a.txt" @@ -40,7 +45,7 @@ class GitSha1Test : GitSingleRepoTest() { fun `test sha for del`() { cd(projectPath) - val path = projectRoot.findChild(A_FILE)!!.path + val path = Paths.get(projectPath, A_FILE) val expectedBefore = git("hash-object $path") git("rm $path") checkSha1ForSingleChange(expectedBefore, BlobIndexUtil.NOT_COMMITTED_HASH) @@ -48,8 +53,8 @@ class GitSha1Test : GitSingleRepoTest() { fun `test sha for modified`() { cd(projectPath) - val virtualFile = projectRoot.findChild(A_FILE) - val path = virtualFile!!.path + val path = Paths.get(projectPath, A_FILE) + val virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(path.toFile())!! val expectedBefore = git("hash-object $path") setFileText(virtualFile, "echo content\n with line separator") checkSha1ForSingleChange(expectedBefore, git("hash-object $path")) From 6ca897f1ec4449a4271495355dc905be48e532f4 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 10 Jan 2018 17:37:19 +0100 Subject: [PATCH 22/33] Darcula SplitPane UI for macOS --- .../ide/ui/laf/darcula/darcula_mac.properties | 3 ++- .../ui/laf/darcula/ui/DarculaSplitPaneUI.java | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaSplitPaneUI.java diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula_mac.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula_mac.properties index 32f21a8df73c..fdda5e1013fe 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula_mac.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula_mac.properties @@ -1,3 +1,4 @@ # suppress inspection "UnusedProperty" for whole file darcula.selectionBackground=2F65CA -Menu.arrowIcon=AllIcons.Mac.Tree_white_right_arrow \ No newline at end of file +Menu.arrowIcon=AllIcons.Mac.Tree_white_right_arrow +SplitPaneUI=com.intellij.ide.ui.laf.darcula.ui.DarculaSplitPaneUI \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaSplitPaneUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaSplitPaneUI.java new file mode 100644 index 000000000000..32963117578f --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaSplitPaneUI.java @@ -0,0 +1,19 @@ +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ +package com.intellij.ide.ui.laf.darcula.ui; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.metal.MetalSplitPaneUI; + +/** + * @author Konstantin Bulenkov + */ +public class DarculaSplitPaneUI extends MetalSplitPaneUI { + + @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"}) + public static ComponentUI createUI(JComponent c) { + return new DarculaSplitPaneUI(); + } +} From c9d2781898939e0201803ac342fc9d1d23e47d99 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 10 Jan 2018 17:50:21 +0100 Subject: [PATCH 23/33] [java] module PSI uses stubs for "uses" and "provides" statements --- .../psi/impl/source/PsiJavaModuleImpl.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java index 6eb60aa328e2..233d28e9188e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java @@ -1,4 +1,6 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ package com.intellij.psi.impl.source; import com.intellij.lang.ASTNode; @@ -75,13 +77,25 @@ public class PsiJavaModuleImpl extends JavaStubPsiElement imp @NotNull @Override public Iterable getUses() { - return psiTraverser().children(this).filter(PsiUsesStatement.class); + PsiJavaModuleStub stub = getGreenStub(); + if (stub != null) { + return JBIterable.of(stub.getChildrenByType(JavaElementType.USES_STATEMENT, PsiUsesStatement.EMPTY_ARRAY)); + } + else { + return psiTraverser().children(this).filter(PsiUsesStatement.class); + } } @NotNull @Override public Iterable getProvides() { - return psiTraverser().children(this).filter(PsiProvidesStatement.class); + PsiJavaModuleStub stub = getGreenStub(); + if (stub != null) { + return JBIterable.of(stub.getChildrenByType(JavaElementType.PROVIDES_STATEMENT, PsiProvidesStatement.EMPTY_ARRAY)); + } + else { + return psiTraverser().children(this).filter(PsiProvidesStatement.class); + } } @NotNull From 00323723e44fedc9d0d6021fb5b5471ea3e0e463 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 10 Jan 2018 20:06:59 +0300 Subject: [PATCH 24/33] git tests: fix a test for case-sensitive OS Case rename on a case-sensitive OS is a regular rename, so no complex reset-restore logic is requires, and no data loss is expected. --- .../tests/git4idea/tests/GitCommitTest.kt | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt b/plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt index 7f5367d8744c..b8e8c79cf74e 100644 --- a/plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt +++ b/plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt @@ -15,6 +15,7 @@ */ package git4idea.tests +import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.vcs.Executor.* import com.intellij.openapi.vcs.VcsException @@ -219,11 +220,13 @@ class GitCommitTest : GitSingleRepoTest() { fun `test commit case rename & don't commit a file which is both staged and unstaged, should reset and restore`() { `assume version where git reset returns 0 exit code on success `() - tac("c.java") + tac("c.java", "initial") generateCaseRename("a.java", "A.java") - echo("c.java", "staged") + val STAGED_CONTENT = "staged" + overwrite("c.java", STAGED_CONTENT) git("add c.java") - overwrite("c.java", "unstaged") + val UNSTAGED_CONTENT = "unstaged" + overwrite("c.java", UNSTAGED_CONTENT) val changes = assertChanges { rename("a.java", "A.java") @@ -241,11 +244,18 @@ class GitCommitTest : GitSingleRepoTest() { repo.assertStagedChanges { modified("c.java") } - // this is intentional data loss: it is a rare case, while restoring both staged and unstaged part is not so easy, - // so we are not doing it, at least until IDEA supports Git index - // (which will mean that users will be able to produce such situation intentionally with a help of IDE). - assertEquals("unstaged", git("show :c.java")) - assertEquals("unstaged", FileUtil.loadFile(File(projectPath, "c.java"))) + + val expected = if (SystemInfo.isFileSystemCaseSensitive) { + STAGED_CONTENT + } + else { + // this is intentional data loss: it is a rare case, while restoring both staged and unstaged part is not so easy, + // so we are not doing it, at least until IDEA supports Git index + // (which will mean that users will be able to produce such situation intentionally with a help of IDE). + UNSTAGED_CONTENT + } + assertEquals(expected, git("show :c.java")) + assertEquals(expected, FileUtil.loadFile(File(projectPath, "c.java"))) } fun `test commit case rename with additional non-staged changes should commit everything`() { From 4950dc91107587bc3ced60d717962db65e1269e7 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 10 Jan 2018 20:18:30 +0300 Subject: [PATCH 25/33] git tests: refresh submodule dir after creating it by git command --- .../testSrc/com/intellij/vcs/test/VcsPlatformTest.kt | 5 +++-- plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/vcs-tests/testSrc/com/intellij/vcs/test/VcsPlatformTest.kt b/platform/vcs-tests/testSrc/com/intellij/vcs/test/VcsPlatformTest.kt index c2dcc2cd3496..2500b6ec20ed 100644 --- a/platform/vcs-tests/testSrc/com/intellij/vcs/test/VcsPlatformTest.kt +++ b/platform/vcs-tests/testSrc/com/intellij/vcs/test/VcsPlatformTest.kt @@ -136,8 +136,9 @@ abstract class VcsPlatformTest : PlatformTestCase() { return true } - protected open fun refresh() { - VfsUtil.markDirtyAndRefresh(false, true, false, testRootFile) + @JvmOverloads + protected open fun refresh(dir: VirtualFile = testRootFile) { + VfsUtil.markDirtyAndRefresh(false, true, false, dir) } protected fun updateChangeListManager() { diff --git a/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt b/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt index 3fcaf20c7c47..2bbd114283a9 100644 --- a/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt +++ b/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt @@ -22,6 +22,7 @@ import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil.getRelativePath import com.intellij.openapi.vcs.Executor.cd import com.intellij.openapi.vcs.update.UpdatedFiles +import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VfsUtilCore.virtualToIoFile import git4idea.config.GitVersion import git4idea.config.UpdateMethod @@ -164,6 +165,7 @@ class GitSubmoduleTest : GitPlatformTest() { addSubmodule(File(projectPath), submoduleUrl, relativePath) val rootPath = "${projectPath}/${relativePath ?: moduleName}" cd(rootPath) + refresh(LocalFileSystem.getInstance().refreshAndFindFileByPath(rootPath)!!) setupDefaultUsername() return registerRepo(project, rootPath) } From ac6f37df764cf2cff04fa7e02c924f563f66e235 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 10 Jan 2018 20:44:41 +0300 Subject: [PATCH 26/33] Updating versions of project dependencies: jdkBuild->u152b1136.1 Anton Tarasov --- build/dependencies/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies/gradle.properties b/build/dependencies/gradle.properties index 5aa4258d2f78..29fd6ea485a6 100644 --- a/build/dependencies/gradle.properties +++ b/build/dependencies/gradle.properties @@ -1,5 +1,5 @@ # The file might be automatically updated. Comments and empty lines will be removed. kotlinPluginBuild=1.2.10-release-IJ2017.3-1 jetSignBuild=42.30 -jdkBuild=u152b1102.2 +jdkBuild=u152b1136.1 gradleApiVersion=4.4 From 05ea559216aae97fa04629297a19ebf4f610d22c Mon Sep 17 00:00:00 2001 From: anstarovoyt Date: Wed, 10 Jan 2018 20:48:55 +0300 Subject: [PATCH 27/33] typescript: remove custom index, use file include provider instead --- .../psi/impl/include/FileIncludeIndex.java | 8 ++-- .../impl/include/FileIncludeManagerImpl.java | 42 ++++++++++++++----- .../psi/impl/include/FileIncludeProvider.java | 8 ++++ 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeIndex.java b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeIndex.java index fa0e9bc20e66..bbb35c705a19 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeIndex.java @@ -46,8 +46,9 @@ public class FileIncludeIndex extends FileBasedIndexExtension getIncludes(VirtualFile file, GlobalSearchScope scope) { - final List result = new ArrayList<>(); + @NotNull + public static List getIncludes(@NotNull VirtualFile file, @NotNull GlobalSearchScope scope) { + final List result = new ArrayList<>(); FileBasedIndex.getInstance().processValues(INDEX_ID, new FileKey(file), file, (file1, value) -> { result.addAll(value); return true; @@ -55,7 +56,8 @@ public class FileIncludeIndex extends FileBasedIndexExtension getIncludingFileCandidates(String fileName, GlobalSearchScope scope) { + @NotNull + public static MultiMap getIncludingFileCandidates(String fileName, @NotNull GlobalSearchScope scope) { final MultiMap result = new MultiMap<>(); FileBasedIndex.getInstance().processValues(INDEX_ID, new IncludeKey(fileName), null, (file, value) -> { result.put(file, value); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java index 93983ac88bca..e8e1e94e8b76 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java @@ -76,8 +76,8 @@ public class FileIncludeManagerImpl extends FileIncludeManager { public void processIncludes(PsiFile file, Processor processor) { GlobalSearchScope scope = GlobalSearchScope.allScope(myProject); - List infoList = FileIncludeIndex.getIncludes(file.getVirtualFile(), scope); - for (FileIncludeInfoImpl info : infoList) { + List infoList = FileIncludeIndex.getIncludes(file.getVirtualFile(), scope); + for (FileIncludeInfo info : infoList) { if (!processor.process(info)) { return; } @@ -101,21 +101,41 @@ public class FileIncludeManagerImpl extends FileIncludeManager { context = context.getOriginalFile(); VirtualFile contextFile = context.getVirtualFile(); if (contextFile == null) return; - MultiMap infoList = FileIncludeIndex.getIncludingFileCandidates(context.getName(), GlobalSearchScope.allScope(myProject)); - for (VirtualFile candidate : infoList.keySet()) { - PsiFile psiFile = myPsiManager.findFile(candidate); - if (psiFile == null || context.equals(psiFile)) continue; - for (FileIncludeInfo info : infoList.get(candidate)) { - PsiFileSystemItem item = resolveFileInclude(info, psiFile); - if (item != null && contextFile.equals(item.getVirtualFile())) { - if (!processor.process(Pair.create(candidate, info))) { - return; + + String originalName = context.getName(); + Collection names = getPossibleIncludeNames(context, originalName); + + GlobalSearchScope scope = GlobalSearchScope.allScope(myProject); + for (String name : names) { + MultiMap infoList = FileIncludeIndex.getIncludingFileCandidates(name, scope); + for (VirtualFile candidate : infoList.keySet()) { + PsiFile psiFile = myPsiManager.findFile(candidate); + if (psiFile == null || context.equals(psiFile)) continue; + for (FileIncludeInfo info : infoList.get(candidate)) { + PsiFileSystemItem item = resolveFileInclude(info, psiFile); + if (item != null && contextFile.equals(item.getVirtualFile())) { + if (!processor.process(Pair.create(candidate, info))) { + return; + } } } } } } + @NotNull + private static Collection getPossibleIncludeNames(@NotNull PsiFile context, @NotNull String originalName) { + Collection names = ContainerUtil.newTroveSet(); + names.add(originalName); + for (FileIncludeProvider provider : FileIncludeProvider.EP_NAME.getExtensions()) { + String newName = provider.getIncludeName(context, originalName); + if (newName != originalName) { + names.add(newName); + } + } + return names; + } + public FileIncludeManagerImpl(Project project, PsiManager psiManager, PsiFileFactory psiFileFactory, CachedValuesManager cachedValuesManager) { myProject = project; diff --git a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeProvider.java b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeProvider.java index 8769131ef1a6..71bba293b745 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeProvider.java @@ -57,4 +57,12 @@ public abstract class FileIncludeProvider { public int getVersion() { return 0; } + + /** + * @return Possible name in included paths. For example if a provider returns FileIncludeInfos without file extensions + */ + @NotNull + public String getIncludeName(@NotNull PsiFile file, @NotNull String originalName) { + return originalName; + } } From 5a15f8730333d957f73f3221d6014448453fc070 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Wed, 10 Jan 2018 20:41:56 +0300 Subject: [PATCH 28/33] respect isHidden in all ides --- .../ide/util/projectWizard/AbstractNewProjectStep.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/projectWizard/AbstractNewProjectStep.java b/platform/lang-impl/src/com/intellij/ide/util/projectWizard/AbstractNewProjectStep.java index 614669bb8221..87ac425a13cd 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/projectWizard/AbstractNewProjectStep.java +++ b/platform/lang-impl/src/com/intellij/ide/util/projectWizard/AbstractNewProjectStep.java @@ -34,10 +34,7 @@ import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.IdeFrame; -import com.intellij.platform.DirectoryProjectGenerator; -import com.intellij.platform.PlatformProjectOpenProcessor; -import com.intellij.platform.ProjectGeneratorPeer; -import com.intellij.platform.ProjectTemplate; +import com.intellij.platform.*; import com.intellij.platform.templates.ArchivedTemplatesFactory; import com.intellij.platform.templates.LocalArchivedTemplate; import com.intellij.platform.templates.TemplateProjectDirectoryGenerator; @@ -136,7 +133,7 @@ public class AbstractNewProjectStep extends DefaultActionGroup implements Dum } protected boolean shouldIgnore(@NotNull DirectoryProjectGenerator generator) { - return false; + return generator instanceof HideableProjectGenerator && ((HideableProjectGenerator)generator).isHidden(); } @NotNull From acf265afefc794c93acc1e7509a4c9d858fa2c09 Mon Sep 17 00:00:00 2001 From: akutarba Date: Tue, 9 Jan 2018 17:30:30 +0100 Subject: [PATCH 29/33] [gui-tests] Don't show native file chooser on mac --- .../intellij/testGuiFramework/launcher/GuiTestLocalLauncher.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/launcher/GuiTestLocalLauncher.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/launcher/GuiTestLocalLauncher.kt index cea2c059947d..667244eb4546 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/launcher/GuiTestLocalLauncher.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/launcher/GuiTestLocalLauncher.kt @@ -229,6 +229,7 @@ object GuiTestLocalLauncher { .plus("-Dapple.laf.useScreenMenuBar=${GuiTestOptions.useAppleScreenMenuBar()}") .plus("-Didea.is.internal=${GuiTestOptions.isInternal()}") .plus("-Didea.debug.mode=true") + .plus("-Dnative.mac.file.chooser.enabled=false") .plus("-Didea.config.path=${GuiTestOptions.getConfigPath()}") .plus("-Didea.system.path=${GuiTestOptions.getSystemPath()}") .plus("-Dfile.encoding=${GuiTestOptions.getEncoding()}") From 76000ee71cad8231024cd08b783f664ce1aa3cf1 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 10 Jan 2018 21:23:25 +0300 Subject: [PATCH 30/33] git tests: fix file content expectation --- plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt b/plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt index b8e8c79cf74e..018f37f3d4cd 100644 --- a/plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt +++ b/plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt @@ -245,7 +245,7 @@ class GitCommitTest : GitSingleRepoTest() { modified("c.java") } - val expected = if (SystemInfo.isFileSystemCaseSensitive) { + val expectedIndexContent = if (SystemInfo.isFileSystemCaseSensitive) { STAGED_CONTENT } else { @@ -254,8 +254,8 @@ class GitCommitTest : GitSingleRepoTest() { // (which will mean that users will be able to produce such situation intentionally with a help of IDE). UNSTAGED_CONTENT } - assertEquals(expected, git("show :c.java")) - assertEquals(expected, FileUtil.loadFile(File(projectPath, "c.java"))) + assertEquals(expectedIndexContent, git("show :c.java")) + assertEquals(UNSTAGED_CONTENT, FileUtil.loadFile(File(projectPath, "c.java"))) } fun `test commit case rename with additional non-staged changes should commit everything`() { From 3108674de27412f0406ea0c8f24996e0ce86124a Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Thu, 11 Jan 2018 09:41:47 +0700 Subject: [PATCH 31/33] handleFlush: do not use inherent nullability for unknown values Fixes IDEA-172844 False positive "Method invocation 'methodName' may produce NPE" in while loop condition --- .../dataFlow/DfaMemoryStateImpl.java | 3 ++- .../fixture/NullableGetterInLoop.java | 27 +++++++++++++++++++ .../DataFlowInspectionTest.java | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/NullableGetterInLoop.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java index c70bf120bc66..c4b86c16ddd4 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java @@ -269,7 +269,8 @@ public class DfaMemoryStateImpl implements DfaMemoryState { private DfaValue handleFlush(DfaVariableValue flushed, DfaValue value) { if (value instanceof DfaVariableValue && (value == flushed || myFactory.getVarFactory().getAllQualifiedBy(flushed).contains(value))) { - Nullness nullability = isNotNull(value) ? Nullness.NOT_NULL : ((DfaVariableValue)value).getInherentNullability(); + Nullness nullability = isNotNull(value) ? Nullness.NOT_NULL : + isUnknownState(value) ? Nullness.UNKNOWN : ((DfaVariableValue)value).getInherentNullability(); return myFactory.createTypeValue(((DfaVariableValue)value).getVariableType(), nullability); } return value; diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/NullableGetterInLoop.java b/java/java-tests/testData/inspection/dataFlow/fixture/NullableGetterInLoop.java new file mode 100644 index 000000000000..e5494670df00 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/NullableGetterInLoop.java @@ -0,0 +1,27 @@ +import org.jetbrains.annotations.*; + +// IDEA-172844 +abstract class SimpleClass { + + @Nullable + protected MyType findSelfOrInnerByNonQualifiedName() { + MyType nearestOuter = getOwnerParentOfType(MyType.class); + if (nearestOuter != null) { + MyType currentOuter = nearestOuter; + while (currentOuter.getOuterClass() != null) { // False positive error here + currentOuter = currentOuter.getOuterClass(); + } + } + + return null; + } + + @Nullable + abstract MyType getOwnerParentOfType(Class apexPsiTypeDeclarationClass); + + static abstract class MyType { + + @Nullable + abstract MyType getOuterClass(); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java index bcd2171cecb1..bf758fbb0076 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java @@ -583,4 +583,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase { public void testLessThanRelations() { doTest(); } public void testAdvancedArrayAccess() { doTest(); } public void testNullabilityBasics() { doTest(); } + public void testNullableGetterInLoop() { doTest(); } } From d7fba34d4c3853dcfa6fe784275fad8fab3ecd7f Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Thu, 11 Jan 2018 10:21:08 +0700 Subject: [PATCH 32/33] Revert incorrect fixes for IDEA-184723 Data flow algorithm complexity This reverts commits 9a837e70d3a98dc6883590167fbb1ef0a60b2b5a and 6d52b5462e53ae628ea5b796c0110b508c853b36. --- .../codeInspection/dataFlow/StateMerger.java | 4 -- .../dataFlow/fixture/NullabilityBasics.java | 31 ------------ .../dataFlow/fixture/OptionalTooComplex.java | 48 ------------------- .../DataFlowInspection8Test.java | 2 - .../DataFlowInspectionTest.java | 1 - 5 files changed, 86 deletions(-) delete mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/NullabilityBasics.java delete mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/OptionalTooComplex.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java index 0f8932dd6ecf..7df042704c05 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java @@ -665,10 +665,6 @@ class StateMerger { @Override void removeFromState(@NotNull DfaMemoryStateImpl state) { - if(!myPositive && state.isNotNull(myVar) && state.isNull(myArg)) { - // merging "x == null" and "x != null" should be possible with marking "x" as nullable - state.forceVariableFact(myVar, CAN_BE_NULL, true); - } state.removeEquivalenceRelations(myVar); } } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/NullabilityBasics.java b/java/java-tests/testData/inspection/dataFlow/fixture/NullabilityBasics.java deleted file mode 100644 index 25dbaf2f37c1..000000000000 --- a/java/java-tests/testData/inspection/dataFlow/fixture/NullabilityBasics.java +++ /dev/null @@ -1,31 +0,0 @@ -import org.jetbrains.annotations.*; - -class NullabilityBasics { - - void test2() { - String x = getNullable(); - if (x == null) { - System.out.println("x is null!"); - } - if (isEmpty(x) && Math.random() > 0.5) { - return; - } - System.out.println(x.trim()); - } - - @Nullable String getNullable() { - return Math.random() > 0.5 ? null : ""; - } - - @Contract(value = "null -> true",pure = true) - static boolean isEmpty(@Nullable String s) { - return s == null || s.isEmpty(); - } - - void test(String x) { - if (x == null) { - System.out.println("x is null!"); - } - System.out.println(x.trim()); - } -} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/OptionalTooComplex.java b/java/java-tests/testData/inspection/dataFlow/fixture/OptionalTooComplex.java deleted file mode 100644 index 0beb16c50f15..000000000000 --- a/java/java-tests/testData/inspection/dataFlow/fixture/OptionalTooComplex.java +++ /dev/null @@ -1,48 +0,0 @@ -import java.util.Optional; - -// IDEA-184723 -class OptionalTooComplex { - // Should not be too complex - public Long fetch() { - final PreparedStatement ps = builder - .setInteger(opt().orElse(null)) - .setInteger(opt().orElse(null)) - .setInteger(opt().orElse(null)) - .setInteger(opt().orElse(null)) - .setInteger(opt().orElse(null)) - .build(); - - ResultSet rs = null; - try { - rs = ps.executeQuery(); - if (rs.next()) { - return rs.getLong(); - } - } catch (final Exception e) { - throw new RuntimeException(e); - } finally { - } - - return 0L; - } - - interface ResultSet { - boolean next() throws Exception; - - long getLong() throws Exception; - } - - interface PreparedStatement { - ResultSet executeQuery() throws Exception; - } - - native Optional opt(); - - interface QueryBuilder { - QueryBuilder setInteger(Integer value); - - PreparedStatement build(); - } - - QueryBuilder builder; -} diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java index 6777aa2d2c29..94bdd47b19e8 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java @@ -220,6 +220,4 @@ public class DataFlowInspection8Test extends DataFlowInspectionTestCase { public void testPrimitiveGetters() { doTest(); } public void testUnknownOnStack() { doTest(); } public void testMapUpdateInlining() { doTestWithCustomAnnotations(); } - - public void testOptionalTooComplex() { doTest(); } } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java index bf758fbb0076..72d122a81038 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java @@ -582,6 +582,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase { public void testPrimitiveNull() { doTest(); } public void testLessThanRelations() { doTest(); } public void testAdvancedArrayAccess() { doTest(); } - public void testNullabilityBasics() { doTest(); } public void testNullableGetterInLoop() { doTest(); } } From 61ae918e402fe216bcf4dde82b2478a06ba639d6 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Thu, 11 Jan 2018 12:19:53 +0700 Subject: [PATCH 33/33] Fixes IDEA-184723 "Data flow algorithm complexity" removing excessive temp variables --- .../dataFlow/DfaMemoryState.java | 2 + .../dataFlow/DfaMemoryStateImpl.java | 13 +++++ .../FinishElementInstruction.java | 1 + .../dataFlow/fixture/NullabilityBasics.java | 31 ++++++++++++ .../dataFlow/fixture/OptionalTooComplex.java | 48 +++++++++++++++++++ .../DataFlowInspection8Test.java | 2 + .../DataFlowInspectionTest.java | 1 + 7 files changed, 98 insertions(+) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/NullabilityBasics.java create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/OptionalTooComplex.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryState.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryState.java index d63c0520564d..8535e6f6de6f 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryState.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryState.java @@ -129,4 +129,6 @@ public interface DfaMemoryState { boolean isEphemeral(); boolean isEmptyStack(); + + void cleanUpTempVariables(); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java index c4b86c16ddd4..f6517d93815c 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java @@ -38,6 +38,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.function.BiConsumer; +import java.util.function.Predicate; public class DfaMemoryStateImpl implements DfaMemoryState { @@ -632,6 +633,18 @@ public class DfaMemoryStateImpl implements DfaMemoryState { return myStack.isEmpty(); } + @Override + public void cleanUpTempVariables() { + Predicate sharesState = var -> + getConstantValue(var) == null && + StreamEx.of(getEquivalentValues(var)).without(var).select(DfaVariableValue.class).findFirst().isPresent(); + List values = StreamEx.ofKeys(myVariableStates) + .filter(var -> ControlFlowAnalyzer.isTempVariable(var.getPsiVariable())) + .remove(sharesState) + .toList(); + values.forEach(this::flushVariable); + } + @Override public boolean castTopOfStack(@NotNull DfaPsiType type) { DfaValue value = unwrap(peek()); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/FinishElementInstruction.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/FinishElementInstruction.java index a0aabe963480..9778d96dabf5 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/FinishElementInstruction.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/FinishElementInstruction.java @@ -43,6 +43,7 @@ public class FinishElementInstruction extends Instruction { state.flushVariable(value); } } + state.cleanUpTempVariables(); return nextInstruction(runner, state); } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/NullabilityBasics.java b/java/java-tests/testData/inspection/dataFlow/fixture/NullabilityBasics.java new file mode 100644 index 000000000000..25dbaf2f37c1 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/NullabilityBasics.java @@ -0,0 +1,31 @@ +import org.jetbrains.annotations.*; + +class NullabilityBasics { + + void test2() { + String x = getNullable(); + if (x == null) { + System.out.println("x is null!"); + } + if (isEmpty(x) && Math.random() > 0.5) { + return; + } + System.out.println(x.trim()); + } + + @Nullable String getNullable() { + return Math.random() > 0.5 ? null : ""; + } + + @Contract(value = "null -> true",pure = true) + static boolean isEmpty(@Nullable String s) { + return s == null || s.isEmpty(); + } + + void test(String x) { + if (x == null) { + System.out.println("x is null!"); + } + System.out.println(x.trim()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/OptionalTooComplex.java b/java/java-tests/testData/inspection/dataFlow/fixture/OptionalTooComplex.java new file mode 100644 index 000000000000..0beb16c50f15 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/OptionalTooComplex.java @@ -0,0 +1,48 @@ +import java.util.Optional; + +// IDEA-184723 +class OptionalTooComplex { + // Should not be too complex + public Long fetch() { + final PreparedStatement ps = builder + .setInteger(opt().orElse(null)) + .setInteger(opt().orElse(null)) + .setInteger(opt().orElse(null)) + .setInteger(opt().orElse(null)) + .setInteger(opt().orElse(null)) + .build(); + + ResultSet rs = null; + try { + rs = ps.executeQuery(); + if (rs.next()) { + return rs.getLong(); + } + } catch (final Exception e) { + throw new RuntimeException(e); + } finally { + } + + return 0L; + } + + interface ResultSet { + boolean next() throws Exception; + + long getLong() throws Exception; + } + + interface PreparedStatement { + ResultSet executeQuery() throws Exception; + } + + native Optional opt(); + + interface QueryBuilder { + QueryBuilder setInteger(Integer value); + + PreparedStatement build(); + } + + QueryBuilder builder; +} diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java index 94bdd47b19e8..6777aa2d2c29 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java @@ -220,4 +220,6 @@ public class DataFlowInspection8Test extends DataFlowInspectionTestCase { public void testPrimitiveGetters() { doTest(); } public void testUnknownOnStack() { doTest(); } public void testMapUpdateInlining() { doTestWithCustomAnnotations(); } + + public void testOptionalTooComplex() { doTest(); } } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java index 72d122a81038..ab31ce3f04ed 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java @@ -583,4 +583,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase { public void testLessThanRelations() { doTest(); } public void testAdvancedArrayAccess() { doTest(); } public void testNullableGetterInLoop() { doTest(); } + public void testNullabilityBasics() { doTest(); } }