mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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<String> 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)
|
||||
|
||||
+6
-5
@@ -38,7 +38,6 @@ class ContractChecker extends DataFlowRunner {
|
||||
private final Set<PsiElement> myViolations = ContainerUtil.newHashSet();
|
||||
private final Set<PsiElement> myNonViolations = ContainerUtil.newHashSet();
|
||||
private final Set<PsiElement> myFailures = ContainerUtil.newHashSet();
|
||||
private final Set<PsiElement> 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");
|
||||
|
||||
+6
-31
@@ -78,13 +78,15 @@ class ContractInferenceInterpreter {
|
||||
|
||||
List<MethodContract> 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<MethodContract>() {
|
||||
@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<MethodContract> 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<MethodContract>() {
|
||||
@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<MethodContract> result = handleDelegation(((PsiExpressionStatement)statements[0]).getExpression(), false);
|
||||
if (result != null) return ContainerUtil.findAll(result, new Condition<MethodContract>() {
|
||||
@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<MethodContract> 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<MethodContract> conditionResults = visitExpression(states, ((PsiAssertStatement)statement).getAssertCondition());
|
||||
|
||||
+23
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+84
-44
@@ -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<PsiElement> myElementStack = new Stack<PsiElement>();
|
||||
|
||||
/**
|
||||
* 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<PsiTryStatement, DfaVariableValue> 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<PsiTryStatement, DfaVariableValue>() {
|
||||
@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<CatchDescriptor>();
|
||||
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<PsiType> flattened = declaredType instanceof PsiDisjunctionType ?
|
||||
((PsiDisjunctionType)declaredType).getDisjunctions() :
|
||||
List<PsiType> 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);
|
||||
|
||||
|
||||
@@ -25,6 +25,14 @@ class Foo {
|
||||
failNatively();
|
||||
}
|
||||
}
|
||||
|
||||
@Contract("null->fail")
|
||||
public Object assertNotNull(Object o) {
|
||||
if (o == null) {
|
||||
failNatively();
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
native void failNatively();
|
||||
|
||||
|
||||
@@ -11,4 +11,13 @@ class Foo {
|
||||
@Contract(pure=<warning descr="Pure methods must return something, void is not allowed as a return type">true</warning>)
|
||||
void voidPureMethod() {}
|
||||
|
||||
@Contract(<warning descr="Method returns void but the contract specifies null">"->null"</warning>)
|
||||
public native void throwMe();
|
||||
|
||||
@Contract(<warning descr="Method returns boolean but the contract specifies null">"->null"</warning>)
|
||||
public native boolean wrongReturnType();
|
||||
|
||||
@Contract(<warning descr="Method returns String but the contract specifies true">"->true"</warning>)
|
||||
public native String wrongReturnType2();
|
||||
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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();
|
||||
|
||||
-5
@@ -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<String, Element> newLiveStates) {
|
||||
|
||||
+5
-5
@@ -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<Pair<StateStorageManager.SaveSession, VirtualFile>> readonlyFiles) {
|
||||
protected void beforeSave(@NotNull List<Pair<SaveSession, VirtualFile>> readonlyFiles) {
|
||||
super.beforeSave(readonlyFiles);
|
||||
|
||||
for (ComponentSaveSession moduleSaveSession : myModuleSaveSessions) {
|
||||
|
||||
@@ -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()));
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
+7
-4
@@ -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 : ""));
|
||||
|
||||
+28
-7
@@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -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<Pair<StateStorageManager.SaveSession, VirtualFile>> readonlyFiles) {
|
||||
protected static void executeSave(@NotNull SaveSession saveSession, @NotNull List<Pair<SaveSession, VirtualFile>> 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<Pair<StateStorageManager.SaveSession, VirtualFile>> readonlyFiles) {
|
||||
public ComponentSaveSession save(@NotNull List<Pair<SaveSession, VirtualFile>> readonlyFiles) {
|
||||
SettingsSavingComponent[] settingsComponents =
|
||||
mySettingsSavingComponents.toArray(new SettingsSavingComponent[mySettingsSavingComponents.size()]);
|
||||
for (SettingsSavingComponent settingsSavingComponent : settingsComponents) {
|
||||
|
||||
+9
-25
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -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<Pair<StateStorageManager.SaveSession, VirtualFile>> readonlyFiles) {
|
||||
public ComponentSaveSession save(@NotNull List<Pair<SaveSession, VirtualFile>> 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<StateStorageManager.SaveSession, VirtualFile> entry : readonlyFiles) {
|
||||
for (Pair<SaveSession, VirtualFile> entry : readonlyFiles) {
|
||||
executeSave(entry.first, readonlyFiles);
|
||||
}
|
||||
|
||||
@@ -510,7 +511,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private VirtualFile[] getFilesList(List<Pair<StateStorageManager.SaveSession, VirtualFile>> readonlyFiles) {
|
||||
private VirtualFile[] getFilesList(List<Pair<SaveSession, VirtualFile>> 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<Pair<StateStorageManager.SaveSession, VirtualFile>> readonlyFiles) {
|
||||
protected void beforeSave(@NotNull List<Pair<SaveSession, VirtualFile>> readonlyFiles) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-6
@@ -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();
|
||||
}
|
||||
}
|
||||
+7
-6
@@ -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<StateStorage, StateStorage.SaveSession> saveSessions = null;
|
||||
Map<StateStorage, SaveSession> 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<StateStorage, StateStorage.SaveSession>();
|
||||
saveSessions = new SmartHashMap<StateStorage, SaveSession>();
|
||||
}
|
||||
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<StateStorage, StateStorage.SaveSession> mySaveSessions;
|
||||
private final Map<StateStorage, SaveSession> mySaveSessions;
|
||||
|
||||
public StateStorageSaveSession(@NotNull Map<StateStorage, StateStorage.SaveSession> saveSessions) {
|
||||
public StateStorageSaveSession(@NotNull Map<StateStorage, SaveSession> saveSessions) {
|
||||
mySaveSessions = saveSessions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
for (StateStorage.SaveSession saveSession : mySaveSessions.values()) {
|
||||
for (SaveSession saveSession : mySaveSessions.values()) {
|
||||
saveSession.save();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -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<Pair<StateStorageManager.SaveSession, VirtualFile>> readonlyFiles = new SmartList<Pair<StateStorageManager.SaveSession, VirtualFile>>();
|
||||
List<Pair<SaveSession, VirtualFile>> readonlyFiles = new SmartList<Pair<SaveSession, VirtualFile>>();
|
||||
session.save(readonlyFiles);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
|
||||
+2
-2
@@ -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<Pair<StateStorageManager.SaveSession, VirtualFile>> readonlyFiles);
|
||||
ComponentSaveSession save(@NotNull List<Pair<StateStorage.SaveSession, VirtualFile>> readonlyFiles);
|
||||
|
||||
void finishSave();
|
||||
}
|
||||
+107
-91
@@ -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<Element>, ExportableApplicationComponent {
|
||||
private static final Logger LOG = Logger.getInstance(ProjectManagerImpl.class);
|
||||
|
||||
public static final int CURRENT_FORMAT_VERSION = 4;
|
||||
|
||||
private static final Key<List<ProjectManagerListener>> 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<Project> myTestProjects = new THashSet<Project>();
|
||||
|
||||
private final MultiMap<Project, ChangedFileEntry> myChangedProjectFiles = MultiMap.createSet();
|
||||
private final Alarm myChangedFilesAlarm = new Alarm();
|
||||
private final SingleAlarm myChangedFilesAlarm;
|
||||
private final List<Pair<VirtualFile, StateStorage>> myChangedApplicationFiles = new SmartList<Pair<VirtualFile, StateStorage>>();
|
||||
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<Project> 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<Pair<VirtualFile, StateStorage>> causes = new THashSet<Pair<VirtualFile, StateStorage>>(myChangedApplicationFiles);
|
||||
myChangedApplicationFiles.clear();
|
||||
|
||||
Collection<String> reloadResult;
|
||||
AccessToken token = WriteAction.start();
|
||||
try {
|
||||
final Application app = ApplicationManager.getApplication();
|
||||
if (app.isDisposed()) {
|
||||
return false;
|
||||
}
|
||||
final Set<Pair<VirtualFile, StateStorage>> causes = new THashSet<Pair<VirtualFile, StateStorage>>(myChangedApplicationFiles);
|
||||
if (causes.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Ref<Collection<String>> 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<VirtualFile, StateStorage> 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<VirtualFile, StateStorage> 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
|
||||
|
||||
+3
-1
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -647,7 +647,7 @@
|
||||
<separator/>
|
||||
<reference ref="MaintenanceGroup"/>
|
||||
|
||||
<action internal="true" id="SendStatistics" class="com.intellij.internal.statistic.tmp.SendStatisticsAction" text="Send statistics"/>
|
||||
<action internal="true" id="SendStatistics" class="com.intellij.internal.statistic.tmp.SendStatisticsAction" text="Send Statistics"/>
|
||||
<add-to-group group-id="ToolsMenu" anchor="last"/>
|
||||
</group>
|
||||
|
||||
|
||||
-4
@@ -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;
|
||||
}
|
||||
|
||||
+5
-1
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
+8
-6
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.openapi.vcs.update;
|
||||
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx;
|
||||
|
||||
@Deprecated
|
||||
public class BlockReloadingUtil {
|
||||
private BlockReloadingUtil() {
|
||||
}
|
||||
|
||||
+1
-6
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,10 @@
|
||||
class Navigation {
|
||||
void m1() {
|
||||
m2(42);
|
||||
}
|
||||
|
||||
void m2(int i) {
|
||||
int r = 3 * i;
|
||||
System.out.println(r);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ("</".equals(prevLeafText) && prevLeaf.getElementType() == XmlTokenType.XML_END_TAG_START) {
|
||||
XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
|
||||
if (tag != null && StringUtil.isNotEmpty(tag.getName()) && TreeUtil.findSibling(prevLeaf, XmlTokenType.XML_NAME) == null) {
|
||||
if (!(file.getFileType() instanceof XmlLikeFileType)) return Result.CONTINUE;
|
||||
|
||||
// check for template language like JSP
|
||||
if (provider instanceof MultiplePsiFilesPerDocumentFileViewProvider) {
|
||||
PsiElement element1 = SingleRootFileViewProvider.findElementAt(file, offset - 1);
|
||||
|
||||
+13
@@ -35,6 +35,19 @@ public class RelaxedHtmlFromSchemaElementDescriptor extends XmlElementDescriptor
|
||||
super(tag);
|
||||
}
|
||||
|
||||
public static XmlAttributeDescriptor[] getCommonAttributeDescriptors(XmlTag context) {
|
||||
final XmlNSDescriptor nsDescriptor = context != null ? context.getNSDescriptor("", false) : null;
|
||||
if (nsDescriptor != null) {
|
||||
for (XmlElementDescriptor descriptor : nsDescriptor.getRootElementsDescriptors(null)) {
|
||||
final String name = descriptor.getName();
|
||||
if ("div".equals(name) || "span".equals(name)) {
|
||||
return descriptor.getAttributesDescriptors(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return XmlAttributeDescriptor.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlElementDescriptor getElementDescriptor(XmlTag childTag, XmlTag contextTag) {
|
||||
XmlElementDescriptor elementDescriptor = super.getElementDescriptor(childTag, contextTag);
|
||||
|
||||
Reference in New Issue
Block a user