From 2c8fa04911a152315e3b8ad6a222604e39f018ca Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Wed, 19 Oct 2016 19:12:32 +0200 Subject: [PATCH 1/9] Put terminal shell integration scripts in build --- .../intellij/build/CommunityRepositoryModules.groovy | 6 +++++- .../plugins/terminal/LocalTerminalDirectRunner.java | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/build/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy b/build/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy index 8673ad594142..1918ebb1733f 100644 --- a/build/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy +++ b/build/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy @@ -238,7 +238,11 @@ class CommunityRepositoryModules { withModule("java-decompiler-engine", mainJarName) doNotCreateSeparateJarForLocalizableResources() }, - javaFXPlugin("javaFX-CE") + javaFXPlugin("javaFX-CE"), + plugin("terminal") { + withResource("resources/.zshrc", "") + withResource("resources/jediterm-sh.in", "") + } ] static PluginLayout androidPlugin(Map additionalModulesToJars) { diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java index 2a07d9e99870..17b6d1345694 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java @@ -34,6 +34,7 @@ import com.intellij.util.containers.HashMap; import com.jediterm.pty.PtyProcessTtyConnector; import com.jediterm.terminal.TtyConnector; import com.pty4j.PtyProcess; +import com.pty4j.util.PtyUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -81,6 +82,12 @@ public class LocalTerminalDirectRunner extends AbstractTerminalRunner Date: Wed, 19 Oct 2016 19:20:50 +0200 Subject: [PATCH 2/9] /bin/sh doesn't have source command. But it has . instead --- python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt b/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt index ad77c7df9e20..9aa8a7ccf0d3 100644 --- a/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt +++ b/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt @@ -85,7 +85,7 @@ class PyVirtualEnvReader(val virtualEnvSdkPath: String) : EnvironmentUtil.ShellE } return if (activate != null) - mutableListOf(shellPath, "-c", "source '$activate'") + mutableListOf(shellPath, "-c", ". '$activate'") else super.getShellProcessCommand() } From 84e361cf67aac1cf25de91809558175087f1a10f Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 19 Oct 2016 19:09:03 +0200 Subject: [PATCH 3/9] SSR: fix matching super calls --- .../impl/matcher/JavaMatchingVisitor.java | 2 +- .../structuralsearch/StructuralSearchTest.java | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java index d1fa39927abf..c648e2256c83 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java @@ -1342,7 +1342,7 @@ public class JavaMatchingVisitor extends JavaElementVisitor { @Override public void visitSuperExpression(final PsiSuperExpression super1) { - myMatchingVisitor.setResult(true); + myMatchingVisitor.setResult(myMatchingVisitor.getElement() instanceof PsiSuperExpression); } @Override diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index 316aadc640d3..205354813a19 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -3488,4 +3488,16 @@ public class StructuralSearchTest extends StructuralSearchTestCase { assertEquals("find diamond new expressions", 3, findMatchesCount(source, "new A<>()")); assertEquals("find parameterized new expressions", 2, findMatchesCount(source, "new A()")); } + + + + public void testFindSuperCall() { + String source = "class A {" + + " public String toString() {" + + " System.out.println();" + + " return super.toString();" + + " }" + + "}"; + assertEquals("find super call", 1, findMatchesCount(source, "super.$m$()")); + } } From 3314382d6e2fd7cf2d6baa3eb0f5f4dd8615c8f0 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Wed, 19 Oct 2016 19:27:46 +0200 Subject: [PATCH 4/9] Only /bin/bash has --rcfile, so name the script accordingly; On Mac /bin/sh is alias for /bin/bash, so we handle that as well --- .../intellij/build/CommunityRepositoryModules.groovy | 2 +- .../resources/{jediterm-sh.in => jediterm-bash.in} | 0 .../plugins/terminal/LocalTerminalDirectRunner.java | 7 +++---- .../plugins/terminal/TerminalShellCommandTest.java | 6 +++--- .../jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt | 4 ++-- 5 files changed, 9 insertions(+), 10 deletions(-) rename plugins/terminal/resources/{jediterm-sh.in => jediterm-bash.in} (100%) diff --git a/build/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy b/build/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy index 1918ebb1733f..a4b6b6ed5de9 100644 --- a/build/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy +++ b/build/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy @@ -241,7 +241,7 @@ class CommunityRepositoryModules { javaFXPlugin("javaFX-CE"), plugin("terminal") { withResource("resources/.zshrc", "") - withResource("resources/jediterm-sh.in", "") + withResource("resources/jediterm-bash.in", "") } ] diff --git a/plugins/terminal/resources/jediterm-sh.in b/plugins/terminal/resources/jediterm-bash.in similarity index 100% rename from plugins/terminal/resources/jediterm-sh.in rename to plugins/terminal/resources/jediterm-bash.in diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java index 17b6d1345694..1d10271353da 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java @@ -72,8 +72,8 @@ public class LocalTerminalDirectRunner extends AbstractTerminalRunner envs = Maps.newHashMap(); - hasRcConfig("sh --rcfile ~/.bashrc", "jediterm-sh.in", envs); + hasRcConfig("sh --rcfile ~/.bashrc", "jediterm-bash.in", envs); assertEquals("~/.bashrc", envs.get("JEDITERM_SOURCE")); } diff --git a/python/python-terminal/src/com/jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt b/python/python-terminal/src/com/jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt index 806ded0c2563..1a359be3d0ee 100644 --- a/python/python-terminal/src/com/jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt +++ b/python/python-terminal/src/com/jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt @@ -45,8 +45,8 @@ class PyVirtualEnvTerminalCustomizer : LocalTerminalCustomizer() { val shellPath = command[0] val shellName = File(shellPath).name - if (shellName == "bash" || shellName == "sh") { - //for bash and sh we pass activate script to jediterm shell integration (see jediterm-sh.in) to source it there + if (shellName == "bash" || (SystemInfo.isMac && shellName == "sh")) { + //for bash we pass activate script to jediterm shell integration (see jediterm-bash.in) to source it there findActivateScript(path, shellPath)?.let { activate -> envs.put("JEDITERM_SOURCE", activate) } } else { From 87a28d8d6e5e00b336cfc40de8962d9e74b664a6 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 19 Oct 2016 18:37:05 +0200 Subject: [PATCH 5/9] dfa: honor control transfer instructions when performing auxiliary analyses (IDEA-162557) --- .../codeInspection/dataFlow/ControlFlow.java | 10 +++++++++ .../dataFlow/DataFlowRunner.java | 2 ++ .../dataFlow/LiveVariablesAnalyzer.java | 21 ++++--------------- .../codeInspection/dataFlow/LoopAnalyzer.java | 11 +++++----- .../dataFlow/controlTransfer.kt | 20 ++++++++++++++++++ .../TryReturnCatchInWhileNotComplex.java | 12 +++++++++++ .../DataFlowInspectionTest.java | 1 + 7 files changed, 54 insertions(+), 23 deletions(-) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/TryReturnCatchInWhileNotComplex.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlow.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlow.java index 710f4b17baf1..b17e08cbe446 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlow.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlow.java @@ -87,6 +87,11 @@ public class ControlFlow { public int getInstructionOffset() { return myElementToStartOffsetMap.get(element); } + + @Override + public String toString() { + return String.valueOf(myElementToStartOffsetMap.get(element)); + } }; } @@ -96,6 +101,11 @@ public class ControlFlow { public int getInstructionOffset() { return myElementToEndOffsetMap.get(element); } + + @Override + public String toString() { + return String.valueOf(myElementToEndOffsetMap.get(element)); + } }; } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java index b7e3418791a8..8b801f0c9ffd 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java @@ -122,6 +122,8 @@ public class DataFlowRunner { joinInstructions.add(myInstructions[((GotoInstruction)instruction).getOffset()]); } else if (instruction instanceof ConditionalGotoInstruction) { joinInstructions.add(myInstructions[((ConditionalGotoInstruction)instruction).getOffset()]); + } else if (instruction instanceof ControlTransferInstruction) { + joinInstructions.addAll(((ControlTransferInstruction)instruction).getPossibleTargetInstructions(myInstructions)); } else if (instruction instanceof MethodCallInstruction && !((MethodCallInstruction)instruction).getContracts().isEmpty()) { joinInstructions.add(myInstructions[index + 1]); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/LiveVariablesAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/LiveVariablesAnalyzer.java index 6738c00c51d5..cc79e8aa20c7 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/LiveVariablesAnalyzer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/LiveVariablesAnalyzer.java @@ -27,6 +27,7 @@ import com.intellij.psi.PsiReferenceExpression; import com.intellij.util.PairFunction; import com.intellij.util.containers.*; import com.intellij.util.containers.Queue; +import one.util.streamex.IntStreamEx; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -68,22 +69,8 @@ public class LiveVariablesAnalyzer { myBackwardMap = calcBackwardMap(); } - private List getSuccessors(Instruction i) { - if (i instanceof GotoInstruction) { - return Arrays.asList(myInstructions[((GotoInstruction)i).getOffset()]); - } - - int index = i.getIndex(); - if (i instanceof ConditionalGotoInstruction) { - return Arrays.asList(myInstructions[((ConditionalGotoInstruction)i).getOffset()], myInstructions[index + 1]); - } - - if (i instanceof ReturnInstruction) { - return Collections.emptyList(); - } - - return Arrays.asList(myInstructions[index + 1]); - + private List getSuccessors(Instruction ins) { + return IntStreamEx.of(LoopAnalyzer.getSuccessorIndices(ins.getIndex(), myInstructions)).mapToObj(i -> myInstructions[i]).toList(); } private MultiMap calcBackwardMap() { @@ -149,7 +136,7 @@ public class LiveVariablesAnalyzer { return instruction instanceof FinishElementInstruction || instruction instanceof GotoInstruction || instruction instanceof ConditionalGotoInstruction || - instruction instanceof ReturnInstruction; + instruction instanceof ControlTransferInstruction; } @Nullable diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/LoopAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/LoopAnalyzer.java index 4ee09b18e771..991fb7e1debe 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/LoopAnalyzer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/LoopAnalyzer.java @@ -18,7 +18,6 @@ package com.intellij.codeInspection.dataFlow; import com.intellij.codeInspection.dataFlow.instructions.ConditionalGotoInstruction; import com.intellij.codeInspection.dataFlow.instructions.GotoInstruction; import com.intellij.codeInspection.dataFlow.instructions.Instruction; -import com.intellij.codeInspection.dataFlow.instructions.ReturnInstruction; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.EmptyIterator; import com.intellij.util.graph.DFSTBuilder; @@ -41,7 +40,7 @@ class LoopAnalyzer { myInstructions = flow.getInstructions(); for (Instruction instruction : myInstructions) { int fromIndex = instruction.getIndex(); - int[] to = next(fromIndex, myInstructions); + int[] to = getSuccessorIndices(fromIndex, myInstructions); for (int toIndex : to) { int[] froms = myIns.get(toIndex); if (froms == null) { @@ -70,7 +69,7 @@ class LoopAnalyzer { @Override public Iterator getOut(Instruction instruction) { int fromIndex = instruction.getIndex(); - int[] next = next(fromIndex, myInstructions); + int[] next = getSuccessorIndices(fromIndex, myInstructions); return indicesToInstructions(next); } @@ -113,13 +112,13 @@ class LoopAnalyzer { } @NotNull - private static int[] next(int i, Instruction[] myInstructions) { + static int[] getSuccessorIndices(int i, Instruction[] myInstructions) { Instruction instruction = myInstructions[i]; if (instruction instanceof GotoInstruction) { return new int[]{((GotoInstruction)instruction).getOffset()}; } - if (instruction instanceof ReturnInstruction) { - return ArrayUtil.EMPTY_INT_ARRAY; + if (instruction instanceof ControlTransferInstruction) { + return ArrayUtil.toIntArray(((ControlTransferInstruction)instruction).getPossibleTargetIndices()); } if (instruction instanceof ConditionalGotoInstruction) { int offset = ((ConditionalGotoInstruction)instruction).getOffset(); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/controlTransfer.kt b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/controlTransfer.kt index c19d8bcb16df..3a90442a9db2 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/controlTransfer.kt +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/controlTransfer.kt @@ -46,6 +46,18 @@ open class ControlTransferInstruction(val transfer: DfaControlTransferValue?) : return ControlTransferHandler(state, runner, transferValue.target).iteration(transferValue.traps).toTypedArray() } + fun getPossibleTargetIndices() : List { + if (transfer == null) return emptyList() + + val result = ArrayList(transfer.traps.flatMap(Trap::getPossibleTargets)) + if (transfer.target is InstructionTransfer) { + result.add(transfer.target.offset.instructionOffset) + } + return result + } + + fun getPossibleTargetInstructions(allInstructions: Array) = getPossibleTargetIndices().map { allInstructions[it] } + override fun toString() = transfer.toString() } @@ -53,6 +65,14 @@ sealed class Trap(val anchor: PsiElement) { class TryCatch(tryStatement : PsiTryStatement, val clauses: LinkedHashMap): Trap(tryStatement) class TryFinally(val finallyBlock: PsiCodeBlock, val jumpOffset: ControlFlow.ControlFlowOffset): Trap(finallyBlock) class InsideFinally(val finallyBlock: PsiCodeBlock): Trap(finallyBlock) + + internal fun getPossibleTargets(): Collection { + return when (this) { + is TryCatch -> clauses.values.map { it.instructionOffset } + is TryFinally -> listOf(jumpOffset.instructionOffset) + else -> emptyList() + } + } } private class ControlTransferHandler(val state: DfaMemoryState, val runner: DataFlowRunner, val target: TransferTarget) { diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/TryReturnCatchInWhileNotComplex.java b/java/java-tests/testData/inspection/dataFlow/fixture/TryReturnCatchInWhileNotComplex.java new file mode 100644 index 000000000000..d8cbc26a923f --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/TryReturnCatchInWhileNotComplex.java @@ -0,0 +1,12 @@ +class Bar { + void repeatUntilPassesInSmartMode(final Runnable r) { + while (true) { + try { + r.run(); + return; + } + catch (Throwable e) { + } + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index eb2a56ad9d22..4c0826fd2a66 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -55,6 +55,7 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase { public void testBuildRegexpNotComplex() throws Throwable { doTest(); } public void testTernaryInWhileNotComplex() throws Throwable { doTest(); } public void testTryCatchInForNotComplex() throws Throwable { doTest(); } + public void testTryReturnCatchInWhileNotComplex() throws Throwable { doTest(); } public void testNestedTryInWhileNotComplex() throws Throwable { doTest(); } public void testExceptionFromFinally() throws Throwable { doTest(); } public void testExceptionFromFinallyNesting() throws Throwable { doTest(); } From 5b863d7817f052d77b16500e9f7726992e9d89e9 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 19 Oct 2016 18:53:38 +0200 Subject: [PATCH 6/9] constructor completion: insert the chosen constructor and position the caret accordingly (IDEA-CR-14717) --- .../completion/ConstructorInsertHandler.java | 4 +++- .../completion/JavaConstructorCallElement.java | 8 ++++++-- .../completion/signature/SeveralConstructors.java | 4 ++-- .../signature/SeveralConstructors_after.java | 12 ++++++++++++ .../completion/SignatureCompletionTest.groovy | 5 +++++ 5 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/signature/SeveralConstructors_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java index a57029729610..2922cb2343ca 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java @@ -214,9 +214,11 @@ public class ConstructorInsertHandler implements InsertHandler 0 : hasConstructorParameters(psiClass, place); JavaCompletionUtil.insertParentheses(context, delegate, false, hasParams, forAnonymous); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaConstructorCallElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaConstructorCallElement.java index d85925410b83..c9688d859131 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaConstructorCallElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaConstructorCallElement.java @@ -49,8 +49,6 @@ public class JavaConstructorCallElement extends LookupElementDecorator diff --git a/java/java-tests/testData/codeInsight/completion/signature/SeveralConstructors_after.java b/java/java-tests/testData/codeInsight/completion/signature/SeveralConstructors_after.java new file mode 100644 index 000000000000..017800f75cb0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/signature/SeveralConstructors_after.java @@ -0,0 +1,12 @@ +class Foo{ + Foo(int arg) { + } + Foo() { + } + Foo(boolean arg) { + } + + { + Foo f = new Foo(); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SignatureCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SignatureCompletionTest.groovy index c2a504fbf36e..b7b2fcb6dcf3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SignatureCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SignatureCompletionTest.groovy @@ -18,6 +18,8 @@ package com.intellij.codeInsight.completion import com.intellij.JavaTestUtil import com.intellij.codeInsight.template.impl.TemplateManagerImpl import com.intellij.openapi.util.registry.Registry +import com.intellij.psi.PsiMethod + /** * @author peter */ @@ -64,6 +66,9 @@ class SignatureCompletionTest extends LightFixtureCompletionTestCase { myFixture.complete(CompletionType.SMART) def items = myFixture.lookup.items assert items.size() == 3 + assert ((PsiMethod) items[0].object).parameterList.parametersCount == 0 + myFixture.type('\n') + checkResult() } } From 1831c5332007636ab6341c86c1d217bb0ea774f3 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 19 Oct 2016 19:23:08 +0200 Subject: [PATCH 7/9] constructor completion: implement anonymous methods after arg live template (IDEA-CR-14717) --- .../completion/ConstructorInsertHandler.java | 31 ++++++++++++++++--- .../AnonymousNonDefaultConstructor.java | 2 ++ .../AnonymousNonDefaultConstructor_after.java | 2 ++ ...usNonDefaultConstructor_afterTemplate.java | 15 +++++++++ .../completion/SignatureCompletionTest.groovy | 9 ++++-- 5 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor_afterTemplate.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java index 2922cb2343ca..03369610d3c3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java @@ -12,6 +12,8 @@ import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementDecorator; import com.intellij.codeInsight.lookup.PsiTypeLookupItem; import com.intellij.codeInsight.template.*; +import com.intellij.codeInsight.template.impl.TemplateManagerImpl; +import com.intellij.codeInsight.template.impl.TemplateState; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; @@ -124,7 +126,7 @@ public class ConstructorInsertHandler implements InsertHandler } diff --git a/java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor_after.java b/java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor_after.java index 49dde1b89a5a..407a6ac4f477 100644 --- a/java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor_after.java +++ b/java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor_after.java @@ -2,6 +2,8 @@ abstract class Foo{ public Foo(int x) { } + abstract int foo(); + { Foo f = new Foo(x) {} } diff --git a/java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor_afterTemplate.java b/java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor_afterTemplate.java new file mode 100644 index 000000000000..ab5730c151b3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/signature/AnonymousNonDefaultConstructor_afterTemplate.java @@ -0,0 +1,15 @@ +abstract class Foo{ + public Foo(int x) { + } + + abstract int foo(); + + { + Foo f = new Foo(x) { + @Override + int foo() { + return 0; + } + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SignatureCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SignatureCompletionTest.groovy index b7b2fcb6dcf3..bed15ad0b482 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SignatureCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SignatureCompletionTest.groovy @@ -19,7 +19,6 @@ import com.intellij.JavaTestUtil import com.intellij.codeInsight.template.impl.TemplateManagerImpl import com.intellij.openapi.util.registry.Registry import com.intellij.psi.PsiMethod - /** * @author peter */ @@ -59,7 +58,13 @@ class SignatureCompletionTest extends LightFixtureCompletionTestCase { void testNonDefaultConstructor() { doFirstItemTest() } - void testAnonymousNonDefaultConstructor() { doFirstItemTest() } + void testAnonymousNonDefaultConstructor() { + configureByTestName() + myFixture.type('\n') + checkResult() + myFixture.type('\n') + checkResultByFile(getTestName(false) + "_afterTemplate.java") + } void testSeveralConstructors() { myFixture.configureByFile(getTestName(false) + ".java") From 9b5199c131198e0ff821a3b92b407852943d3a45 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 19 Oct 2016 20:04:32 +0300 Subject: [PATCH 8/9] removed redundant casts --- .../src/com/intellij/debugger/ui/breakpoints/Breakpoint.java | 2 +- .../src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java index 55c7f75f17bd..f1d89c9d904e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java @@ -312,7 +312,7 @@ public abstract class Breakpoint

implements if (isCountFilterEnabled()) { debugProcess.getVirtualMachineProxy().suspend(); debugProcess.getRequestsManager().deleteRequest(this); - ((Breakpoint)this).createRequest(debugProcess); + createRequest(debugProcess); debugProcess.getVirtualMachineProxy().resume(); } if (isInstanceFiltersEnabled()) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java index 3c97a1ee9084..aed6e01802b8 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java @@ -265,13 +265,13 @@ public class XDebuggerUtilImpl extends XDebuggerUtil { else { P properties = variants.get(0).createProperties(); result.setResult( - Promise.resolve((XLineBreakpoint)breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary))); + Promise.resolve(breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary))); return; } } P properties = type.createBreakpointProperties(file, line); result.setResult( - Promise.resolve((XLineBreakpoint)breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary))); + Promise.resolve(breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary))); return; } result.setResult(rejectedPromise()); From 4f07658363073983e3d8d9200c65b37806ccb00e Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 19 Oct 2016 20:31:39 +0300 Subject: [PATCH 9/9] emulate method exit breakpoints as well --- .../ui/breakpoints/MethodBreakpoint.java | 58 +++++++++++++++---- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java index d88a3e2d323a..1dc9fc059d26 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java @@ -32,6 +32,7 @@ import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; import com.intellij.debugger.engine.requests.RequestManagerImpl; import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.debugger.impl.PositionUtil; +import com.intellij.debugger.jdi.MethodBytecodeUtil; import com.intellij.debugger.requests.Requestor; import com.intellij.icons.AllIcons; import com.intellij.openapi.application.ApplicationManager; @@ -62,6 +63,9 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.java.debugger.breakpoints.properties.JavaMethodBreakpointProperties; +import org.jetbrains.org.objectweb.asm.Label; +import org.jetbrains.org.objectweb.asm.MethodVisitor; +import org.jetbrains.org.objectweb.asm.Opcodes; import javax.swing.*; import java.util.List; @@ -130,27 +134,53 @@ public class MethodBreakpoint extends BreakpointWithHighlighter { if (instanceOf(referenceType, baseType)) { - createRequestForPreparedClassEmulated(debugProcess, referenceType, () -> {}); + createRequestForPreparedClassEmulated(debugProcess, referenceType, false); } }, null); if (request != null) { request.enable(); } - processSubTypes(baseType, subType -> createRequestForPreparedClassEmulated(debugProcess, subType, () -> {})); + processSubTypes(baseType, subType -> createRequestForPreparedClassEmulated(debugProcess, subType, false)); } - private void createRequestForPreparedClassEmulated(@NotNull DebugProcessImpl debugProcess, @NotNull ReferenceType classType, Runnable onCreated) { + private void createRequestForPreparedClassEmulated(@NotNull DebugProcessImpl debugProcess, @NotNull ReferenceType classType, boolean base) { try { for (Method method : classType.methods()) { if (getMethodName().equals(method.name()) && mySignature.getName(debugProcess).equals(method.signature())) { - // desired class found - now also track all new classes - Location firstLocation = ContainerUtil.getFirstItem(method.allLineLocations()); - if (firstLocation != null) { - RequestManagerImpl requestsManager = debugProcess.getRequestsManager(); - requestsManager.enableRequest(requestsManager.createBreakpointRequest(this, firstLocation)); + List allLineLocations = method.allLineLocations(); + if (isWatchEntry()) { + createLocationBreakpoint(ContainerUtil.getFirstItem(allLineLocations), debugProcess); + } + if (isWatchExit()) { + MethodBytecodeUtil.visit(classType, method, new MethodVisitor(Opcodes.API_VERSION) { + int myLastLine = 0; + @Override + public void visitLineNumber(int line, Label start) { + myLastLine = line; + } + + @Override + public void visitInsn(int opcode) { + switch (opcode) { + case Opcodes.RETURN: + case Opcodes.IRETURN: + case Opcodes.FRETURN: + case Opcodes.ARETURN: + case Opcodes.LRETURN: + case Opcodes.DRETURN: + case Opcodes.ATHROW: + allLineLocations.stream() + .filter(l -> l.lineNumber() == myLastLine) + .findFirst().ifPresent(location -> createLocationBreakpoint(location, debugProcess)); + } + } + }); + } + if (base) { + // desired class found - now also track all new classes + createRequestForSubClasses(debugProcess, classType); } - onCreated.run(); break; } } @@ -160,9 +190,17 @@ public class MethodBreakpoint extends BreakpointWithHighlighter createRequestForSubClasses(debugProcess, classType)); + createRequestForPreparedClassEmulated(debugProcess, classType, true); } else { createRequestForPreparedClassOriginal(debugProcess, classType);