diff --git a/build/scripts/tests.gant b/build/scripts/tests.gant index 6b66da56ba06..00acccec1053 100644 --- a/build/scripts/tests.gant +++ b/build/scripts/tests.gant @@ -1,18 +1,39 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome includeTargets << new File("${guessHome(this)}/build/scripts/common_tests.gant") setProperty("testcases", ["com.intellij.AllTests"]) + if ("GIT_TESTS".equalsIgnoreCase(System.getProperty("idea.test.group"))) { setProperty("cucumber_test_dirs", [["git4idea", "Idea", "$home/plugins/git4idea/test-features/git4idea", "git4idea"]]) } -def isMac = System.getProperty("os.name").toLowerCase().startsWith("mac") -def args = [ +List args = [ "-Xmx450m", "-XX:MaxPermSize=430m", "-XX:ReservedCodeCacheSize=96m" ] -if (isMac) args << "-d32"; + +if (System.getProperty("os.name").toLowerCase().startsWith("mac")) { + String vendor = System.getProperty("java.vm.vendor") + if (vendor != null && vendor.toLowerCase().contains("apple")) { + args << "-d32" + } +}; setProperty("jvm_args", args) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractChecker.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractChecker.java index 7fad6fddd121..213468e89b5c 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractChecker.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractChecker.java @@ -38,7 +38,6 @@ class ContractChecker extends DataFlowRunner { private final Set myViolations = ContainerUtil.newHashSet(); private final Set myNonViolations = ContainerUtil.newHashSet(); private final Set myFailures = ContainerUtil.newHashSet(); - private final Set myCalls = ContainerUtil.newHashSet(); ContractChecker(PsiMethod method, PsiCodeBlock body, MethodContract contract, final boolean onTheFly) { super(body); @@ -105,11 +104,13 @@ class ContractChecker extends DataFlowRunner { } if (instruction instanceof MethodCallInstruction && - ((MethodCallInstruction)instruction).getMethodType() == MethodCallInstruction.MethodType.REGULAR_METHOD_CALL) { - ContainerUtil.addIfNotNull(myCalls, ((MethodCallInstruction)instruction).getCallExpression()); + ((MethodCallInstruction)instruction).getMethodType() == MethodCallInstruction.MethodType.REGULAR_METHOD_CALL && + myContract.returnValue == MethodContract.ValueConstraint.THROW_EXCEPTION) { + ContainerUtil.addIfNotNull(myFailures, ((MethodCallInstruction)instruction).getCallExpression()); + return DfaInstructionState.EMPTY_ARRAY; } - return super.acceptInstruction(visitor, instructionState); + return super.acceptInstruction(visitor, instructionState); } @@ -125,7 +126,7 @@ class ContractChecker extends DataFlowRunner { for (PsiElement element : myFailures) { errors.put(element, "Contract clause '" + myContract + "' is violated: exception might be thrown instead of returning " + myContract.returnValue); } - } else if (myFailures.isEmpty() && errors.isEmpty() && myCalls.isEmpty()) { + } else if (myFailures.isEmpty() && errors.isEmpty()) { PsiIdentifier nameIdentifier = myMethod.getNameIdentifier(); errors.put(nameIdentifier != null ? nameIdentifier : myMethod, "Contract clause '" + myContract + "' is violated: no exception is thrown"); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java index 21dc78070f67..4ef9a1dbc08b 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java @@ -78,13 +78,15 @@ class ContractInferenceInterpreter { List inferContracts() { final boolean notNull = NullableNotNullManager.isNotNull(myMethod); + PsiTypeElement typeElement = myMethod.getReturnTypeElement(); + final PsiType returnType = typeElement == null ? null : typeElement.getType(); return ContainerUtil.filter(doInferContracts(), new Condition() { @Override public boolean value(MethodContract contract) { if (notNull && contract.returnValue == NOT_NULL_VALUE) { return false; } - return true; + return ContractInspection.isReturnTypeCompatible(returnType, contract.returnValue); } }); } @@ -98,31 +100,12 @@ class ContractInferenceInterpreter { if (statements[0] instanceof PsiReturnStatement) { List result = handleDelegation(((PsiReturnStatement)statements[0]).getReturnValue(), false); if (result != null) { - PsiTypeElement typeElement = myMethod.getReturnTypeElement(); - final boolean returningObject = typeElement == null || !(typeElement.getType() instanceof PsiClassType); - return ContainerUtil.findAll(result, new Condition() { - @Override - public boolean value(MethodContract contract) { - if ((contract.returnValue == NULL_VALUE || contract.returnValue == NOT_NULL_VALUE) && returningObject) { - return false; - } - if ((contract.returnValue == TRUE_VALUE || contract.returnValue == FALSE_VALUE) && !returningObject) { - return false; - } - - return true; - } - }); + return result; } } else if (statements[0] instanceof PsiExpressionStatement && ((PsiExpressionStatement)statements[0]).getExpression() instanceof PsiMethodCallExpression) { List result = handleDelegation(((PsiExpressionStatement)statements[0]).getExpression(), false); - if (result != null) return ContainerUtil.findAll(result, new Condition() { - @Override - public boolean value(MethodContract contract) { - return contract.returnValue == THROW_EXCEPTION || !textMatches(myMethod.getReturnTypeElement(), PsiKeyword.VOID); - } - }); + if (result != null) return result; } } @@ -385,15 +368,7 @@ class ContractInferenceInterpreter { result.addAll(toContracts(states, THROW_EXCEPTION)); } else if (statement instanceof PsiReturnStatement) { - List contracts = visitExpression(states, ((PsiReturnStatement)statement).getReturnValue()); - for (MethodContract contract : contracts) { - if ((contract.returnValue == TRUE_VALUE || contract.returnValue == FALSE_VALUE) && - !textMatches(myMethod.getReturnTypeElement(), PsiKeyword.BOOLEAN)) { - continue; - } - - result.add(contract); - } + result.addAll(visitExpression(states, ((PsiReturnStatement)statement).getReturnValue())); } else if (statement instanceof PsiAssertStatement) { List conditionResults = visitExpression(states, ((PsiAssertStatement)statement).getAssertCondition()); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInspection.java index 463ca738121f..dc86cba28de2 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInspection.java @@ -91,7 +91,30 @@ public class ContractInspection extends BaseJavaBatchLocalInspectionTool { if (contract.arguments.length != paramCount) { return "Method takes " + paramCount + " parameters, while contract clause number " + (i + 1) + " expects " + contract.arguments.length; } + PsiType returnType = method.getReturnType(); + if (returnType != null && !isReturnTypeCompatible(returnType, contract.returnValue)) { + return "Method returns " + returnType.getPresentableText() + " but the contract specifies " + contract.returnValue; + } } return null; } + + static boolean isReturnTypeCompatible(@Nullable PsiType returnType, @NotNull MethodContract.ValueConstraint returnValue) { + if (returnValue == MethodContract.ValueConstraint.ANY_VALUE || returnValue == MethodContract.ValueConstraint.THROW_EXCEPTION) { + return true; + } + if (PsiType.VOID.equals(returnType)) return false; + + if (PsiType.BOOLEAN.equals(returnType)) { + return returnValue == MethodContract.ValueConstraint.TRUE_VALUE || + returnValue == MethodContract.ValueConstraint.FALSE_VALUE; + } + + if (returnType instanceof PsiClassType) { + return returnValue == MethodContract.ValueConstraint.NULL_VALUE || + returnValue == MethodContract.ValueConstraint.NOT_NULL_VALUE; + } + + return true; + } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index 36b633068b87..bd225a84bb91 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -26,6 +26,7 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.*; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.FactoryMap; import com.intellij.util.containers.Stack; import com.siyeh.ig.numeric.UnnecessaryExplicitNumericCastInspection; import org.jetbrains.annotations.Contract; @@ -54,9 +55,9 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { private Stack myElementStack = new Stack(); /** - * A mock variable for try-related control transfers. Contains exceptions or an (Throwable-inconvertible) string to indicate return inside finally + * Variables for try-related control transfers. Contain exceptions or an (Throwable-inconvertible) string to indicate return inside finally */ - private DfaVariableValue myExceptionHolder; + private FactoryMap myExceptionHolders; ControlFlowAnalyzer(final DfaValueFactory valueFactory) { myFactory = valueFactory; @@ -64,7 +65,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { public ControlFlow buildControlFlow(@NotNull PsiElement codeFragment, boolean ignoreAssertions) { myIgnoreAssertions = ignoreAssertions; - PsiManager manager = codeFragment.getManager(); + final PsiManager manager = codeFragment.getManager(); GlobalSearchScope scope = codeFragment.getResolveScope(); myRuntimeException = myFactory.createTypeValue(createClassType(manager, scope, JAVA_LANG_RUNTIME_EXCEPTION), Nullness.NOT_NULL); myError = myFactory.createTypeValue(createClassType(manager, scope, JAVA_LANG_ERROR), Nullness.NOT_NULL); @@ -72,9 +73,16 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { myAssertionError = createClassType(manager, scope, JAVA_LANG_ASSERTION_ERROR); myString = myFactory.createTypeValue(createClassType(manager, scope, JAVA_LANG_STRING), Nullness.NOT_NULL); - PsiParameter mockVar = JavaPsiFacade.getElementFactory(manager.getProject()).createParameterFromText("java.lang.Object $exception$", null); - myExceptionHolder = myFactory.getVarFactory().createVariableValue(mockVar, false); - + myExceptionHolders = new FactoryMap() { + @Nullable + @Override + protected DfaVariableValue create(PsiTryStatement key) { + String text = "java.lang.Object $exception" + myExceptionHolders.size() + "$"; + PsiParameter mockVar = JavaPsiFacade.getElementFactory(manager.getProject()).createParameterFromText(text, null); + return myFactory.getVarFactory().createVariableValue(mockVar, false); + } + }; + myCatchStack = new Stack(); myCurrentFlow = new ControlFlow(myFactory); @@ -232,9 +240,10 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { if (description != null) { description.accept(this); } - - initException(myAssertionError); - addThrowCode(false, statement); + + CatchDescriptor cd = findNextCatch(false); + initException(myAssertionError, cd); + addThrowCode(cd, statement); } finishElement(statement); } @@ -569,14 +578,14 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { } private void returnCheckingFinally(boolean viaException, @NotNull PsiElement anchor) { - ControlFlow.ControlFlowOffset finallyOffset = getFinallyOffset(); - if (finallyOffset != null) { - addInstruction(new PushInstruction(myExceptionHolder, null)); + CatchDescriptor finallyDescriptor = findFinally(); + if (finallyDescriptor != null) { + addInstruction(new PushInstruction(getExceptionHolder(finallyDescriptor), null)); addInstruction(new PushInstruction(myString, null)); addInstruction(new AssignInstruction(null)); addInstruction(new PopInstruction()); - addInstruction(new GotoInstruction(finallyOffset)); + addInstruction(new GotoInstruction(finallyDescriptor.getJumpOffset(this))); } else { addInstruction(new ReturnInstruction(viaException, anchor)); } @@ -694,7 +703,8 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { if (exception != null) { exception.accept(this); - if (myCatchStack.isEmpty()) { + CatchDescriptor cd = findNextCatch(false); + if (cd == null) { addInstruction(new ReturnInstruction(true, statement)); finishElement(statement); return; @@ -708,22 +718,23 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { addInstruction(gotoInstruction); addInstruction(new PopInstruction()); - initException(myNpe); - addThrowCode(false, statement); + initException(myNpe, cd); + addThrowCode(cd, statement); gotoInstruction.setOffset(myCurrentFlow.getInstructionCount()); - addInstruction(new PushInstruction(myExceptionHolder, null)); + addInstruction(new PushInstruction(getExceptionHolder(cd), null)); addInstruction(new SwapInstruction()); addInstruction(new AssignInstruction(null)); addInstruction(new PopInstruction()); - addThrowCode(false, statement); + addThrowCode(cd, statement); } finishElement(statement); } private void addConditionalRuntimeThrow() { - if (myCatchStack.isEmpty()) { + CatchDescriptor cd = findNextCatch(false); + if (cd == null) { return; } @@ -731,7 +742,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { final ConditionalGotoInstruction ifNoException = addInstruction(new ConditionalGotoInstruction(null, false, null)); addInstruction(new EmptyStackInstruction()); - addInstruction(new PushInstruction(myExceptionHolder, null)); + addInstruction(new PushInstruction(getExceptionHolder(cd), null)); pushUnknown(); final ConditionalGotoInstruction ifError = addInstruction(new ConditionalGotoInstruction(null, false, null)); @@ -744,7 +755,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { addInstruction(new AssignInstruction(null)); addInstruction(new PopInstruction()); - addThrowCode(false, null); + addThrowCode(cd, null); ifNoException.setOffset(myCurrentFlow.getInstructionCount()); } @@ -762,14 +773,24 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { } // the exception object should be in $exception$ variable - private void addThrowCode(boolean catchRethrow, @Nullable PsiElement explicitThrower) { - if (myCatchStack.isEmpty()) { + private void addThrowCode(@Nullable CatchDescriptor cd, @Nullable PsiElement explicitThrower) { + if (cd == null) { addInstruction(new ReturnInstruction(true, explicitThrower)); return; } + flushVariablesOnControlTransfer(cd.getBlock()); + addInstruction(new GotoInstruction(cd.getJumpOffset(this))); + } + + @Nullable + private CatchDescriptor findNextCatch(boolean catchRethrow) { + if (myCatchStack.isEmpty()) { + return null; + } + PsiElement currentElement = myElementStack.peek(); - + CatchDescriptor cd = myCatchStack.get(myCatchStack.size() - 1); if (!cd.isFinally() && PsiTreeUtil.isAncestor(cd.getBlock().getParent(), currentElement, false)) { int i = myCatchStack.size() - 2; @@ -777,21 +798,20 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { i--; } if (i < 0) { - addInstruction(new ReturnInstruction(true, explicitThrower)); - return; + return null; } cd = myCatchStack.get(i); } - flushVariablesOnControlTransfer(cd.getBlock()); - addInstruction(new GotoInstruction(cd.getJumpOffset(this))); + return cd; } + @Nullable - private ControlFlow.ControlFlowOffset getFinallyOffset() { + private CatchDescriptor findFinally() { for (int i = myCatchStack.size() - 1; i >= 0; i--) { CatchDescriptor cd = myCatchStack.get(i); - if (cd.isFinally()) return cd.getJumpOffset(this); + if (cd.isFinally()) return cd; } return null; @@ -909,17 +929,17 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { } if (finallyBlock != null) { - myCatchStack.pop(); + CatchDescriptor finallyDescriptor = myCatchStack.pop(); finallyBlock.accept(this); //if $exception$==null => continue normal execution - addInstruction(new PushInstruction(myExceptionHolder, null)); + addInstruction(new PushInstruction(getExceptionHolder(finallyDescriptor), null)); addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, statement.getProject())); addInstruction(new ConditionalGotoInstruction(getEndOffset(statement), false, null)); // else throw $exception$ - addThrowCode(false, null); + rethrowException(finallyDescriptor, false); } finishElement(statement); @@ -930,35 +950,49 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { startElement(section); PsiCodeBlock catchBlock = section.getCatchBlock(); if (catchBlock != null) { - // exception is in myExceptionHolder mock variable + CatchDescriptor currentDescriptor = new CatchDescriptor(section.getParameter(), catchBlock); + DfaVariableValue exceptionHolder = getExceptionHolder(currentDescriptor); + + // exception is in exceptionHolder mock variable // check if it's assignable to catch parameter type PsiType declaredType = section.getCatchType(); - List flattened = declaredType instanceof PsiDisjunctionType ? - ((PsiDisjunctionType)declaredType).getDisjunctions() : + List flattened = declaredType instanceof PsiDisjunctionType ? + ((PsiDisjunctionType)declaredType).getDisjunctions() : ContainerUtil.createMaybeSingletonList(declaredType); for (PsiType catchType : flattened) { - addInstruction(new PushInstruction(myExceptionHolder, null)); + addInstruction(new PushInstruction(exceptionHolder, null)); addInstruction(new PushInstruction(myFactory.createTypeValue(catchType, Nullness.UNKNOWN), null)); addInstruction(new BinopInstruction(JavaTokenType.INSTANCEOF_KEYWORD, null, section.getProject())); addInstruction(new ConditionalGotoInstruction(ControlFlow.deltaOffset(getStartOffset(catchBlock), -5), false, null)); } // not assignable => rethrow - addThrowCode(true, null); + rethrowException(currentDescriptor, true); // e = $exception$ addInstruction(new PushInstruction(myFactory.getVarFactory().createVariableValue(section.getParameter(), false), null)); - addInstruction(new PushInstruction(myExceptionHolder, null)); + addInstruction(new PushInstruction(exceptionHolder, null)); addInstruction(new AssignInstruction(null)); addInstruction(new PopInstruction()); - addInstruction(new FlushVariableInstruction(myExceptionHolder)); + addInstruction(new FlushVariableInstruction(exceptionHolder)); catchBlock.accept(this); } finishElement(section); } + private void rethrowException(CatchDescriptor currentDescriptor, boolean catchRethrow) { + CatchDescriptor nextCatch = findNextCatch(catchRethrow); + if (nextCatch != null) { + addInstruction(new PushInstruction(getExceptionHolder(nextCatch), null, false)); + addInstruction(new PushInstruction(getExceptionHolder(currentDescriptor), null, true)); + addInstruction(new AssignInstruction(null)); + addInstruction(new PopInstruction()); + } + addThrowCode(nextCatch, null); + } + @Override public void visitResourceList(PsiResourceList resourceList) { for (PsiResourceVariable variable : resourceList.getResourceVariables()) { @@ -1335,6 +1369,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { } private void addMethodThrows(PsiMethod method, @Nullable PsiElement explicitCall) { + CatchDescriptor cd = findNextCatch(false); if (method != null) { PsiClassType[] refs = method.getThrowsList().getReferencedTypes(); for (PsiClassType ref : refs) { @@ -1342,20 +1377,25 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { ConditionalGotoInstruction cond = new ConditionalGotoInstruction(null, false, null); addInstruction(cond); addInstruction(new EmptyStackInstruction()); - initException(ref); - addThrowCode(false, explicitCall); + initException(ref, cd); + addThrowCode(cd, explicitCall); cond.setOffset(myCurrentFlow.getInstructionCount()); } } } - private void initException(PsiType ref) { - addInstruction(new PushInstruction(myExceptionHolder, null)); + private void initException(PsiType ref, @Nullable CatchDescriptor cd) { + if (cd == null) return; + addInstruction(new PushInstruction(getExceptionHolder(cd), null)); addInstruction(new PushInstruction(myFactory.createTypeValue(ref, Nullness.NOT_NULL), null)); addInstruction(new AssignInstruction(null)); addInstruction(new PopInstruction()); } + private DfaVariableValue getExceptionHolder(CatchDescriptor cd) { + return myExceptionHolders.get(cd.getTryStatement()); + } + @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { startElement(expression); diff --git a/java/java-tests/testData/inspection/dataFlow/contractCheck/NestedCallsMayThrow.java b/java/java-tests/testData/inspection/dataFlow/contractCheck/NestedCallsMayThrow.java index 073e3fab1bec..c7d15603047c 100644 --- a/java/java-tests/testData/inspection/dataFlow/contractCheck/NestedCallsMayThrow.java +++ b/java/java-tests/testData/inspection/dataFlow/contractCheck/NestedCallsMayThrow.java @@ -25,6 +25,14 @@ class Foo { failNatively(); } } + + @Contract("null->fail") + public Object assertNotNull(Object o) { + if (o == null) { + failNatively(); + } + return o; + } native void failNatively(); diff --git a/java/java-tests/testData/inspection/dataFlow/contractCheck/SignatureIssues.java b/java/java-tests/testData/inspection/dataFlow/contractCheck/SignatureIssues.java index 84c77511c7e8..412a4c820bbd 100644 --- a/java/java-tests/testData/inspection/dataFlow/contractCheck/SignatureIssues.java +++ b/java/java-tests/testData/inspection/dataFlow/contractCheck/SignatureIssues.java @@ -11,4 +11,13 @@ class Foo { @Contract(pure=true) void voidPureMethod() {} + @Contract("->null") + public native void throwMe(); + + @Contract("->null") + public native boolean wrongReturnType(); + + @Contract("->true") + public native String wrongReturnType2(); + } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/TryFinallyInsideFinally.java b/java/java-tests/testData/inspection/dataFlow/fixture/TryFinallyInsideFinally.java new file mode 100644 index 000000000000..b87492380f6d --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/TryFinallyInsideFinally.java @@ -0,0 +1,23 @@ +class Test { + private String foo; + + public void test() { + boolean rangeMarkersDisposed = false; + try { + if (foo == "dd") { + throw new RuntimeException(); + } + rangeMarkersDisposed = true; + } + finally { + try { + } + finally { + } + + if (!rangeMarkersDisposed) { + foo = "dd"; + } + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index 405478625937..754a6dcd31f3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -67,6 +67,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { public void testExceptionFromFinally() throws Throwable { doTest(); } public void testExceptionFromFinallyNesting() throws Throwable { doTest(); } public void testNestedFinally() { doTest(); } + public void testTryFinallyInsideFinally() { doTest(); } public void testFieldChangedBetweenSynchronizedBlocks() throws Throwable { doTest(); } public void testGeneratedEquals() throws Throwable { doTest(); } diff --git a/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java b/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java index 1cf0e078bfd3..4bbf705c23fe 100644 --- a/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java +++ b/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java @@ -27,7 +27,6 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.SystemProperties; -import org.jdom.Document; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; @@ -102,7 +101,7 @@ public class CompilerTestUtil { //emulate save via 'saveSettings' so file won't be treated as changed externally OutputStream stream = virtualFile.getOutputStream(new SaveSessionRequestor()); try { - JDOMUtil.writeDocument(new Document(root), stream, SystemProperties.getLineSeparator()); + JDOMUtil.writeParent(root, stream, SystemProperties.getLineSeparator()); } finally { stream.close(); diff --git a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java index 7386fe0e9d41..ba6bb7474fc4 100644 --- a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java @@ -125,11 +125,6 @@ public class ModuleStoreImpl extends BaseFileConfigurableStoreImpl implements IM } } - @Override - public boolean isEmpty() { - return super.isEmpty() && myOptions.isEmpty(); - } - @Override @NotNull protected Element save(@NotNull Map newLiveStates) { diff --git a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java index 3e63072599f1..8d0548ccd70a 100644 --- a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.components.impl.stores; +import com.intellij.openapi.components.StateStorage.SaveSession; import com.intellij.openapi.components.TrackingPathMacroSubstitutor; import com.intellij.openapi.components.store.ComponentSaveSession; import com.intellij.openapi.module.Module; @@ -45,11 +46,10 @@ public class ProjectWithModulesStoreImpl extends ProjectStoreImpl { } for (Module module : getPersistentModules()) { - if (((ModuleStoreImpl)((ModuleImpl)module).getStateStore()).reinitComponent(componentName, reloadData)) { - return true; - } + // we have to reinit all modules for component because we don't know affected module + ((ModuleStoreImpl)((ModuleImpl)module).getStateStore()).reinitComponent(componentName, reloadData); } - return false; + return true; } @Override @@ -124,7 +124,7 @@ public class ProjectWithModulesStoreImpl extends ProjectStoreImpl { } @Override - protected void beforeSave(@NotNull List> readonlyFiles) { + protected void beforeSave(@NotNull List> readonlyFiles) { super.beforeSave(readonlyFiles); for (ComponentSaveSession moduleSaveSession : myModuleSaveSessions) { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java b/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java index b726f9ece414..936a3362a51c 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java @@ -17,7 +17,6 @@ package com.intellij.ide.actions; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.util.SystemInfo; @@ -27,6 +26,11 @@ import org.jetbrains.annotations.NotNull; import java.io.File; public class RevealFileAction extends DumbAwareAction { + + public RevealFileAction() { + getTemplatePresentation().setText(getActionName()); + } + @Override public void update(AnActionEvent e) { VirtualFile file = ShowFilePathAction.findLocalFile(CommonDataKeys.VIRTUAL_FILE.getData(e.getDataContext())); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/search/SearchableOptionsRegistrarImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/search/SearchableOptionsRegistrarImpl.java index 2daae1ae7da6..aa224b33be2b 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/search/SearchableOptionsRegistrarImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/search/SearchableOptionsRegistrarImpl.java @@ -244,7 +244,7 @@ public class SearchableOptionsRegistrarImpl extends SearchableOptionsRegistrar { } } - if (options.isEmpty()) { + if (configurables != null && options.isEmpty()) { hits.getNameHits().add(each); hits.getNameFullHits().add(each); } diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsHttpClientSender.java b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsHttpClientSender.java index 954babd73ec6..5da90c972433 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsHttpClientSender.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsHttpClientSender.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import com.intellij.openapi.updateSettings.impl.UpdateChecker; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.net.HttpConfigurable; import org.apache.http.Header; +import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.fluent.Form; import org.apache.http.client.fluent.Request; @@ -37,11 +38,13 @@ public class StatisticsHttpClientSender implements StatisticsDataSender { add("content", content). add("uuid", UpdateChecker.getInstallationUID(PropertiesComponent.getInstance())). add("ide", ApplicationNamesInfo.getInstance().getProductName()).build()).execute(); - if (response.returnResponse().getStatusLine().getStatusCode() != HttpStatus.SC_OK) { - throw new StatServiceException("Error during data sending... Code: " + response.returnResponse().getStatusLine().getStatusCode()); + + final HttpResponse httpResponse = response.returnResponse(); + if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + throw new StatServiceException("Error during data sending... Code: " + httpResponse.getStatusLine().getStatusCode()); } - final Header errors = response.returnResponse().getFirstHeader("errors"); + final Header errors = httpResponse.getFirstHeader("errors"); if (errors != null) { String value = errors.getValue(); throw new StatServiceException("Error during updating statistics " + (!StringUtil.isEmptyOrSpaces(value) ? " : " + value : "")); diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/tmp/SendStatisticsAction.java b/platform/platform-impl/src/com/intellij/internal/statistic/tmp/SendStatisticsAction.java index 4fddde766229..c6c02ceb7148 100755 --- a/platform/platform-impl/src/com/intellij/internal/statistic/tmp/SendStatisticsAction.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/tmp/SendStatisticsAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,19 +21,40 @@ import com.intellij.internal.statistic.connect.StatisticsService; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; -import com.intellij.util.PlatformIcons; +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; public class SendStatisticsAction extends AnAction { @Override - public void actionPerformed(AnActionEvent e) { + public void actionPerformed(@NotNull AnActionEvent e) { final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); - if (project != null) { - StatisticsService service = StatisticsUploadAssistant.getStatisticsService(); - StatisticsResult result = service.send(); - Messages.showMessageDialog(result.getDescription(), "Result", PlatformIcons.CUSTOM_FILE_ICON); + if (project == null) { + return; } + + ProgressManager.getInstance().run(new Task.Backgroundable(project, "Sending statistics...", false) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + StatisticsService service = StatisticsUploadAssistant.getStatisticsService(); + final StatisticsResult result = service.send(); + + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + Messages.showMultilineInputDialog(project, "Result: " + result.getCode(), "Statistics Result", + StringUtil.replace(result.getDescription(), ";", "\n"), + null, null); + } + }, ModalityState.NON_MODAL, project.getDisposed()); + } + }); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java index dd145a3758f5..f4f0992f8398 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java @@ -20,6 +20,7 @@ import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.components.*; +import com.intellij.openapi.components.StateStorage.SaveSession; import com.intellij.openapi.components.impl.ComponentManagerImpl; import com.intellij.openapi.components.store.ComponentSaveSession; import com.intellij.openapi.components.store.ReadOnlyModificationException; @@ -107,7 +108,7 @@ public abstract class ComponentStoreImpl implements IComponentStore { } } - StateStorageManager.SaveSession storageManagerSaveSession = storageManager.startSave(externalizationSession); + SaveSession storageManagerSaveSession = storageManager.startSave(externalizationSession); if (storageManagerSaveSession == null) { return null; } @@ -340,7 +341,7 @@ public abstract class ComponentStoreImpl implements IComponentStore { return null; } - protected static void executeSave(@NotNull StateStorageManager.SaveSession saveSession, @NotNull List> readonlyFiles) { + protected static void executeSave(@NotNull SaveSession saveSession, @NotNull List> readonlyFiles) { try { saveSession.save(); } @@ -350,14 +351,14 @@ public abstract class ComponentStoreImpl implements IComponentStore { } protected class SaveSessionImpl implements ComponentSaveSession { - protected StateStorageManager.SaveSession myStorageManagerSaveSession; + protected SaveSession myStorageManagerSaveSession; public SaveSessionImpl() { } @NotNull @Override - public ComponentSaveSession save(@NotNull List> readonlyFiles) { + public ComponentSaveSession save(@NotNull List> readonlyFiles) { SettingsSavingComponent[] settingsComponents = mySettingsSavingComponents.toArray(new SettingsSavingComponent[mySettingsSavingComponents.size()]); for (SettingsSavingComponent settingsSavingComponent : settingsComponents) { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java index 3df9fa12c28c..11956153ddcf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.components.*; +import com.intellij.openapi.components.StateStorage.SaveSession; import com.intellij.openapi.options.StreamProvider; import com.intellij.openapi.project.impl.ProjectImpl; import com.intellij.openapi.project.impl.ProjectManagerImpl; @@ -35,7 +36,7 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { private final ProjectManagerImpl myProjectManager; @NonNls private static final String ROOT_TAG_NAME = "defaultProject"; - public DefaultProjectStoreImpl(@NotNull ProjectImpl project, final ProjectManagerImpl projectManager) { + public DefaultProjectStoreImpl(@NotNull ProjectImpl project, @NotNull ProjectManagerImpl projectManager) { super(project); myProjectManager = projectManager; @@ -58,12 +59,9 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { _d = myElement; } - final ComponentManager componentManager = getComponentManager(); - final PathMacroManager pathMacroManager = PathMacroManager.getInstance(componentManager); - + ComponentManager componentManager = getComponentManager(); final Element element = _d; - - final XmlElementStorage storage = new XmlElementStorage("", RoamingType.DISABLED, pathMacroManager.createTrackingSubstitutor(), componentManager, + final XmlElementStorage storage = new XmlElementStorage("", RoamingType.DISABLED, PathMacroManager.getInstance(componentManager).createTrackingSubstitutor(), componentManager, ROOT_TAG_NAME, null, ComponentVersionProvider.EMPTY) { @Override @@ -77,7 +75,8 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { return new MySaveSession(storageData) { @Override protected void doSave(@Nullable Element element) { - myProjectManager.setDefaultProjectRootElement(element == null ? null : element); + // we must set empty element instead of null as indicator - ProjectManager state is ready to save + myProjectManager.setDefaultProjectRootElement(element == null ? new Element("empty") : element); } // we must not collapse paths here, because our solution is just a big hack @@ -147,8 +146,7 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { @Nullable @Override public SaveSession startSave(@NotNull ExternalizationSession externalizationSession) { - StateStorage.SaveSession saveSession = storage.startSave(((MyExternalizationSession)externalizationSession).externalizationSession); - return saveSession == null ? null : new MySaveSession(saveSession); + return storage.startSave(((MyExternalizationSession)externalizationSession).externalizationSession); } @Override @@ -211,8 +209,7 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { } @Override - public void setState(@NotNull Storage[] storageSpecs, @NotNull Object component, @NotNull String componentName, @NotNull Object state) - throws StateStorageException { + public void setState(@NotNull Storage[] storageSpecs, @NotNull Object component, @NotNull String componentName, @NotNull Object state) { externalizationSession.setState(component, componentName, state, null); } @@ -221,17 +218,4 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { externalizationSession.setState(component, componentName, state, null); } } - - private static class MySaveSession implements StateStorageManager.SaveSession { - @NotNull private final StateStorage.SaveSession saveSession; - - public MySaveSession(@NotNull StateStorage.SaveSession saveSession) { - this.saveSession = saveSession; - } - - @Override - public void save() { - saveSession.save(); - } - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java index e0fbd85adb20..db381105f4b9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java @@ -21,6 +21,7 @@ import com.intellij.ide.highlighter.WorkspaceFileType; import com.intellij.notification.NotificationsManager; import com.intellij.openapi.application.*; import com.intellij.openapi.components.*; +import com.intellij.openapi.components.StateStorage.SaveSession; import com.intellij.openapi.components.store.ComponentSaveSession; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileType; @@ -468,7 +469,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject protected class ProjectSaveSession extends SaveSessionImpl { @NotNull @Override - public ComponentSaveSession save(@NotNull List> readonlyFiles) { + public ComponentSaveSession save(@NotNull List> readonlyFiles) { ProjectImpl.UnableToSaveProjectNotification[] notifications = NotificationsManager.getNotificationsManager().getNotificationsOfType(ProjectImpl.UnableToSaveProjectNotification.class, myProject); if (notifications.length > 0) { @@ -495,7 +496,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject } else { readonlyFiles.clear(); - for (Pair entry : readonlyFiles) { + for (Pair entry : readonlyFiles) { executeSave(entry.first, readonlyFiles); } @@ -510,7 +511,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject } @NotNull - private VirtualFile[] getFilesList(List> readonlyFiles) { + private VirtualFile[] getFilesList(List> readonlyFiles) { final VirtualFile[] files = new VirtualFile[readonlyFiles.size()]; for (int i = 0, size = readonlyFiles.size(); i < size; i++) { files[i] = readonlyFiles.get(i).second; @@ -518,7 +519,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject return files; } - protected void beforeSave(@NotNull List> readonlyFiles) { + protected void beforeSave(@NotNull List> readonlyFiles) { } } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java index a9cafbc09bfc..28a83ecfbb02 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java @@ -62,9 +62,9 @@ public interface StateStorageManager { * return null if nothing to save */ @Nullable - SaveSession startSave(@NotNull ExternalizationSession externalizationSession); + StateStorage.SaveSession startSave(@NotNull ExternalizationSession externalizationSession); - void finishSave(@NotNull SaveSession saveSession); + void finishSave(@NotNull StateStorage.SaveSession saveSession); @Nullable StateStorage getOldStorage(@NotNull Object component, @NotNull String componentName, @NotNull StateStorageOperation operation); @@ -88,8 +88,4 @@ public interface StateStorageManager { void setStateInOldStorage(@NotNull Object component, @NotNull String componentName, @NotNull Object state); } - - interface SaveSession { - void save(); - } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java index e942479c5b57..23d192ba6fe2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java @@ -20,6 +20,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.*; +import com.intellij.openapi.components.StateStorage.SaveSession; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.CurrentUserHolder; import com.intellij.openapi.util.Couple; @@ -413,12 +414,12 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di @Override public SaveSession startSave(@NotNull ExternalizationSession externalizationSession) { StateStorageManagerExternalizationSession myExternalizationSession = (StateStorageManagerExternalizationSession)externalizationSession; - Map saveSessions = null; + Map saveSessions = null; for (StateStorage stateStorage : myExternalizationSession.mySessions.keySet()) { - StateStorage.SaveSession saveSession = stateStorage.startSave(myExternalizationSession.getExternalizationSession(stateStorage)); + SaveSession saveSession = stateStorage.startSave(myExternalizationSession.getExternalizationSession(stateStorage)); if (saveSession != null) { if (saveSessions == null) { - saveSessions = new SmartHashMap(); + saveSessions = new SmartHashMap(); } saveSessions.put(stateStorage, saveSession); } @@ -496,15 +497,15 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di protected abstract String getOldStorageSpec(@NotNull Object component, @NotNull String componentName, @NotNull StateStorageOperation operation); private final static class StateStorageSaveSession implements SaveSession { - private final Map mySaveSessions; + private final Map mySaveSessions; - public StateStorageSaveSession(@NotNull Map saveSessions) { + public StateStorageSaveSession(@NotNull Map saveSessions) { mySaveSessions = saveSessions; } @Override public void save() { - for (StateStorage.SaveSession saveSession : mySaveSessions.values()) { + for (SaveSession saveSession : mySaveSessions.values()) { saveSession.save(); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StoreUtil.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StoreUtil.java index 10a96cb631bc..eb37f0621f69 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StoreUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StoreUtil.java @@ -17,6 +17,7 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.diagnostic.IdeErrorsDialog; import com.intellij.diagnostic.PluginException; +import com.intellij.openapi.components.StateStorage.SaveSession; import com.intellij.openapi.components.StateStorageException; import com.intellij.openapi.components.store.ComponentSaveSession; import com.intellij.openapi.extensions.PluginId; @@ -43,7 +44,7 @@ public class StoreUtil { ShutDownTracker.getInstance().registerStopperThread(Thread.currentThread()); try { - List> readonlyFiles = new SmartList>(); + List> readonlyFiles = new SmartList>(); session.save(readonlyFiles); } catch (Throwable e) { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/store/ComponentSaveSession.java b/platform/platform-impl/src/com/intellij/openapi/components/store/ComponentSaveSession.java index 042048add609..68a6e0576983 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/store/ComponentSaveSession.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/store/ComponentSaveSession.java @@ -15,7 +15,7 @@ */ package com.intellij.openapi.components.store; -import com.intellij.openapi.components.impl.stores.StateStorageManager; +import com.intellij.openapi.components.StateStorage; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; @@ -24,7 +24,7 @@ import java.util.List; public interface ComponentSaveSession { @NotNull - ComponentSaveSession save(@NotNull List> readonlyFiles); + ComponentSaveSession save(@NotNull List> readonlyFiles); void finishSave(); } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index 9b80ac319367..d68940a964cc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -28,10 +28,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.application.*; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.application.impl.ApplicationImpl; -import com.intellij.openapi.components.ExportableApplicationComponent; -import com.intellij.openapi.components.StateStorage; -import com.intellij.openapi.components.StateStorageException; -import com.intellij.openapi.components.TrackingPathMacroSubstitutor; +import com.intellij.openapi.components.*; import com.intellij.openapi.components.impl.stores.FileBasedStorage; import com.intellij.openapi.components.impl.stores.StateStorageManager; import com.intellij.openapi.components.impl.stores.StorageUtil; @@ -52,10 +49,7 @@ import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.impl.local.FileWatcher; import com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl; import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame; -import com.intellij.util.Alarm; -import com.intellij.util.ArrayUtil; -import com.intellij.util.SmartList; -import com.intellij.util.TimeoutUtil; +import com.intellij.util.*; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.containers.SmartHashSet; @@ -74,13 +68,19 @@ import java.io.IOException; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; -public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExternalizable, ExportableApplicationComponent { - private static final Logger LOG = Logger.getInstance("#com.intellij.project.impl.ProjectManagerImpl"); +@State( + name = "ProjectManager", + storages = { + @Storage( + file = StoragePathMacros.APP_CONFIG + "/project.default.xml" + )} +) +public class ProjectManagerImpl extends ProjectManagerEx implements PersistentStateComponent, ExportableApplicationComponent { + private static final Logger LOG = Logger.getInstance(ProjectManagerImpl.class); public static final int CURRENT_FORMAT_VERSION = 4; private static final Key> LISTENERS_IN_PROJECT_KEY = Key.create("LISTENERS_IN_PROJECT_KEY"); - private static final String ELEMENT_DEFAULT_PROJECT = "defaultProject"; @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) private ProjectImpl myDefaultProject; // Only used asynchronously in save and dispose, which itself are synchronized. @@ -94,7 +94,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt private final Set myTestProjects = new THashSet(); private final MultiMap myChangedProjectFiles = MultiMap.createSet(); - private final Alarm myChangedFilesAlarm = new Alarm(); + private final SingleAlarm myChangedFilesAlarm; private final List> myChangedApplicationFiles = new SmartList>(); private final AtomicInteger myReloadBlockCount = new AtomicInteger(0); private final ProgressManager myProgressManager; @@ -169,9 +169,20 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt ); registerExternalProjectFileListener(virtualFileManager); + myChangedFilesAlarm = new SingleAlarm(new Runnable() { + @Override + public void run() { + if (LOG.isDebugEnabled()) { + LOG.debug("[RELOAD] Scheduling reload application & project, myReloadBlockCount = " + myReloadBlockCount.get()); + } + if (myReloadBlockCount.get() == 0) { + scheduleReloadApplicationAndProject(); + } + } + }, 444); } - static class ChangedFileEntry { + static final class ChangedFileEntry { public VirtualFile file; public StateStorage storage; public long timestamp; @@ -183,6 +194,22 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt timestamp = file.getTimeStamp(); savedContent = file.contentsToByteArray(); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || !(o instanceof ChangedFileEntry)) { + return false; + } + return file.equals(((ChangedFileEntry)o).file); + } + + @Override + public int hashCode() { + return file.hashCode(); + } } private void projectStorageFileChanged(@NotNull VirtualFileEvent event, @NotNull StateStorage storage, @Nullable Project project) { @@ -614,7 +641,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt WelcomeFrame.showIfNoProjectOpened(); } - private void registerExternalProjectFileListener(VirtualFileManager virtualFileManager) { + private void registerExternalProjectFileListener(@NotNull VirtualFileManager virtualFileManager) { virtualFileManager.addVirtualFileManagerListener(new VirtualFileManagerListener() { @Override public void beforeRefreshStart(boolean asynchronous) { @@ -628,7 +655,9 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } private void askToReloadProjectIfConfigFilesChangedExternally() { - LOG.debug("[RELOAD] myReloadBlockCount = " + myReloadBlockCount.get()); + if (LOG.isDebugEnabled()) { + LOG.debug("[RELOAD] myReloadBlockCount = " + myReloadBlockCount.get()); + } if (myReloadBlockCount.get() == 0) { Set projects; synchronized (myChangedProjectFiles) { @@ -653,60 +682,54 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } private boolean tryToReloadApplication() { + if (ApplicationManager.getApplication().isDisposed()) { + return false; + } + if (myChangedApplicationFiles.isEmpty()) { + return true; + } + + Set> causes = new THashSet>(myChangedApplicationFiles); + myChangedApplicationFiles.clear(); + + Collection reloadResult; + AccessToken token = WriteAction.start(); try { - final Application app = ApplicationManager.getApplication(); - if (app.isDisposed()) { - return false; - } - final Set> causes = new THashSet>(myChangedApplicationFiles); - if (causes.isEmpty()) { - return true; - } - - final Ref> reloadResult = Ref.create(); - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - try { - reloadResult.set(((ApplicationImpl)app).getStateStore().reload(causes)); - } - catch (Exception e) { - Messages.showWarningDialog(ProjectBundle.message("project.reload.failed", e.getMessage()), - ProjectBundle.message("project.reload.failed.title")); - } - } - }); - - if (reloadResult.isNull()) { - return true; - } - - if (!reloadResult.get().isEmpty()) { - String message = "Application components were changed externally and cannot be reloaded:\n"; - for (String component : reloadResult.get()) { - message += component + "\n"; - } - - final boolean canRestart = ApplicationManager.getApplication().isRestartCapable(); - message += "Would you like to " + (canRestart ? "restart " : "shutdown "); - message += ApplicationNamesInfo.getInstance().getProductName() + "?"; - - if (Messages.showYesNoDialog(message, - "Application Configuration Reload", Messages.getQuestionIcon()) == Messages.YES) { - for (Pair cause : causes) { - StateStorage stateStorage = cause.getSecond(); - if (stateStorage instanceof XmlElementStorage) { - ((XmlElementStorage)stateStorage).disableSaving(); - } - } - ApplicationManagerEx.getApplicationEx().restart(true); - } - } + reloadResult = ((ApplicationImpl)ApplicationManager.getApplication()).getStateStore().reload(causes); + } + catch (Exception e) { + Messages.showWarningDialog(ProjectBundle.message("project.reload.failed", e.getMessage()), + ProjectBundle.message("project.reload.failed.title")); return false; } finally { - myChangedApplicationFiles.clear(); + token.finish(); } + + if (ContainerUtil.isEmpty(reloadResult)) { + return true; + } + + StringBuilder message = new StringBuilder("Application components were changed externally and cannot be reloaded:\n"); + for (String component : reloadResult) { + message.append(component).append('\n'); + } + + final boolean canRestart = ApplicationManager.getApplication().isRestartCapable(); + message.append("Would you like to ").append(canRestart ? "restart" : "shutdown").append(' '); + message.append(ApplicationNamesInfo.getInstance().getProductName()).append('?'); + + if (Messages.showYesNoDialog(message.toString(), + "Application Configuration Reload", Messages.getQuestionIcon()) == Messages.YES) { + for (Pair cause : causes) { + StateStorage stateStorage = cause.getSecond(); + if (stateStorage instanceof XmlElementStorage) { + ((XmlElementStorage)stateStorage).disableSaving(); + } + } + ApplicationManagerEx.getApplicationEx().restart(true); + } + return false; } @Nullable @@ -872,16 +895,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } } - myChangedFilesAlarm.cancelAllRequests(); - myChangedFilesAlarm.addRequest(new Runnable() { - @Override - public void run() { - LOG.debug("[RELOAD] Scheduling reload application & project, myReloadBlockCount = " + myReloadBlockCount); - if (myReloadBlockCount.get() == 0) { - scheduleReloadApplicationAndProject(); - } - } - }, 444); + myChangedFilesAlarm.cancelAndRequest(); } @Override @@ -1118,35 +1132,37 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt Messages.getWarningIcon()) == 0; } + + @Nullable @Override - public void writeExternal(Element parentNode) { + public Element getState() { if (myDefaultProject != null) { myDefaultProject.save(); } + if (myDefaultProjectRootElement == null) { + // we are not ready to save + return null; + } + + Element element = new Element("state"); + myDefaultProjectRootElement.detach(); + element.addContent(myDefaultProjectRootElement); + return element; + } + + @Override + public void loadState(Element state) { + myDefaultProjectRootElement = state.getChild("defaultProject"); if (myDefaultProjectRootElement != null) { myDefaultProjectRootElement.detach(); - parentNode.addContent(myDefaultProjectRootElement); } } - public void setDefaultProjectRootElement(@Nullable Element defaultProjectRootElement) { + public void setDefaultProjectRootElement(@NotNull Element defaultProjectRootElement) { myDefaultProjectRootElement = defaultProjectRootElement; } - @Override - public void readExternal(Element parentNode) { - myDefaultProjectRootElement = parentNode.getChild(ELEMENT_DEFAULT_PROJECT); - if (myDefaultProjectRootElement != null) { - myDefaultProjectRootElement.detach(); - } - } - - @Override - public String getExternalFileName() { - return "project.default"; - } - @Override @NotNull public String getComponentName() { @@ -1156,7 +1172,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt @Override @NotNull public File[] getExportFiles() { - return new File[]{PathManager.getOptionsFile(this)}; + return new File[]{PathManager.getOptionsFile("project.default")}; } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/IncompatibleEncodingDialog.java b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/IncompatibleEncodingDialog.java index 7470f9222f95..1f6f7aa7117b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/IncompatibleEncodingDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/IncompatibleEncodingDialog.java @@ -126,7 +126,9 @@ public class IncompatibleEncodingDialog extends DialogWrapper { convertAction.putValue(Action.SMALL_ICON, AllIcons.General.Warning); } convertAction.putValue(Action.MNEMONIC_KEY, (int)'C'); - return new Action[]{reloadAction, convertAction, getCancelAction()}; + Action cancelAction = getCancelAction(); + cancelAction.putValue(DEFAULT_ACTION, Boolean.TRUE); + return new Action[]{reloadAction, convertAction, cancelAction}; } public static final int RELOAD_EXIT_CODE = 10; diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 58bc65a31f6e..b3cd91e34915 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -1381,7 +1381,6 @@ action.Console.History.Next.text=Next action.Console.History.Next.description=Next console history entry action.Console.History.Browse.text=Browse History action.Console.History.Browse.description=Browse console history -action.RevealIn.text=Show/Reveal in Explorer/Finder/Konqueror/Nautilus action.RevealIn.description=Highlights the file in platform's file manager action.GoToLinkTarget.text=Go to Link Target action.GoToLinkTarget.description=Opens a target ot this symlink in the Project View diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 8bb72b556979..78ea8dce2c9e 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -712,7 +712,7 @@ label.please.enter.project.name=Please enter a name to create a new {0} {1}. prompt.please.select.project.jdk=Please select project SDK.\nThis SDK will be used by default by all project modules. label.project.jdk=Project SDK: button.configure=&Configure... -prompt.confirm.project.no.jdk=Do you want to create a project with no SDK assigned?\nAn SDK is required for compiling, debugging and running applications\n, as well as for the standard SDK classes resolution. +prompt.confirm.project.no.jdk=Do you want to create a project with no SDK assigned?\nAn SDK is required for compiling, debugging and running applications,\nas well as for the standard SDK classes resolution. title.no.jdk.specified=No SDK Specified prompt.please.specify.module.name=Please specify module name prompt.please.specify.module.name.and.content.root=Please specify module name and module content root.\nA module content root is a directory where the files that belong to the module are stored. diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index 956a90ea3c14..42600e35a72c 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -647,7 +647,7 @@ - + diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/StorageData.java b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/StorageData.java index d4f301bee8de..b13d4ecf081c 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/StorageData.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/StorageData.java @@ -369,10 +369,6 @@ public class StorageData { return diffs; } - public boolean isEmpty() { - return myComponentStates.isEmpty(); - } - public boolean hasState(@NotNull String componentName) { return myComponentStates.get(componentName) instanceof Element; } diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/CompletionAutoPopupTester.groovy b/platform/testFramework/src/com/intellij/testFramework/fixtures/CompletionAutoPopupTester.groovy index 1711aa69bf47..4f01645b19c3 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/CompletionAutoPopupTester.groovy +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/CompletionAutoPopupTester.groovy @@ -61,9 +61,13 @@ class CompletionAutoPopupTester { if (condition(phase)) { return } + if (j >= 400 && j % 100 == 0) { + println "Free memory: " + Runtime.runtime.freeMemory() + " of " + Runtime.runtime.totalMemory() + "\n" + UsefulTestCase.printThreadDump() + println "\n\n----------------------------\n\n" + } Thread.sleep(10) } - UsefulTestCase.printThreadDump() UsefulTestCase.fail("Too long completion: " + CompletionServiceImpl.phaseRaw) } diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index b860131d285b..bf670c8abce7 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -1407,14 +1407,17 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig private PsiFile configureInner(@NotNull final VirtualFile copy, @NotNull final SelectionAndCaretMarkupLoader loader) { assertInitialized(); + new WriteCommandAction.Simple(getProject()) { @Override public void run() { - try { - copy.setBinaryContent(loader.newFileText.getBytes(copy.getCharset())); - } - catch (IOException e) { - throw new RuntimeException(e); + if (!copy.getFileType().isBinary()) { + try { + copy.setBinaryContent(loader.newFileText.getBytes(copy.getCharset())); + } + catch (IOException e) { + throw new RuntimeException(e); + } } myFile = copy; myEditor = createEditor(copy); @@ -1436,7 +1439,6 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig } }.execute().throwException(); - return getFile(); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/BlockReloadingUtil.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/BlockReloadingUtil.java index 56308a42ce41..40ddcd5e6bc3 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/BlockReloadingUtil.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/BlockReloadingUtil.java @@ -17,6 +17,7 @@ package com.intellij.openapi.vcs.update; import com.intellij.openapi.project.ex.ProjectManagerEx; +@Deprecated public class BlockReloadingUtil { private BlockReloadingUtil() { } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionBase.java index 5306ade7d656..302c9f18cc88 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionBase.java @@ -35,7 +35,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -199,11 +198,7 @@ public class IgnoreResultOfCallInspectionBase extends BaseInspection { return false; } } - if (pattern == null) { - return false; - } - final Matcher matcher = pattern.matcher(methodName); - return matcher.matches(); + return pattern.matcher(methodName).matches(); } } } diff --git a/plugins/java-decompiler/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java b/plugins/java-decompiler/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java index c6c9ab8dfb87..9d099f46bab1 100644 --- a/plugins/java-decompiler/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java +++ b/plugins/java-decompiler/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java @@ -15,11 +15,15 @@ */ package org.jetbrains.java.decompiler; +import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction; +import com.intellij.openapi.application.PluginPathManager; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.vfs.StandardFileSystems; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileVisitor; +import com.intellij.pom.Navigatable; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.compiled.ClsFileImpl; @@ -28,15 +32,13 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import org.jetbrains.annotations.NotNull; public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase { - private static final String BANNER = IdeaDecompiler.BANNER; - public void testSimple() { String path = PlatformTestUtil.getRtJarPath() + "!/java/lang/String.class"; VirtualFile file = StandardFileSystems.jar().findFileByPath(path); assertNotNull(path, file); String decompiled = new IdeaDecompiler().getText(file).toString(); - assertTrue(decompiled.startsWith(BANNER + "package java.lang;\n")); + assertTrue(decompiled.startsWith(IdeaDecompiler.BANNER + "package java.lang;\n")); assertTrue(decompiled, decompiled.contains("public final class String")); assertTrue(decompiled, decompiled.contains("@deprecated")); assertTrue(decompiled, decompiled.contains("private static class CaseInsensitiveComparator")); @@ -69,4 +71,28 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase { } }); } + + public void testNavigation() { + String path = PluginPathManager.getPluginHomePath("java-decompiler") + "/testData/Navigation.class"; + VirtualFile file = StandardFileSystems.local().findFileByPath(path); + assertNotNull(path, file); + myFixture.configureFromExistingVirtualFile(file); + + String text = myFixture.getEditor().getDocument().getText(); + assertTrue(text, text.startsWith(IdeaDecompiler.BANNER)); + + doTestNavigation(11, 14, 14, 10); // to "m2()" + doTestNavigation(15, 21, 14, 17); // to "int i" + doTestNavigation(16, 28, 15, 13); // to "int r" + } + + private void doTestNavigation(int line, int column, int expLine, int expColumn) { + Editor editor = myFixture.getEditor(); + int offset = editor.getDocument().getLineStartOffset(line - 1) + column - 1; + PsiElement target = GotoDeclarationAction.findTargetElement(getProject(), editor, offset); + assertTrue(String.valueOf(target), target instanceof Navigatable); + ((Navigatable)target).navigate(true); + int expected = editor.getDocument().getLineStartOffset(expLine - 1) + expColumn - 1; + assertEquals(expected, editor.getCaretModel().getOffset()); + } } diff --git a/plugins/java-decompiler/testData/Navigation.class b/plugins/java-decompiler/testData/Navigation.class new file mode 100644 index 000000000000..0d906973a331 Binary files /dev/null and b/plugins/java-decompiler/testData/Navigation.class differ diff --git a/plugins/java-decompiler/testData/Navigation.java b/plugins/java-decompiler/testData/Navigation.java new file mode 100644 index 000000000000..b363ee37ad06 --- /dev/null +++ b/plugins/java-decompiler/testData/Navigation.java @@ -0,0 +1,10 @@ +class Navigation { + void m1() { + m2(42); + } + + void m2(int i) { + int r = 3 * i; + System.out.println(r); + } +} \ No newline at end of file diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java index 97016d4d88f1..8c76d63f1036 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java @@ -19,6 +19,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.ex.ProjectManagerEx; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Ref; @@ -98,7 +99,7 @@ public class SvnIntegrateChangesTask extends Task.Backgroundable { myHandler.setProgressIndicator(ProgressManager.getInstance().getProgressIndicator()); myResolveWorker = new ResolveWorker(myInfo.isUnderProjectRoot(), myProject); - BlockReloadingUtil.block(); + ProjectManagerEx.getInstanceEx().blockReloadingProjectOnExternalChanges(); myProjectLevelVcsManager.startBackgroundVcsOperation(); try { @@ -174,7 +175,7 @@ public class SvnIntegrateChangesTask extends Task.Backgroundable { afterExecution(wasCancelled); } } finally { - BlockReloadingUtil.unblock(); + ProjectManagerEx.getInstanceEx().unblockReloadingProjectOnExternalChanges(); } } diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java index 729e6062c626..52851edc1e33 100644 --- a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java +++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.editorActions; import com.intellij.application.options.editor.WebEditorOptions; +import com.intellij.ide.highlighter.XmlLikeFileType; import com.intellij.lang.ASTNode; import com.intellij.lang.xml.XMLLanguage; import com.intellij.openapi.editor.Editor; @@ -90,6 +91,8 @@ public class XmlSlashTypedHandler extends TypedHandlerDelegate { if ("