diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index 77f8afc227c2..dc9d1e9e1ec7 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -424,8 +424,13 @@ public abstract class DebugProcessImpl implements DebugProcess { for (final StepRequest request : stepRequests) { ThreadReference threadReference = request.thread(); // [jeka] on attempt to delete a request assigned to a thread with unknown status, a JDWP error occures - if (threadReference.status() != ThreadReference.THREAD_STATUS_UNKNOWN && (stepThread == null || stepThread.equals(threadReference))) { - toDelete.add(request); + try { + if (threadReference.status() != ThreadReference.THREAD_STATUS_UNKNOWN && (stepThread == null || stepThread.equals(threadReference))) { + toDelete.add(request); + } + } + catch (IllegalThreadStateException e) { + LOG.info(e); // undocumented by JDI: may be thrown when querying thread status } } requestManager.deleteEventRequests(toDelete); diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/LambdaMethodFilter.java b/java/debugger/impl/src/com/intellij/debugger/engine/LambdaMethodFilter.java index 7e4fd940c772..32669347eb81 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/LambdaMethodFilter.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/LambdaMethodFilter.java @@ -17,6 +17,7 @@ package com.intellij.debugger.engine; import com.intellij.debugger.SourcePosition; import com.intellij.debugger.engine.evaluation.EvaluateException; +import com.intellij.debugger.jdi.VirtualMachineProxyImpl; import com.intellij.psi.PsiCodeBlock; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiLambdaExpression; @@ -76,7 +77,8 @@ public class LambdaMethodFilter implements BreakpointStepMethodFilter{ } public boolean locationMatches(DebugProcessImpl process, Location location) throws EvaluateException { + final VirtualMachineProxyImpl vm = process.getVirtualMachineProxy(); final Method method = location.method(); - return method.name().startsWith(LAMBDA_METHOD_PREFIX) && method.isSynthetic(); + return method.name().startsWith(LAMBDA_METHOD_PREFIX) && (!vm.canGetSyntheticAttribute() || method.isSynthetic()); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java index 771444af0868..151fc6f9bb6e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java @@ -268,24 +268,19 @@ public class PositionManagerImpl implements PositionManager { private ReferenceType findNested(final ReferenceType fromClass, final int currentDepth, final PsiClass classToFind, final int requiredDepth, final SourcePosition position) { final VirtualMachineProxyImpl vmProxy = myDebugProcess.getVirtualMachineProxy(); if (fromClass.isPrepared()) { - - try { - //final int lineNumber = position.getLine() + 1; - if (currentDepth < requiredDepth) { final List nestedTypes = vmProxy.nestedTypes(fromClass); for (ReferenceType nested : nestedTypes) { final ReferenceType found = findNested(nested, currentDepth + 1, classToFind, requiredDepth, position); if (found != null) { - // check if enclosing class also has executable code at the same line, and if yes, prefer enclosing class - //return fromClass.locationsOfLine(lineNumber).isEmpty()? found : fromClass; return found; } } return null; } + final boolean canGetSynthetic = vmProxy.canGetSyntheticAttribute(); int rangeBegin = Integer.MAX_VALUE; int rangeEnd = Integer.MIN_VALUE; for (Location location : fromClass.allLineLocations()) { @@ -294,8 +289,9 @@ public class PositionManagerImpl implements PositionManager { continue; // should be a native method, skipping } final Method method = location.method(); - if (method == null || method.isSynthetic() || method.isBridge() || method.isObsolete()) { - continue; // do not take into account synthetic stuff + if (method == null || (canGetSynthetic && method.isSynthetic()) || method.isBridge()) { + // do not take into account synthetic stuff + continue; } final int locationLine = lnumber - 1; rangeBegin = Math.min(rangeBegin, locationLine); diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/events/SuspendContextCommandImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/events/SuspendContextCommandImpl.java index f3ad39594d3a..739c96270cca 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/events/SuspendContextCommandImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/events/SuspendContextCommandImpl.java @@ -67,16 +67,23 @@ public abstract class SuspendContextCommandImpl extends DebuggerCommandImpl { } finally{ suspendContext.myInProgress = false; - SuspendContextCommandImpl postponed = suspendContext.pollPostponedCommand(); - if (postponed != null) { - final Stack stack = new Stack(); - while (postponed != null) { - stack.push(postponed); - postponed = suspendContext.pollPostponedCommand(); + if (suspendContext.isResumed()) { + for (SuspendContextCommandImpl postponed = suspendContext.pollPostponedCommand(); postponed != null; postponed = suspendContext.pollPostponedCommand()) { + postponed.notifyCancelled(); } - final DebuggerManagerThreadImpl managerThread = suspendContext.getDebugProcess().getManagerThread(); - while (!stack.isEmpty()) { - managerThread.pushBack(stack.pop()); + } + else { + SuspendContextCommandImpl postponed = suspendContext.pollPostponedCommand(); + if (postponed != null) { + final Stack stack = new Stack(); + while (postponed != null) { + stack.push(postponed); + postponed = suspendContext.pollPostponedCommand(); + } + final DebuggerManagerThreadImpl managerThread = suspendContext.getDebugProcess().getManagerThread(); + while (!stack.isEmpty()) { + managerThread.pushBack(stack.pop()); + } } } } diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java index 2898e3f10dd9..796aab701765 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java @@ -26,11 +26,12 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.StringBuilderSpinAllocator; +import com.intellij.util.concurrency.Semaphore; import com.intellij.util.ui.MessageCategory; -import com.intellij.util.ui.UIUtil; import com.sun.jdi.ReferenceType; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.io.File; import java.io.IOException; import java.util.Collections; @@ -163,50 +164,41 @@ class ReloadClassesWorker { processException(e); } + final Semaphore waitSemaphore = new Semaphore(); + waitSemaphore.down(); //noinspection SSBasedInspection - UIUtil.invokeAndWaitIfNeeded(new Runnable() { + SwingUtilities.invokeLater(new Runnable() { public void run() { - if (project.isDisposed()) { - return; - } - final BreakpointManager breakpointManager = (DebuggerManagerEx.getInstanceEx(project)).getBreakpointManager(); - breakpointManager.reloadBreakpoints(); - debugProcess.getRequestsManager().clearWarnings(); - if (LOG.isDebugEnabled()) { - LOG.debug("requests updated"); - LOG.debug("time stamp set"); - } - myDebuggerSession.refresh(false); - - /* - debugProcess.getManagerThread().schedule(new DebuggerCommandImpl() { - protected void action() throws Exception { - try { - breakpointManager.enableBreakpoints(debugProcess); + try { + if (!project.isDisposed()) { + final BreakpointManager breakpointManager = (DebuggerManagerEx.getInstanceEx(project)).getBreakpointManager(); + breakpointManager.reloadBreakpoints(); + debugProcess.getRequestsManager().clearWarnings(); + if (LOG.isDebugEnabled()) { + LOG.debug("requests updated"); + LOG.debug("time stamp set"); } - catch (Exception e) { - processException(e); - } - //try { - // virtualMachineProxy.resume(); - //} - //catch (Exception e) { - // processException(e); - //} + myDebuggerSession.refresh(false); } - - public Priority getPriority() { - return Priority.HIGH; - } - }); - */ + } + catch (Throwable e) { + LOG.error(e); + } + finally { + waitSemaphore.up(); + } } }); - try { - breakpointManager.enableBreakpoints(debugProcess); - } - catch (Exception e) { - processException(e); + + waitSemaphore.waitFor(); + + if (!project.isDisposed()) { + try { + breakpointManager.enableBreakpoints(debugProcess); + } + catch (Exception e) { + processException(e); + } } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTree.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTree.java index 32ace1064daf..39c2775df018 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTree.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTree.java @@ -32,10 +32,7 @@ import com.intellij.debugger.engine.events.SuspendContextCommandImpl; import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.impl.DebuggerSession; import com.intellij.debugger.impl.DebuggerUtilsEx; -import com.intellij.debugger.jdi.LocalVariableProxyImpl; -import com.intellij.debugger.jdi.StackFrameProxyImpl; -import com.intellij.debugger.jdi.ThreadGroupReferenceProxyImpl; -import com.intellij.debugger.jdi.ThreadReferenceProxyImpl; +import com.intellij.debugger.jdi.*; import com.intellij.debugger.settings.NodeRendererSettings; import com.intellij.debugger.settings.ThreadsViewSettings; import com.intellij.debugger.ui.breakpoints.Breakpoint; @@ -462,8 +459,10 @@ public abstract class DebuggerTree extends DebuggerTreeBase implements DataProvi final ReferenceType thisRefType = thisObjectReference.referenceType(); if (thisRefType instanceof ClassType && thisRefType.equals(location.declaringType()) && thisRefType.name().contains("$")) { // makes sense for nested classes only final ClassType clsType = (ClassType)thisRefType; + final DebugProcessImpl debugProcess = getDebuggerContext().getDebugProcess(); + final VirtualMachineProxyImpl vm = debugProcess.getVirtualMachineProxy(); for (Field field : clsType.fields()) { - if (field.isSynthetic() && StringUtil.startsWith(field.name(), FieldDescriptorImpl.OUTER_LOCAL_VAR_FIELD_PREFIX)) { + if ((!vm.canGetSyntheticAttribute() || field.isSynthetic()) && StringUtil.startsWith(field.name(), FieldDescriptorImpl.OUTER_LOCAL_VAR_FIELD_PREFIX)) { final FieldDescriptorImpl fieldDescriptor = myNodeManager.getFieldDescriptor(stackDescriptor, thisObjectReference, field); myChildren.add(myNodeManager.createNode(fieldDescriptor, evaluationContext)); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index 3492a2b13b04..7a89381553f8 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -42,7 +42,7 @@ import static com.intellij.codeInsight.ConditionChecker.Type.*; import static com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint; import static com.intellij.psi.CommonClassNames.*; -class ControlFlowAnalyzer extends JavaElementVisitor { +public class ControlFlowAnalyzer extends JavaElementVisitor { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer"); public static final String ORG_JETBRAINS_ANNOTATIONS_CONTRACT = Contract.class.getName(); private boolean myIgnoreAssertions; diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java index eeb81ea22292..c6314f7d9bb1 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java @@ -111,13 +111,21 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool { if (method == null) return; String text = AnnotationUtil.getStringAttributeValue(annotation, null); - if (text == null) return; + if (StringUtil.isNotEmpty(text)) { + String error = checkContract(method, text); + if (error != null) { + PsiAnnotationMemberValue value = annotation.findAttributeValue(null); + assert value != null; + holder.registerProblem(value, error); + return; + } + } - String error = checkContract(method, text); - if (error != null) { - PsiAnnotationMemberValue value = annotation.findAttributeValue(null); + if (Boolean.TRUE.equals(AnnotationUtil.getBooleanAttributeValue(annotation, "pure")) && + PsiType.VOID.equals(method.getReturnType())) { + PsiAnnotationMemberValue value = annotation.findDeclaredAttributeValue("pure"); assert value != null; - holder.registerProblem(value, error); + holder.registerProblem(value, "Pure methods must return something, void is not allowed as a return type"); } } }; diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java index cc315b646281..1c0231b97b11 100644 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java +++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java @@ -5,10 +5,11 @@ import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Factory; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.indexing.*; import com.intellij.util.io.DataExternalizer; +import com.intellij.util.io.IOUtil; import com.intellij.util.io.KeyDescriptor; import com.intellij.util.io.PersistentHashMap; import org.jetbrains.asm4.tree.ClassNode; @@ -51,24 +52,32 @@ public abstract class CompilerOutputBaseIndex { if (!IndexInfrastructure.getIndexRootDir(indexId).exists()) { rewriteIndex.set(true); } - final File storageFile = IndexInfrastructure.getStorageFile(indexId); + final File storageFile = getStorageFile(indexId); final MapIndexStorage indexStorage = new MapIndexStorage(storageFile, myKeyDescriptor, myValueExternalizer, 1024); index = new MapReduceIndex(indexId, getIndexer(), indexStorage); index.setInputIdToDataKeysIndex(new Factory>>() { @Override public PersistentHashMap> create() { - Exception failCause = null; - for (int attempts = 0; attempts < 2; attempts++) { - try { - return FileBasedIndexImpl.createIdToDataKeysIndex(indexId, myKeyDescriptor, new MemoryIndexStorage(indexStorage)); - } - catch (IOException e) { - failCause = e; - FileUtil.delete(IndexInfrastructure.getInputIndexStorageFile(getIndexId())); - rewriteIndex.set(true); - } + try { + return IOUtil.openCleanOrResetBroken( + new ThrowableComputable>, IOException>() { + @Override + public PersistentHashMap> compute() throws IOException { + return FileBasedIndexImpl.createIdToDataKeysIndex(indexId, myKeyDescriptor, new MemoryIndexStorage(indexStorage)); + } + }, + new Runnable() { + @Override + public void run() { + FileUtil.delete(getInputIndexStorageFile(getIndexId())); + rewriteIndex.set(true); + } + } + ); + } + catch (IOException e) { + throw new RuntimeException("couldn't create index", e); } - throw new RuntimeException("couldn't create index", failCause); } }); final File versionFile = getVersionFile(indexId); @@ -144,9 +153,4 @@ public abstract class CompilerOutputBaseIndex { protected final ID generateIndexId(final String indexName) { return CompilerOutputIndexUtil.generateIndexId(indexName, myProject); } - - protected final ID generateIndexId(final Class aClass) { - final String className = StringUtil.getShortName(aClass); - return generateIndexId(StringUtil.trimEnd(className, "Index")); - } } diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java index 3c23306b8b53..fed4c02502b0 100644 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java +++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java @@ -12,6 +12,7 @@ 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.util.ThrowableComputable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.registry.RegistryValue; import com.intellij.openapi.util.registry.RegistryValueListener; @@ -153,16 +154,19 @@ public class CompilerOutputIndexer extends AbstractProjectComponent { private void doEnable() { if (myInitialized.compareAndSet(false, true)) { initTimestampIndex(); - File storageFile = + final File storageFile = IndexInfrastructure.getStorageFile(CompilerOutputIndexUtil.generateIndexId("compilerOutputIndexFileId.enum", myProject)); - for (int i = 0; i < 2; i++) { - try { - myFileEnumerator = new PersistentEnumeratorDelegate(storageFile, new EnumeratorStringDescriptor(), 2048); - } - catch (IOException e) { - if (i == 1) throw new RuntimeException(e); - IOUtil.deleteAllFilesStartingWith(storageFile); - } + + try { + myFileEnumerator = IOUtil.openCleanOrResetBroken(new ThrowableComputable, IOException>() { + @Override + public PersistentEnumeratorDelegate compute() throws IOException { + return new PersistentEnumeratorDelegate(storageFile, new EnumeratorStringDescriptor(), 2048); + } + }, storageFile); + } + catch (IOException e) { + throw new RuntimeException(e); } CompilerManager.getInstance(myProject).addCompilationStatusListener(new CompilationStatusAdapter() { @Override @@ -184,29 +188,35 @@ public class CompilerOutputIndexer extends AbstractProjectComponent { } private void initTimestampIndex() { - for (int attempts = 0; attempts < 2; attempts++) { - try { - myFileTimestampsIndex = new PersistentHashMap(IndexInfrastructure.getStorageFile(getFileTimestampsIndexId()), - new EnumeratorStringDescriptor(), new DataExternalizer() { + final File storageFile = IndexInfrastructure.getStorageFile(getFileTimestampsIndexId()); + try { + myFileTimestampsIndex = IOUtil.openCleanOrResetBroken( + new ThrowableComputable, IOException>() { @Override - public void save(final DataOutput out, final Long value) throws IOException { - out.writeLong(value); - } + public PersistentHashMap compute() throws IOException { + return new PersistentHashMap(storageFile, + new EnumeratorStringDescriptor(), new DataExternalizer() { + @Override + public void save(final DataOutput out, final Long value) throws IOException { + out.writeLong(value); + } - @Override - public Long read(final DataInput in) throws IOException { - return in.readLong(); + @Override + public Long read(final DataInput in) throws IOException { + return in.readLong(); + } + }); } - }); - } - catch (IOException e) { - FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId())); - } - if (myFileTimestampsIndex != null) { - return; - } + }, + new Runnable() { + public void run() { + FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId())); + } + } + ); + } catch (IOException ex) { + throw new RuntimeException("Timestamps index not initialized", ex); } - throw new RuntimeException("Timestamps index not initialized"); } public void reindex(final FileVisitorService visitorService, final @NotNull ProgressIndicator indicator) { diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ContractAnnotation.java b/java/java-tests/testData/inspection/dataFlow/fixture/ContractAnnotation.java index a5c27dd21749..3d97047e240e 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/ContractAnnotation.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ContractAnnotation.java @@ -46,4 +46,7 @@ public class AssertIsNotNull { @Contract("null -> _") void wrongParameterCount(Object a, boolean b) {} + + @Contract(pure=true) + void voidPureMethod() {} } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy index 052442f9a61e..04a73243dd91 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -116,7 +116,7 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase { } """) type "r" - assertContains "iterable", "iter" + myFixture.assertPreferredCompletionItems 1, "iter", "iterable" type '\b' assertContains "iterable" @@ -131,7 +131,7 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase { assertContains "iterable" type "r" - assertContains "iterable", "iter" + myFixture.assertPreferredCompletionItems 1, "iter", "iterable" } public void testExplicitSelectionShouldSurvive() { @@ -151,7 +151,7 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase { assertEquals 'iterable2', lookup.currentItem.lookupString type "r" - myFixture.assertPreferredCompletionItems 2, "iterable", "iter", 'iterable2' + myFixture.assertPreferredCompletionItems 2, "iter", "iterable", 'iterable2' } @@ -172,7 +172,7 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase { assertEquals 'iterable2', lookup.currentItem.lookupString type "r" - myFixture.assertPreferredCompletionItems 2, "iterable", "iter", 'iterable2' + myFixture.assertPreferredCompletionItems 2, "iter", "iterable", 'iterable2' } @@ -1305,7 +1305,7 @@ class Foo { type 'e' myFixture.assertPreferredCompletionItems 0, 'itera', 'itex' type 'r' - myFixture.assertPreferredCompletionItems 0, 'itera', 'iter' + myFixture.assertPreferredCompletionItems 1, 'iter', 'itera' type '\b' myFixture.assertPreferredCompletionItems 0, 'itera', 'itex' } @@ -1544,9 +1544,9 @@ class Foo { } ''' type 'tpl' - myFixture.assertPreferredCompletionItems 0, 'tplMn', 'tpl' + myFixture.assertPreferredCompletionItems 1, 'tpl', 'tplMn' - LookupElementPresentation p = LookupElementPresentation.renderElement(myFixture.lookupElements[1]) + LookupElementPresentation p = LookupElementPresentation.renderElement(myFixture.lookupElements[0]) assert p.itemText == 'tpl' assert !p.tailText def tabKeyPresentation = KeyEvent.getKeyText(TemplateSettings.TAB_CHAR as int) diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index f8707d97f9e3..02dcfc0072b3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -39,12 +39,6 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { return JAVA_1_7; } - @Override - protected void setUp() throws Exception { - super.setUp(); - myFixture.addClass("package org.jetbrains.annotations; public @interface Contract { String value(); }"); - } - @Override protected String getTestDataPath() { return JavaTestUtil.getJavaTestDataPath() + "/inspection/dataFlow/fixture/"; diff --git a/java/mockJDK-1.7/jre/lib/annotations.jar b/java/mockJDK-1.7/jre/lib/annotations.jar index c1e4afba8bee..72aa54c908ed 100644 Binary files a/java/mockJDK-1.7/jre/lib/annotations.jar and b/java/mockJDK-1.7/jre/lib/annotations.jar differ diff --git a/platform/annotations/src/org/jetbrains/annotations/Contract.java b/platform/annotations/src/org/jetbrains/annotations/Contract.java index 6fa2e4b779e9..360bf5923d91 100644 --- a/platform/annotations/src/org/jetbrains/annotations/Contract.java +++ b/platform/annotations/src/org/jetbrains/annotations/Contract.java @@ -43,11 +43,19 @@ import java.lang.annotation.*; * @Contract("_, null -> null; _, !null -> !null") - method returns null if its second argument is null and not-null otherwise
* @Contract("true -> fail") - a typical assertFalse method which throws an exception if true is passed to it
* - * @author peter */ @Documented @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) public @interface Contract { - String value(); + /** + * Contains the contract clauses describing causal relations between call arguments and the returned value + */ + String value() default ""; + + /** + * Specifies if this method is pure, i.e. has no visible side effects. This may be used for more precise data flow analysis, and + * to check that the method's return value is actually used in the call place. + */ + boolean pure() default false; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java index 76416e74ef56..b460abe8b399 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java @@ -223,15 +223,7 @@ public class CompletionLookupArranger extends LookupArranger { ensureItemAdded(items, model, byRelevance, relevantSelection); ensureEverythingVisibleAdded(lookup, model, byRelevance); - ArrayList result = new ArrayList(model); - if (result.size() > 1) { - LookupElement first = result.get(0); - if (isLiveTemplate(first) && isPrefixItem(lookup, first, true) && CompletionServiceImpl.isStartMatch(result.get(1), lookup)) { - ContainerUtil.swapElements(result, 0, 1); - } - } - - return result; + return new ArrayList(model); } private static void ensureEverythingVisibleAdded(LookupImpl lookup, final LinkedHashSet model, Iterator byRelevance) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java index 413835ffd48f..a6b0eba7730a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java @@ -133,7 +133,7 @@ public class LiveTemplateCompletionContributor extends CompletionContributor { @Override public boolean skipElement(LookupElement element, CompletionLocation location) { - return element instanceof LiveTemplateLookupElement && ((LiveTemplateLookupElement)element).sudden; + return element instanceof LiveTemplateLookupElement && ((LiveTemplateLookupElement)element).sudden && !Registry.is("ide.completion.autopopup.select.live.templates"); } } diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java index fb8a7d8253f4..b35309e40b58 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java @@ -522,7 +522,7 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo try { if (editorHighlighter instanceof LayeredLexerEditorHighlighter) { - lexer = LexerEditorHighlighterLexer.getLexerBasedOnLexerHighlighter(text, file, myProject); + lexer = new LexerEditorHighlighterLexer(editorHighlighter, false); } else { lexer = highlighter.getHighlightingLexer(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java index b17dc292ca51..b515362b5024 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java @@ -213,7 +213,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark } private int fitLineToEditor(int visualLine) { - return Math.min(myEditor.getVisibleLineCount() - 1, Math.max(0, visualLine)); + return Math.max(0, Math.min(myEditor.getVisibleLineCount() - 1, visualLine)); } private int getOffset(int visualLine, boolean startLine) { diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index c2a3376be978..d4075008459a 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -213,6 +213,7 @@ ide.mac.fix.accessibleLeak=true projectView.showHierarchyErrors=true projectView.hide.dot.idea=true show.live.templates.in.completion=false +ide.completion.autopopup.select.live.templates=false documentation.component.editor.font=false ide.completion.show.better.matching.classes=true diff --git a/platform/projectModel-api/src/com/intellij/openapi/module/ModuleUtilCore.java b/platform/projectModel-api/src/com/intellij/openapi/module/ModuleUtilCore.java index d3db67dfaeef..d466794efd00 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/module/ModuleUtilCore.java +++ b/platform/projectModel-api/src/com/intellij/openapi/module/ModuleUtilCore.java @@ -79,13 +79,11 @@ public class ModuleUtilCore { @Nullable public static Module findModuleForPsiElement(@NotNull PsiElement element) { + if (!element.isValid()) { + return null; + } PsiFile containingFile = element.getContainingFile(); - if (containingFile == null) { - if (!element.isValid()) return null; - } - else { - if (!containingFile.isValid()) return null; - } + if (containingFile != null && !containingFile.isValid()) return null; Project project = (containingFile == null ? element : containingFile).getProject(); if (project.isDefault()) return null; diff --git a/platform/util/src/com/intellij/util/io/IOUtil.java b/platform/util/src/com/intellij/util/io/IOUtil.java index 89496e5dac7f..c10f04a78dba 100644 --- a/platform/util/src/com/intellij/util/io/IOUtil.java +++ b/platform/util/src/com/intellij/util/io/IOUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.util.io; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.SystemProperties; @@ -184,4 +185,26 @@ public class IOUtil { throw new RuntimeException(e); } } + + public static T openCleanOrResetBroken(@NotNull ThrowableComputable factoryComputable, final File file) throws IOException { + return openCleanOrResetBroken(factoryComputable, new Runnable() { + @Override + public void run() { + deleteAllFilesStartingWith(file); + } + }); + } + + public static T openCleanOrResetBroken(@NotNull ThrowableComputable factoryComputable, Runnable cleanupCallback) throws IOException { + for(int i = 0; i < 2; ++i) { + try { + return factoryComputable.compute(); + } catch (IOException ex) { + if (i == 1) throw ex; + cleanupCallback.run(); + } + } + + return null; + } } diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java index ab79e3305b06..a90fad17baae 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java @@ -32,6 +32,13 @@ public interface VcsLog { @NotNull List getSelectedCommits(); + /** + * Returns details of the selected commits if all of them have been loaded. + * To avoid data inconsistency, if at least one of the selected commits have no details loaded, empty list is returned. + */ + @NotNull + List getSelectedDetails(); + /** * Returns details of the given commit, if they have been already loaded. * In most cases they are already in the cache, and will be returned. diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java new file mode 100644 index 000000000000..3f0efa30084f --- /dev/null +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2013 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. + */ +package com.intellij.vcs.log; + +import com.intellij.openapi.actionSystem.DataKey; + +/** + * Provides {@link DataKey DataKeys} which can be used by actions to access data available in the VCS log. + */ +public class VcsLogDataKeys { + + public static DataKey VSC_LOG = DataKey.create("Vcs.Log"); + +} diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogSettings.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogSettings.java index 4d73ca6b2fa4..a370379b4d77 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogSettings.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogSettings.java @@ -18,4 +18,11 @@ public interface VcsLogSettings { */ int getRecentCommitsCount(); + /** + * Checks if the branches panel should be displayed or hidden. + */ + boolean isShowBranchesPanel(); + + void setShowBranchesPanel(boolean show); + } diff --git a/platform/vcs-log/impl/src/META-INF/vcs-log.xml b/platform/vcs-log/impl/src/META-INF/vcs-log.xml index d5596f2daf88..377cc00e3f89 100644 --- a/platform/vcs-log/impl/src/META-INF/vcs-log.xml +++ b/platform/vcs-log/impl/src/META-INF/vcs-log.xml @@ -12,18 +12,22 @@ - - + + + + + diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilter.java index 49101372c4fb..aed9fe018920 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilter.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilter.java @@ -8,26 +8,22 @@ import org.jetbrains.annotations.NotNull; import java.util.Collection; -/** - * TODO use VcsRef instead of String - */ public class VcsLogBranchFilter implements VcsLogGraphFilter { @NotNull private final Collection myMatchingHeads; - private final String myBranchName; + @NotNull private final String myBranchName; - public VcsLogBranchFilter(Collection allRefs, final String branchName) { - myBranchName = branchName; + public VcsLogBranchFilter(@NotNull Collection allRefs, @NotNull final String selectedBranchName) { + myBranchName = selectedBranchName; myMatchingHeads = ContainerUtil.mapNotNull(allRefs, new Function() { @Override public Hash fun(VcsRef ref) { - if (ref.getName().equals(branchName)) { + if (ref.getName().equals(selectedBranchName)) { return ref.getCommitHash(); } return null; } }); - } @Override @@ -44,4 +40,5 @@ public class VcsLogBranchFilter implements VcsLogGraphFilter { public String getBranchName() { return myBranchName; } + } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java index 07da58e71db4..3489b5e5a2a7 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java @@ -20,6 +20,8 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsLog; +import com.intellij.vcs.log.data.VcsLogDataHolder; +import com.intellij.vcs.log.ui.VcsLogUI; import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,25 +34,19 @@ import java.util.List; */ public class VcsLogImpl implements VcsLog { - private final VcsLogManager myLogManager; + @NotNull private final VcsLogDataHolder myDataHolder; + @NotNull private final VcsLogUI myUi; - public VcsLogImpl(VcsLogManager vcsLogManager) { - myLogManager = vcsLogManager; - } - - /** - * Checks if the log is initialized. - * TODO Temporary method until the old Git log is switched off and removed - */ - public boolean isReady() { - return myLogManager.getDataHolder() != null && myLogManager.getLogUi() != null; + public VcsLogImpl(@NotNull VcsLogDataHolder holder, @NotNull VcsLogUI ui) { + myDataHolder = holder; + myUi = ui; } @Override @NotNull public List getSelectedCommits() { List hashes = ContainerUtil.newArrayList(); - JBTable table = myLogManager.getLogUi().getTable(); + JBTable table = myUi.getTable(); for (int row : table.getSelectedRows()) { Hash hash = ((AbstractVcsLogTableModel)table.getModel()).getHashAtRow(row); if (hash != null) { @@ -60,10 +56,26 @@ public class VcsLogImpl implements VcsLog { return hashes; } + @NotNull + @Override + public List getSelectedDetails() { + List details = ContainerUtil.newArrayList(); + JBTable table = myUi.getTable(); + for (int row : table.getSelectedRows()) { + AbstractVcsLogTableModel model = (AbstractVcsLogTableModel)table.getModel(); + VcsFullCommitDetails commitDetails = model.getFullCommitDetails(row); + if (commitDetails == null) { + return ContainerUtil.emptyList(); + } + details.add(commitDetails); + } + return details; + } + @Override @Nullable public VcsFullCommitDetails getDetailsIfAvailable(@NotNull final Hash hash) { - return myLogManager.getDataHolder().getCommitDetailsGetter().getCommitDataIfAvailable(hash); + return myDataHolder.getCommitDetailsGetter().getCommitDataIfAvailable(hash); } @Nullable diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogSettingsImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogSettingsImpl.java index 42ac17687493..88b2b449ac69 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogSettingsImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogSettingsImpl.java @@ -17,6 +17,7 @@ public class VcsLogSettingsImpl implements VcsLogSettings, PersistentStateCompon public static class State { public int RECENT_COMMITS_COUNT = 1000; + public boolean SHOW_BRANCHES_PANEL = false; } @Nullable @@ -35,6 +36,16 @@ public class VcsLogSettingsImpl implements VcsLogSettings, PersistentStateCompon return myState.RECENT_COMMITS_COUNT; } + @Override + public boolean isShowBranchesPanel() { + return myState.SHOW_BRANCHES_PANEL; + } + + @Override + public void setShowBranchesPanel(boolean show) { + myState.SHOW_BRANCHES_PANEL = show; + } + public void setRecentCommitsBlockSize(int commitCount) { myState.RECENT_COMMITS_COUNT = commitCount; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogCreatePatchAction.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogCreatePatchAction.java new file mode 100644 index 000000000000..08a713e99491 --- /dev/null +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogCreatePatchAction.java @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2013 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. + */ +package com.intellij.vcs.log.ui; + +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.vcs.VcsDataKeys; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.actions.CreatePatchFromChangesAction; + +public class VcsLogCreatePatchAction extends CreatePatchFromChangesAction { + + @Override + public void update(AnActionEvent e) { + Change[] changes; + e.getPresentation().setEnabled((changes = e.getData(VcsDataKeys.CHANGES)) != null && changes.length > 0); + } + +} diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogQuickSettingsActions.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogQuickSettingsActions.java new file mode 100644 index 000000000000..36ce6fdac616 --- /dev/null +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogQuickSettingsActions.java @@ -0,0 +1,87 @@ +/* + * Copyright 2000-2013 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. + */ +package com.intellij.vcs.log.ui; + +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.impl.content.ToolWindowContentUi; +import com.intellij.vcs.log.VcsLogSettings; +import com.intellij.vcs.log.impl.VcsLogManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; + +public class VcsLogQuickSettingsActions extends DumbAwareAction { + + @Override + public void actionPerformed(AnActionEvent e) { + Project project = e.getProject(); + if (project == null) { + return; + } + VcsLogSettings settings = ServiceManager.getService(project, VcsLogSettings.class); + VcsLogManager logManager = ServiceManager.getService(project, VcsLogManager.class); + if (settings == null || logManager == null) { + return; + } + VcsLogUI logUi = logManager.getLogUi(); + + ActionGroup settingsGroup = new MySettingsActionGroup(settings, logUi); + ActionPopupMenu popupMenu = ActionManager.getInstance().createActionPopupMenu(ToolWindowContentUi.POPUP_PLACE, settingsGroup); + int x = 0; + int y = 0; + InputEvent inputEvent = e.getInputEvent(); + if (inputEvent instanceof MouseEvent) { + x = ((MouseEvent)inputEvent).getX(); + y = ((MouseEvent)inputEvent).getY(); + } + popupMenu.getComponent().show(inputEvent.getComponent(), x, y); + } + + private static class MySettingsActionGroup extends ActionGroup { + + private final VcsLogSettings mySettings; + private final VcsLogUI myUi; + + public MySettingsActionGroup(VcsLogSettings settings, VcsLogUI ui) { + mySettings = settings; + myUi = ui; + } + + @NotNull + @Override + public AnAction[] getChildren(@Nullable AnActionEvent e) { + return new AnAction[] { + new ToggleAction("Show Branches Panel") { + @Override + public boolean isSelected(AnActionEvent e) { + return mySettings.isShowBranchesPanel(); + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + mySettings.setShowBranchesPanel(state); + myUi.setBranchesPanelVisible(state); + } + } + }; + } + } +} diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java index 14e01a5da6fd..81ddba796957 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java @@ -5,6 +5,7 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.Hash; +import com.intellij.vcs.log.VcsLog; import com.intellij.vcs.log.VcsLogFilter; import com.intellij.vcs.log.VcsLogSettings; import com.intellij.vcs.log.compressedlist.UpdateRequest; @@ -16,6 +17,7 @@ import com.intellij.vcs.log.graph.elements.GraphElement; import com.intellij.vcs.log.graph.elements.Node; import com.intellij.vcs.log.graphmodel.FragmentManager; import com.intellij.vcs.log.graphmodel.GraphFragment; +import com.intellij.vcs.log.impl.VcsLogImpl; import com.intellij.vcs.log.printmodel.SelectController; import com.intellij.vcs.log.ui.frame.MainFrame; import com.intellij.vcs.log.ui.frame.VcsLogGraphTable; @@ -42,6 +44,7 @@ public class VcsLogUI { @NotNull private final VcsLogColorManager myColorManager; @NotNull private final VcsLogUiProperties myUiProperties; @NotNull private final VcsLogFilterer myFilterer; + @NotNull private final VcsLog myLog; @Nullable private GraphElement prevGraphElement; @@ -52,7 +55,8 @@ public class VcsLogUI { myColorManager = manager; myUiProperties = uiProperties; myFilterer = new VcsLogFilterer(logDataHolder, this); - myMainFrame = new MainFrame(myLogDataHolder, this, project, uiProperties); + myLog = new VcsLogImpl(myLogDataHolder, this); + myMainFrame = new MainFrame(myLogDataHolder, this, project, settings, uiProperties, myLog); project.getMessageBus().connect(project).subscribe(VcsLogDataHolder.REFRESH_COMPLETED, new Runnable() { @Override public void run() { @@ -247,4 +251,8 @@ public class VcsLogUI { ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, task, false, null, this.getMainFrame().getMainComponent()); } + public void setBranchesPanelVisible(boolean visible) { + myMainFrame.setBranchesPanelVisible(visible); + } + } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/ActiveSurface.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/ActiveSurface.java index d31357198d63..ff68984b8c64 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/ActiveSurface.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/ActiveSurface.java @@ -8,10 +8,12 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.committed.RepositoryChangesBrowser; import com.intellij.openapi.vcs.changes.ui.ChangesBrowser; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.components.JBLoadingPanel; import com.intellij.util.ArrayUtil; +import com.intellij.vcs.log.VcsLogSettings; import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.ui.VcsLogUI; import org.jetbrains.annotations.NotNull; @@ -38,14 +40,19 @@ public class ActiveSurface extends JPanel implements TypeSafeDataProvider { @NotNull private final Splitter myDetailsSplitter; @NotNull private final JBLoadingPanel myChangesLoadingPane; - ActiveSurface(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUI vcsLogUI, @NotNull Project project) { + ActiveSurface(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUI vcsLogUI, + @NotNull VcsLogSettings settings, @NotNull Project project) { myLogDataHolder = logDataHolder; myGraphTable = new VcsLogGraphTable(vcsLogUI, logDataHolder); myBranchesPanel = new BranchesPanel(logDataHolder, vcsLogUI); + + if (!settings.isShowBranchesPanel()) { + myBranchesPanel.setVisible(false); + } + myDetailsPanel = new DetailsPanel(logDataHolder, myGraphTable, vcsLogUI.getColorManager()); - final ChangesBrowser changesBrowser = new ChangesBrowser(project, null, Collections.emptyList(), null, false, false, null, - ChangesBrowser.MyUseCase.COMMITTED_CHANGES, null); + final ChangesBrowser changesBrowser = new RepositoryChangesBrowser(project, null, Collections.emptyList(), null); changesBrowser.getDiffAction().registerCustomShortcutSet(CommonShortcuts.getDiff(), myGraphTable); setDefaultEmptyText(changesBrowser); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java index e092be5fc456..cc26a84aef29 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java @@ -8,6 +8,7 @@ import com.intellij.ui.components.JBLoadingPanel; import com.intellij.ui.components.JBTextField; import com.intellij.ui.components.labels.LinkLabel; import com.intellij.ui.components.labels.LinkListener; +import com.intellij.util.text.DateFormatUtil; import com.intellij.util.ui.GridBag; import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.Hash; @@ -159,10 +160,12 @@ class DetailsPanel extends JPanel implements ListSelectionListener { else { myHashLabel.setText(commit.getHash().toShortString()); myCommitMessage.setText(commit.getFullMessage()); + myCommitMessage.setCaretPosition(0); - String authorText = commit.getAuthorName(); + String authorText = commit.getAuthorName() + " at " + DateFormatUtil.formatDateTime(commit.getAuthorTime()); if (!commit.getAuthorName().equals(commit.getCommitterName()) || !commit.getAuthorEmail().equals(commit.getCommitterEmail())) { - authorText += " (committed by " + commit.getCommitterName() + ")"; + authorText += " (committed by " + commit.getCommitterName() + + " at " + DateFormatUtil.formatDateTime(commit.getCommitTime()) + ")"; } myAuthor.setText(authorText); } @@ -190,6 +193,7 @@ class DetailsPanel extends JPanel implements ListSelectionListener { void setRefs(@NotNull List refs) { myRefs = refs; + setVisible(!myRefs.isEmpty()); repaint(); } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index f44746b10f9d..b01cdf3f7e79 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -8,6 +8,9 @@ import com.intellij.openapi.project.Project; import com.intellij.ui.JBColor; import com.intellij.ui.SeparatorComponent; import com.intellij.ui.SeparatorOrientation; +import com.intellij.vcs.log.VcsLog; +import com.intellij.vcs.log.VcsLogDataKeys; +import com.intellij.vcs.log.VcsLogSettings; import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.data.VcsLogUiProperties; import com.intellij.vcs.log.ui.VcsLogUI; @@ -22,24 +25,25 @@ import java.awt.*; /** * @author erokhins */ -public class MainFrame { +public class MainFrame extends JPanel implements TypeSafeDataProvider { @NotNull private final VcsLogDataHolder myLogDataHolder; @NotNull private final VcsLogUI myUI; @NotNull private final Project myProject; - @NotNull private final JPanel myMainPanel; @NotNull private final ActiveSurface myActiveSurface; @NotNull private final VcsLogUiProperties myUiProperties; + @NotNull private final VcsLog myLog; @NotNull private final VcsLogFilterUi myFilterUi; public MainFrame(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUI vcsLogUI, @NotNull Project project, - @NotNull VcsLogUiProperties uiProperties) { + @NotNull VcsLogSettings settings, @NotNull VcsLogUiProperties uiProperties, @NotNull VcsLog log) { myLogDataHolder = logDataHolder; myUI = vcsLogUI; myProject = project; myUiProperties = uiProperties; + myLog = log; - myActiveSurface = new ActiveSurface(logDataHolder, vcsLogUI, project); + myActiveSurface = new ActiveSurface(logDataHolder, vcsLogUI, settings, project); myActiveSurface.setupDetailsSplitter(myUiProperties.isShowDetails()); JComponent toolbar = Box.createHorizontalBox(); @@ -48,10 +52,9 @@ public class MainFrame { toolbar.add(new SeparatorComponent(JBColor.LIGHT_GRAY, SeparatorOrientation.VERTICAL)); toolbar.add(createActionsToolbar()); - myMainPanel = new JPanel(); - myMainPanel.setLayout(new BorderLayout()); - myMainPanel.add(toolbar, BorderLayout.NORTH); - myMainPanel.add(myActiveSurface, BorderLayout.CENTER); + setLayout(new BorderLayout()); + add(toolbar, BorderLayout.NORTH); + add(myActiveSurface, BorderLayout.CENTER); } public VcsLogGraphTable getGraphTable() { @@ -119,7 +122,7 @@ public class MainFrame { } }; - refreshAction.registerShortcutOn(myMainPanel); + refreshAction.registerShortcutOn(this); DefaultActionGroup toolbarGroup = new DefaultActionGroup(hideBranchesAction, showBranchesAction, showFullPatchAction, refreshAction, showDetailsAction); @@ -128,11 +131,21 @@ public class MainFrame { } public JComponent getMainComponent() { - return myMainPanel; + return this; } public void refresh() { myActiveSurface.getBranchesPanel().rebuild(); } + public void setBranchesPanelVisible(boolean visible) { + myActiveSurface.getBranchesPanel().setVisible(visible); + } + + @Override + public void calcData(DataKey key, DataSink sink) { + if (VcsLogDataKeys.VSC_LOG == key) { + sink.put(key, myLog); + } + } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java index bee2ed6e0ef7..b2b803b9895b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java @@ -5,6 +5,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile; import com.intellij.util.text.DateFormatUtil; import com.intellij.vcs.log.Hash; +import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsShortCommitDetails; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,6 +36,9 @@ public abstract class AbstractVcsLogTableModel extends AbstractTableModel { @Nullable protected abstract VcsShortCommitDetails getShortDetails(int rowIndex); + @Nullable + public abstract VcsFullCommitDetails getFullCommitDetails(int row); + @NotNull @Override public final Object getValueAt(int rowIndex, int columnIndex) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java index 8cd09242275d..9ddd0c5d3879 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java @@ -54,6 +54,13 @@ public class GraphTableModel extends AbstractVcsLogTableModel { return commitNode == null ? null : myDataHolder.getMiniDetailsGetter().getCommitData(commitNode); } + @Nullable + @Override + public VcsFullCommitDetails getFullCommitDetails(int row) { + Node node = myDataPack.getGraphModel().getGraph().getCommitNodeInRow(row); + return node == null ? null : myDataHolder.getCommitDetailsGetter().getCommitData(node); + } + @Override public void requestToLoadMore() { myDataHolder.showFullLog(EmptyRunnable.INSTANCE); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/NoGraphTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/NoGraphTableModel.java index f39d548edd3d..842ad73ce3ef 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/NoGraphTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/NoGraphTableModel.java @@ -41,6 +41,12 @@ public class NoGraphTableModel extends AbstractVcsLogTableModel { @Nullable @Override protected VcsShortCommitDetails getShortDetails(int rowIndex) { + return getFullCommitDetails(rowIndex); + } + + @Nullable + @Override + public VcsFullCommitDetails getFullCommitDetails(int rowIndex) { VcsFullCommitDetails commits = myCommits.get(rowIndex); if (commits == null) { LOG.error("Couldn't identify details for commit at " + rowIndex, new Attachment("loaded_commits", myCommits.toString())); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionBase.java index da52a98e6d70..0da3ca3c2aa5 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionBase.java @@ -15,6 +15,8 @@ */ package com.siyeh.ig.bugs; +import com.intellij.codeInsight.AnnotationUtil; +import com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; import com.intellij.psi.*; @@ -146,6 +148,13 @@ public class IgnoreResultOfCallInspectionBase extends BaseInspection { registerMethodCallError(call, aClass); return; } + + PsiAnnotation contractAnnotation = ControlFlowAnalyzer.findContractAnnotation(method); + if (contractAnnotation != null && Boolean.TRUE.equals(AnnotationUtil.getBooleanAttributeValue(contractAnnotation, "pure"))) { + registerMethodCallError(call, aClass); + return; + } + final PsiReferenceExpression methodExpression = call.getMethodExpression(); final String methodName = methodExpression.getReferenceName(); if (methodName == null) { diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionTest.groovy similarity index 82% rename from plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionTest.java rename to plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionTest.groovy index 922fedc676e0..a9175c14f9e4 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionTest.groovy @@ -12,15 +12,15 @@ public class IgnoreResultOfCallInspectionTest extends LightInspectionTestCase { @Override protected String[] getEnvironmentClasses() { - return new String[]{ + return [ "package java.util.regex; public class Pattern {" + " public static Pattern compile(String regex) {return null;}" + " public Matcher matcher(CharSequence input) {return null;}" + "}", "package java.util.regex; public class Matcher {" + " public boolean find() {return true;}" + - "}", - }; + "}" + ] as String[] } public void testObjectMethods() { @@ -41,4 +41,21 @@ public class IgnoreResultOfCallInspectionTest extends LightInspectionTestCase { " }\n" + "}\n"); } + + public void testPureMethod() { + doTest """ +import org.jetbrains.annotations.Contract; + +class Util { + @Contract(pure=true) + static Object util() { return null; } +} + +class C { + { + Util./*Result of 'Util.util()' is ignored*/util/**/(); + } +} +""" + } } \ No newline at end of file diff --git a/plugins/git4idea/src/META-INF/plugin.xml b/plugins/git4idea/src/META-INF/plugin.xml index ad09f73663a6..da7d14a9117a 100644 --- a/plugins/git4idea/src/META-INF/plugin.xml +++ b/plugins/git4idea/src/META-INF/plugin.xml @@ -75,10 +75,27 @@ - + + + + + + + + + + + + + + + - + + diff --git a/plugins/git4idea/src/git4idea/GitUtil.java b/plugins/git4idea/src/git4idea/GitUtil.java index fec8b0b8c2c6..42c8f1030d10 100644 --- a/plugins/git4idea/src/git4idea/GitUtil.java +++ b/plugins/git4idea/src/git4idea/GitUtil.java @@ -939,4 +939,16 @@ public class GitUtil { final String output = diff.run(); return !output.trim().isEmpty(); } + + /** + * Report a warning that the given root has no associated GitRepositories. + */ + public static void noRepositoryForRoot(@NotNull Logger log, @NotNull VirtualFile root, @NotNull Project project) { + GitRepositoryManager repositoryManager = getRepositoryManager(project); + ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project); + List roots = Arrays.asList(vcsManager.getRootsUnderVcs(GitVcs.getInstance(project))); + log.warn(String.format("Repository not found for root: %s. All roots: %s, all repositories: %s", root, roots, + repositoryManager.getRepositories())); + } + } diff --git a/plugins/git4idea/src/git4idea/actions/GitCheckoutRevisionAction.java b/plugins/git4idea/src/git4idea/actions/GitCheckoutRevisionAction.java new file mode 100644 index 000000000000..fc2451820fee --- /dev/null +++ b/plugins/git4idea/src/git4idea/actions/GitCheckoutRevisionAction.java @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2013 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. + */ +package git4idea.actions; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.vcs.log.VcsFullCommitDetails; +import git4idea.branch.GitBrancher; +import git4idea.repo.GitRepository; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; + +public class GitCheckoutRevisionAction extends GitLogSingleCommitAction { + + @Override + protected void actionPerformed(@NotNull GitRepository repository, @NotNull VcsFullCommitDetails commit) { + GitBrancher brancher = ServiceManager.getService(repository.getProject(), GitBrancher.class); + brancher.checkout(commit.getHash().asString(), Collections.singletonList(repository), null); + } + +} diff --git a/plugins/git4idea/src/git4idea/actions/GitCreateNewBranchAction.java b/plugins/git4idea/src/git4idea/actions/GitCreateNewBranchAction.java new file mode 100644 index 000000000000..e53f243608fd --- /dev/null +++ b/plugins/git4idea/src/git4idea/actions/GitCreateNewBranchAction.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2013 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. + */ +package git4idea.actions; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.vcs.log.VcsFullCommitDetails; +import git4idea.branch.GitBranchUtil; +import git4idea.branch.GitBrancher; +import git4idea.repo.GitRepository; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; + +public class GitCreateNewBranchAction extends GitLogSingleCommitAction { + + @Override + protected void actionPerformed(@NotNull GitRepository repository, @NotNull VcsFullCommitDetails commit) { + Project project = repository.getProject(); + String reference = commit.getHash().asString(); + final String name = GitBranchUtil.getNewBranchNameFromUser(project, Collections.singleton(repository), + "Checkout New Branch From " + reference); + if (name != null) { + GitBrancher brancher = ServiceManager.getService(project, GitBrancher.class); + brancher.checkoutNewBranchStartingFrom(name, reference, Collections.singletonList(repository), null); + } + } +} diff --git a/plugins/git4idea/src/git4idea/actions/GitCreateTagAction.java b/plugins/git4idea/src/git4idea/actions/GitCreateTagAction.java new file mode 100644 index 000000000000..344c236b3f37 --- /dev/null +++ b/plugins/git4idea/src/git4idea/actions/GitCreateTagAction.java @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2013 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. + */ +package git4idea.actions; + +import com.intellij.vcs.log.VcsFullCommitDetails; +import git4idea.history.wholeTree.GitCreateNewTag; +import git4idea.repo.GitRepository; +import org.jetbrains.annotations.NotNull; + +public class GitCreateTagAction extends GitLogSingleCommitAction { + + @Override + protected void actionPerformed(@NotNull GitRepository repository, @NotNull VcsFullCommitDetails commit) { + String reference = commit.getHash().asString(); + new GitCreateNewTag(repository.getProject(), repository, reference, null).execute(); + } + +} diff --git a/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java b/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java new file mode 100644 index 000000000000..364b1f58b15e --- /dev/null +++ b/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java @@ -0,0 +1,90 @@ +/* + * Copyright 2000-2013 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. + */ +package git4idea.actions; + +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.project.Project; +import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.VcsLog; +import com.intellij.vcs.log.VcsLogDataKeys; +import git4idea.GitUtil; +import git4idea.repo.GitRepository; +import git4idea.repo.GitRepositoryManager; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * @author Kirill Likhodedov + */ +public abstract class GitLogSingleCommitAction extends DumbAwareAction { + + private static final Logger LOG = Logger.getInstance(GitLogSingleCommitAction.class); + + protected abstract void actionPerformed(@NotNull GitRepository repository, @NotNull VcsFullCommitDetails commit); + + @Override + public void actionPerformed(AnActionEvent e) { + Data data = Data.collect(e); + if (!data.isValid()) { + return; + } + + List details = data.log.getSelectedDetails(); + if (details.size() != 1) { + return; + } + VcsFullCommitDetails commit = details.get(0); + + GitRepositoryManager repositoryManager = ServiceManager.getService(data.project, GitRepositoryManager.class); + final GitRepository repository = repositoryManager.getRepositoryForRoot(commit.getRoot()); + if (repository == null) { + GitUtil.noRepositoryForRoot(LOG, commit.getRoot(), data.project); + return; + } + + actionPerformed(repository, commit); + } + + @Override + public void update(AnActionEvent e) { + Data data = Data.collect(e); + boolean enabled = data.isValid() && data.log.getSelectedCommits().size() == 1; + getTemplatePresentation().setVisible(data.isValid()); + getTemplatePresentation().setEnabled(enabled); + } + + private static class Data { + Project project; + VcsLog log; + + static Data collect(AnActionEvent e) { + Data data = new Data(); + data.project = e.getData(CommonDataKeys.PROJECT); + data.log = e.getData(VcsLogDataKeys.VSC_LOG); + return data; + } + + boolean isValid() { + return project != null && log != null; + } + } + +} diff --git a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java index ffa399e93299..705e86169847 100644 --- a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java +++ b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java @@ -26,11 +26,7 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.intellij.vcs.log.Hash; -import com.intellij.vcs.log.VcsFullCommitDetails; -import com.intellij.vcs.log.VcsLog; -import com.intellij.vcs.log.VcsLogObjectsFactory; -import com.intellij.vcs.log.impl.VcsLogImpl; +import com.intellij.vcs.log.*; import git4idea.GitLocalBranch; import git4idea.GitPlatformFacade; import git4idea.GitVcs; @@ -175,7 +171,7 @@ public class GitCherryPickAction extends DumbAwareAction { if (commits != null) { return convertHeavyCommitToFullDetails(commits, project); } - final VcsLog log = getVcsLog(project); + final VcsLog log = getVcsLog(e); if (log == null) { return null; } @@ -218,9 +214,8 @@ public class GitCherryPickAction extends DumbAwareAction { }); } - private static VcsLog getVcsLog(@NotNull Project project) { - VcsLog logService = ServiceManager.getService(project, VcsLog.class); - return logService != null && ((VcsLogImpl)logService).isReady() ? logService : null; + private static VcsLog getVcsLog(@NotNull AnActionEvent event) { + return event.getData(VcsLogDataKeys.VSC_LOG); } // TODO remove after removing the old Vcs Log implementation @@ -233,7 +228,7 @@ public class GitCherryPickAction extends DumbAwareAction { if (event.getProject() == null) { return null; } - VcsLog log = getVcsLog(event.getProject()); + VcsLog log = getVcsLog(event); if (log == null) { return null; } diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserFromLogAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserFromLogAction.java index b3b2e12982f5..7b3d9a1b8c3e 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserFromLogAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserFromLogAction.java @@ -22,11 +22,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.intellij.vcs.log.Hash; -import com.intellij.vcs.log.VcsLog; -import com.intellij.vcs.log.VcsLogObjectsFactory; -import com.intellij.vcs.log.VcsShortCommitDetails; -import com.intellij.vcs.log.impl.VcsLogImpl; +import com.intellij.vcs.log.*; import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.history.browser.GitHeavyCommit; @@ -84,8 +80,8 @@ public class GithubShowCommitInBrowserFromLogAction extends GithubShowCommitInBr return factory.createShortDetails(factory.createHash(heavyCommit.getHash().getValue()), parents, heavyCommit.getAuthorTime(), heavyCommit.getRoot(), heavyCommit.getSubject(), heavyCommit.getAuthor()); } - VcsLog log = ServiceManager.getService(e.getProject(), VcsLog.class); - if (log == null || !((VcsLogImpl)log).isReady()) { + VcsLog log = e.getData(VcsLogDataKeys.VSC_LOG); + if (log == null) { return null; } List selectedCommits = log.getSelectedCommits(); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java index dd1e26f55302..9a933d3bbfd7 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java @@ -15,6 +15,7 @@ */ package org.jetbrains.idea.maven.indices; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.io.*; import gnu.trove.THashMap; @@ -617,8 +618,13 @@ public class MavenIndex { } } - private PersistentHashMap> createPersistentMap(File f) throws IOException { - return new PersistentHashMap>(f, new EnumeratorStringDescriptor(), new SetDescriptor()); + private PersistentHashMap> createPersistentMap(final File f) throws IOException { + return IOUtil.openCleanOrResetBroken(new ThrowableComputable>, IOException>() { + @Override + public PersistentHashMap> compute() throws IOException { + return new PersistentHashMap>(f, new EnumeratorStringDescriptor(), new SetDescriptor()); + } + }, f); } public void close(boolean releaseIndexContext) throws MavenIndexException {