Merge remote-tracking branch 'origin/master'

This commit is contained in:
Konstantin Bulenkov
2016-10-19 19:48:09 +02:00
26 changed files with 218 additions and 59 deletions
@@ -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-bash.in", "")
}
]
static PluginLayout androidPlugin(Map<String, String> additionalModulesToJars) {
@@ -312,7 +312,7 @@ public abstract class Breakpoint<P extends JavaBreakpointProperties> implements
if (isCountFilterEnabled()) {
debugProcess.getVirtualMachineProxy().suspend();
debugProcess.getRequestsManager().deleteRequest(this);
((Breakpoint)this).createRequest(debugProcess);
createRequest(debugProcess);
debugProcess.getVirtualMachineProxy().resume();
}
if (isInstanceFiltersEnabled()) {
@@ -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<JavaMethodBreakp
DebuggerManagerThreadImpl.assertIsManagerThread();
ClassPrepareRequest request = debugProcess.getRequestsManager().createClassPrepareRequest((debuggerProcess, referenceType) -> {
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<Location> 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<JavaMethodBreakp
}
}
private void createLocationBreakpoint(@Nullable Location location, @NotNull DebugProcessImpl debugProcess) {
if (location != null) {
RequestManagerImpl requestsManager = debugProcess.getRequestsManager();
requestsManager.enableRequest(requestsManager.createBreakpointRequest(this, location));
}
}
protected void createRequestForPreparedClass(@NotNull DebugProcessImpl debugProcess, @NotNull ReferenceType classType) {
if (Registry.is("debugger.emulate.method.breakpoints")) {
createRequestForPreparedClassEmulated(debugProcess, classType, () -> createRequestForSubClasses(debugProcess, classType));
createRequestForPreparedClassEmulated(debugProcess, classType, true);
}
else {
createRequestForPreparedClassOriginal(debugProcess, classType);
@@ -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));
}
};
}
@@ -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]);
}
@@ -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<Instruction> 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<Instruction> getSuccessors(Instruction ins) {
return IntStreamEx.of(LoopAnalyzer.getSuccessorIndices(ins.getIndex(), myInstructions)).mapToObj(i -> myInstructions[i]).toList();
}
private MultiMap<Instruction, Instruction> 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
@@ -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<Instruction> 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();
@@ -46,6 +46,18 @@ open class ControlTransferInstruction(val transfer: DfaControlTransferValue?) :
return ControlTransferHandler(state, runner, transferValue.target).iteration(transferValue.traps).toTypedArray()
}
fun getPossibleTargetIndices() : List<Int> {
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<Instruction>) = 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<PsiCatchSection, ControlFlow.ControlFlowOffset>): Trap(tryStatement)
class TryFinally(val finallyBlock: PsiCodeBlock, val jumpOffset: ControlFlow.ControlFlowOffset): Trap(finallyBlock)
class InsideFinally(val finallyBlock: PsiCodeBlock): Trap(finallyBlock)
internal fun getPossibleTargets(): Collection<Int> {
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) {
@@ -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<LookupElementDeco
PsiDocumentManager.getInstance(file.getProject()).commitDocument(document);
reformatEnclosingExpressionListAtOffset(file, offset);
if (promptTypeOrConstructorArgs(context, delegate, context.getOffset(insideRef))) return;
if (promptTypeOrConstructorArgs(context, delegate, insideRef, insideBraces)) return;
editor.getCaretModel().moveToOffset(context.getOffset(insideBraces));
context.setLaterRunnable(generateAnonymousBody(editor, file));
@@ -142,17 +144,36 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
if (mySmart) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW);
}
promptTypeOrConstructorArgs(context, delegate, context.getOffset(insideRef));
promptTypeOrConstructorArgs(context, delegate, insideRef, null);
}
}
private static boolean promptTypeOrConstructorArgs(InsertionContext context, LookupElement delegate, int refOffset) {
if (shouldFillTypeArgs(context, delegate) && JavaCompletionUtil.promptTypeArgs(context, refOffset)) {
private static boolean promptTypeOrConstructorArgs(InsertionContext context, LookupElement delegate, OffsetKey refOffset, @Nullable OffsetKey insideBraces) {
if (shouldFillTypeArgs(context, delegate) && JavaCompletionUtil.promptTypeArgs(context, context.getOffset(refOffset))) {
return true;
}
PsiMethod constructor = JavaConstructorCallElement.extractCalledConstructor(delegate);
return constructor != null && JavaMethodCallElement.startArgumentLiveTemplate(context, constructor);
if (constructor != null && JavaMethodCallElement.startArgumentLiveTemplate(context, constructor)) {
implementMethodsWhenTemplateIsFinished(context, insideBraces);
return true;
}
return false;
}
private static void implementMethodsWhenTemplateIsFinished(InsertionContext context, @Nullable final OffsetKey insideBraces) {
TemplateState state = TemplateManagerImpl.getTemplateState(context.getEditor());
if (state != null && insideBraces != null) {
state.addTemplateStateListener(new TemplateEditingAdapter() {
@Override
public void templateFinished(Template template, boolean brokenOff) {
if (!brokenOff) {
context.getEditor().getCaretModel().moveToOffset(context.getOffset(insideBraces));
createOverrideRunnable(context.getEditor(), context.getFile(), context.getProject()).run();
}
}
});
}
}
private static boolean shouldFillTypeArgs(InsertionContext context, LookupElement delegate) {
@@ -214,9 +235,11 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
return false;
}
PsiMethod constructor = JavaConstructorCallElement.extractCalledConstructor(delegate);
final PsiElement place = context.getFile().findElementAt(context.getStartOffset());
assert place != null;
boolean hasParams = hasConstructorParameters(psiClass, place);
boolean hasParams = constructor != null ? constructor.getParameterList().getParametersCount() > 0 : hasConstructorParameters(psiClass, place);
JavaCompletionUtil.insertParentheses(context, delegate, false, hasParams, forAnonymous);
@@ -49,8 +49,6 @@ public class JavaConstructorCallElement extends LookupElementDecorator<LookupEle
myConstructor = constructor;
myType = type;
mySubstitutor = myType.resolveGenerics().getSubstitutor();
markClassItemWrapped(classItem);
}
private void markClassItemWrapped(@NotNull LookupElement classItem) {
@@ -62,6 +60,12 @@ public class JavaConstructorCallElement extends LookupElementDecorator<LookupEle
}
}
@Override
public void handleInsert(InsertionContext context) {
markClassItemWrapped(getDelegate());
super.handleInsert(context);
}
@NotNull
@Override
public PsiMethod getObject() {
@@ -2,6 +2,8 @@ abstract class Foo{
public Foo(int x) {
}
abstract int foo();
{
Foo f = new F<caret>
}
@@ -2,6 +2,8 @@ abstract class Foo{
public Foo(int x) {
}
abstract int foo();
{
Foo f = new Foo(<selection>x</selection><caret>) {}
}
@@ -0,0 +1,15 @@
abstract class Foo{
public Foo(int x) {
}
abstract int foo();
{
Foo f = new Foo(x) {
@Override
int foo() {
return 0;
}
}
}
}
@@ -1,10 +1,10 @@
class Foo{
Foo(int arg) {
}
Foo(boolean arg) {
}
Foo() {
}
Foo(boolean arg) {
}
{
Foo f = new F<caret>
@@ -0,0 +1,12 @@
class Foo{
Foo(int arg) {
}
Foo() {
}
Foo(boolean arg) {
}
{
Foo f = new Foo();<caret>
}
}
@@ -0,0 +1,12 @@
class Bar {
void repeatUntilPassesInSmartMode(final Runnable r) {
while (true) {
try {
r.run();
return;
}
catch (Throwable e) {
}
}
}
}
@@ -18,6 +18,7 @@ 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
*/
@@ -57,13 +58,22 @@ 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")
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()
}
}
@@ -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(); }
@@ -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
@@ -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<Integer, String>()"));
}
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$()"));
}
}
@@ -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());
@@ -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;
@@ -71,8 +72,8 @@ public class LocalTerminalDirectRunner extends AbstractTerminalRunner<PtyProcess
private static String findRCFile(String shellName) {
if (shellName != null) {
if ("bash".equals(shellName)) {
shellName = "sh";
if ("sh".equals(shellName)) {
shellName = "bash";
}
try {
@@ -81,6 +82,12 @@ public class LocalTerminalDirectRunner extends AbstractTerminalRunner<PtyProcess
rcfile = ".zshrc";
}
URL resource = LocalTerminalDirectRunner.class.getClassLoader().getResource(rcfile);
if (resource != null && "jar".equals(resource.getProtocol())) {
File file = new File(new File(PtyUtil.getJarContainingFolderPath(LocalTerminalDirectRunner.class)).getParent(), rcfile);
if (file.exists()) {
return file.getAbsolutePath();
}
}
if (resource != null) {
URI uri = resource.toURI();
return uri.getPath();
@@ -188,10 +195,9 @@ public class LocalTerminalDirectRunner extends AbstractTerminalRunner<PtyProcess
String rcFilePath = findRCFile(shellName);
if (rcFilePath != null &&
shellIntegration) {
if (shellName.equals("bash") || shellName.equals("sh")) {
if (shellName.equals("bash") || (SystemInfo.isMac && shellName.equals("sh"))) {
addRcFileArgument(envs, command, result, rcFilePath, "--rcfile");
}
else if (shellName.equals("zsh")) {
@@ -43,10 +43,10 @@ public class TerminalShellCommandTest extends TestCase {
}
public void testAddRcConfig() {
hasRcConfig("bash -i", "jediterm-sh.in", Maps.newHashMap());
hasRcConfig("sh --login", "jediterm-sh.in", Maps.newHashMap());
hasRcConfig("bash -i", "jediterm-bash.in", Maps.newHashMap());
hasRcConfig("sh --login", "jediterm-bash.in", Maps.newHashMap());
Map<String, String> 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"));
}
@@ -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 {
@@ -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()
}