Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2014-10-02 12:01:59 +04:00
39 changed files with 448 additions and 273 deletions
+24 -3
View File
@@ -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)
@@ -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");
@@ -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());
@@ -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;
}
}
@@ -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();
@@ -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) {
@@ -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()));
@@ -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);
}
@@ -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 : ""));
@@ -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());
}
});
}
}
@@ -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) {
@@ -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();
}
}
}
@@ -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) {
}
}
@@ -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();
}
}
@@ -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();
}
}
@@ -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) {
@@ -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();
}
@@ -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
@@ -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>
@@ -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;
}
@@ -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)
}
@@ -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() {
}
@@ -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);
@@ -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);