Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2016-11-09 19:50:55 +01:00
9 changed files with 112 additions and 72 deletions
@@ -24,7 +24,6 @@ import com.intellij.psi.impl.PsiJavaParserFacadeImpl;
import com.sun.jdi.*;
import java.util.Collections;
import java.util.List;
/**
* @author Eugene Zhuravlev
@@ -59,14 +58,14 @@ public class BoxingEvaluator implements Evaluator{
final ClassType wrapperClass = (ClassType)process.findClass(context, wrapperTypeName, null);
final String methodSignature = "(" + JVMNameUtil.getPrimitiveSignature(value.type().name()) + ")L" + wrapperTypeName.replace('.', '/') + ";";
List<Method> methods = wrapperClass.methodsByName("valueOf", methodSignature);
if (methods.size() == 0) { // older JDK version
methods = wrapperClass.methodsByName(JVMNameUtil.CONSTRUCTOR_NAME, methodSignature);
Method method = wrapperClass.concreteMethodByName("valueOf", methodSignature);
if (method == null) { // older JDK version
method = wrapperClass.concreteMethodByName(JVMNameUtil.CONSTRUCTOR_NAME, methodSignature);
}
if (methods.size() == 0) {
if (method == null) {
throw new EvaluateException("Cannot construct wrapper object for value of type " + value.type() + ": Unable to find either valueOf() or constructor method");
}
return process.invokeMethod(context, wrapperClass, methods.get(0), Collections.singletonList(value));
return process.invokeMethod(context, wrapperClass, method, Collections.singletonList(value));
}
}
@@ -26,6 +26,11 @@ import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.sun.jdi.ClassType;
import com.sun.jdi.Method;
import com.sun.jdi.StringReference;
import java.util.Collections;
class LiteralEvaluator implements Evaluator {
private final Object myValue;
@@ -57,7 +62,13 @@ class LiteralEvaluator implements Evaluator {
return DebuggerUtilsEx.createValue(vm, myExpectedType, ((Number)myValue).longValue());
}
if (myValue instanceof String) {
return vm.mirrorOf((String)myValue);
StringReference str = vm.mirrorOf((String)myValue);
// intern
Method internMethod = ((ClassType)str.referenceType()).concreteMethodByName("intern", "()Ljava/lang/String;");
if (internMethod != null) {
return context.getDebugProcess().invokeMethod(context, str, internMethod, Collections.emptyList());
}
return str;
}
throw EvaluateExceptionUtil
.createEvaluateException(DebuggerBundle.message("evaluation.error.unknown.expression.type", myExpectedType));
@@ -29,7 +29,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
@@ -80,12 +79,12 @@ public class UnBoxingEvaluator implements Evaluator{
String conversionMethodSignature) throws EvaluateException {
final DebugProcessImpl process = context.getDebugProcess();
final ClassType wrapperClass = (ClassType)value.referenceType();
final List<Method> methods = wrapperClass.methodsByName(conversionMethodName, conversionMethodSignature);
if (methods.size() == 0) {
Method method = wrapperClass.concreteMethodByName(conversionMethodName, conversionMethodSignature);
if (method == null) {
throw new EvaluateException("Cannot convert to primitive value of type " + value.type() + ": Unable to find method " +
conversionMethodName + conversionMethodSignature);
}
return process.invokeMethod(context, value, methods.get(0), Collections.emptyList());
return process.invokeMethod(context, value, method, Collections.emptyList());
}
}
@@ -16,6 +16,7 @@
package com.intellij.debugger.jdi;
import com.intellij.Patches;
import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.debugger.engine.jdi.VirtualMachineProxy;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.openapi.util.Ref;
@@ -23,7 +24,6 @@ import com.intellij.util.ReflectionUtil;
import com.intellij.util.ThrowableConsumer;
import com.intellij.util.containers.ContainerUtil;
import com.sun.jdi.*;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.org.objectweb.asm.*;
@@ -242,9 +242,12 @@ public class MethodBytecodeUtil {
visit(applicableMethods.get(0), new MethodVisitor(Opcodes.API_VERSION) {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
ReferenceType cls = ContainerUtil.getFirstItem(vm.classesByName(owner));
ReferenceType cls = ContainerUtil.getFirstItem(vm.classesByName(owner.replace("/", ".")));
if (cls != null) {
cls.methodsByName(name, desc).stream().findFirst().ifPresent(methodRef::set);
Method method = DebuggerUtils.findMethod(cls, name, desc);
if (method != null) {
methodRef.setIfNull(method);
}
}
}
}, false);
@@ -262,14 +265,18 @@ public class MethodBytecodeUtil {
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
ReferenceType declaringType = method.declaringType();
ReferenceType cls = null;
if (declaringType.name().equals(owner.replace("/", "."))) {
owner = owner.replace("/", ".");
if (declaringType.name().equals(owner)) {
cls = declaringType;
}
else if (!"java/lang/AbstractMethodError".equals(owner)) {
else if (!"java.lang.AbstractMethodError".equals(owner)) {
cls = ContainerUtil.getFirstItem(vm.classesByName(owner));
}
if (cls != null) {
StreamEx.of(cls.methodsByName(name, desc)).findFirst().ifPresent(methodRef::set);
Method method = DebuggerUtils.findMethod(cls, name, desc);
if (method != null) {
methodRef.setIfNull(method);
}
}
}
}, false);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -47,7 +47,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements ValueDescriptor{
@@ -235,11 +234,11 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
final ObjectReference exceptionObj = ex.getExceptionFromTargetVM();
if (exceptionObj != null && evaluationContext != null) {
try {
final ReferenceType refType = exceptionObj.referenceType();
final List<Method> methods = refType.methodsByName("getStackTrace", "()[Ljava/lang/StackTraceElement;");
if (methods.size() > 0) {
ClassType refType = (ClassType)exceptionObj.referenceType();
Method method = refType.concreteMethodByName("getStackTrace", "()[Ljava/lang/StackTraceElement;");
if (method != null) {
final DebugProcessImpl process = evaluationContext.getDebugProcess();
process.invokeMethod(evaluationContext, exceptionObj, methods.get(0), Collections.emptyList());
process.invokeMethod(evaluationContext, exceptionObj, method, Collections.emptyList());
// print to console as well
@@ -260,9 +259,7 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
}
}
}
catch (EvaluateException ignored) {
}
catch (ClassNotLoadedException ignored) {
catch (EvaluateException | ClassNotLoadedException ignored) {
}
catch (Throwable e) {
LOG.info(e); // catch all exceptions to ensure the method returns gracefully
@@ -133,8 +133,8 @@ public class ToStringRenderer extends NodeRendererImpl {
@SuppressWarnings({"HardCodedStringLiteral"})
private static boolean overridesToString(Type type) {
if (type instanceof ClassType) {
return ((ClassType)type).methodsByName("toString", "()Ljava/lang/String;").stream()
.anyMatch(method -> !CommonClassNames.JAVA_LANG_OBJECT.equals(method.declaringType().name()));
return !CommonClassNames.JAVA_LANG_OBJECT
.equals(((ClassType)type).concreteMethodByName("toString", "()Ljava/lang/String;").declaringType().name());
}
return false;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -13,12 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.history.integration;
import com.intellij.history.*;
import com.intellij.history.core.*;
import com.intellij.history.core.tree.RootEntry;
import com.intellij.history.integration.ui.models.DirectoryHistoryDialogModel;
import com.intellij.history.integration.ui.models.EntireFileHistoryDialogModel;
import com.intellij.history.integration.ui.models.HistoryDialogModel;
@@ -26,11 +24,10 @@ import com.intellij.history.utils.LocalHistoryLog;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Clock;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.ShutDownTracker;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
@@ -39,7 +36,6 @@ import com.intellij.openapi.vfs.VirtualFileListener;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusConnection;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
@@ -104,24 +100,6 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
VirtualFileManager fm = VirtualFileManager.getInstance();
fm.addVirtualFileManagerListener(myEventDispatcher);
if (ApplicationManager.getApplication().isInternal() && !ApplicationManager.getApplication().isUnitTestMode()) {
ApplicationManager.getApplication().executeOnPooledThread(() -> validateStorage());
}
}
private void validateStorage() {
if (ApplicationManager.getApplication().isInternal() && !ApplicationManager.getApplication().isUnitTestMode()) {
LocalHistoryLog.LOG.info("Checking local history storage...");
try {
long before = Clock.getTime();
myVcs.getChangeListInTests().getChangesInTests();
LocalHistoryLog.LOG.info("Local history storage seems to be ok (took " + ((Clock.getTime() - before) / 1000) + " sec)");
}
catch (Exception e) {
LocalHistoryLog.LOG.error(e);
}
}
}
public File getStorageDir() {
@@ -144,12 +122,8 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
fm.removeVirtualFileManagerListener(myEventDispatcher);
CommandProcessor.getInstance().removeCommandListener(myEventDispatcher);
validateStorage();
LocalHistoryLog.LOG.debug("Purging local history...");
myChangeList.purgeObsolete(period);
validateStorage();
myChangeList.close();
LocalHistoryLog.LOG.debug("Local history storage successfully closed.");
@@ -179,7 +153,7 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
return label(myVcs.putUserLabel(name, getProjectId(p)));
}
private String getProjectId(Project p) {
private static String getProjectId(Project p) {
return p.getLocationHash();
}
@@ -203,13 +177,7 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
@Override
public ByteContent getByteContent(final String path) {
return ApplicationManager.getApplication().runReadAction(new Computable<ByteContent>() {
@Override
public ByteContent compute() {
RootEntry root = myGateway.createTransientRootEntryForPathOnly(path);
return impl.getByteContent(root, path);
}
});
return ReadAction.compute(() -> impl.getByteContent(myGateway.createTransientRootEntryForPathOnly(path), path));
}
};
}
@@ -219,12 +187,7 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
public byte[] getByteContent(final VirtualFile f, final FileRevisionTimestampComparator c) {
if (!isInitialized()) return null;
if (!myGateway.areContentChangesVersioned(f)) return null;
return ApplicationManager.getApplication().runReadAction(new Computable<byte[]>() {
@Override
public byte[] compute() {
return new ByteContentRetriever(myGateway, myVcs, f, c).getResult();
}
});
return ReadAction.compute(() -> new ByteContentRetriever(myGateway, myVcs, f, c).getResult());
}
@Override
@@ -237,7 +200,6 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
}
@Override
@NonNls
@NotNull
public String getComponentName() {
return "Local History";
@@ -270,4 +232,4 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
throw new LocalHistoryException(String.format("Couldn't revert %s to local history label.", f.getName()), e);
}
}
}
}
@@ -0,0 +1,63 @@
/*
* Copyright 2000-2016 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.history.integration
import com.intellij.history.core.changes.ChangeSet
import com.intellij.history.core.changes.ChangeVisitor
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.Task
import com.intellij.openapi.ui.Messages
import com.intellij.util.ExceptionUtil
class ValidateHistoryAction : AnAction() {
override fun update(e: AnActionEvent) {
e.presentation.isEnabledAndVisible = ApplicationManager.getApplication().isInternal
}
override fun actionPerformed(e: AnActionEvent) {
object : Task.Modal(e.project, "Checking local history storage", true) {
override fun run(indicator: ProgressIndicator) {
val t = System.currentTimeMillis()
try {
LocalHistoryImpl.getInstanceImpl().facade?.accept(object : ChangeVisitor() {
private var count = 0
override fun end(c: ChangeSet) {
indicator.checkCanceled()
if (++count % 10 == 0) {
indicator.text = "${count} records checked"
}
}
override fun finished() {
val message = "Local history storage seems to be OK (checked ${count} records in ${System.currentTimeMillis() - t} ms)"
ApplicationManager.getApplication().invokeLater { Messages.showInfoMessage(e.project, message, "Local History Validation") }
}
})
}
catch(ex: ProcessCanceledException) { throw ex }
catch(ex: Exception) {
Messages.showErrorDialog(e.project, ExceptionUtil.getThrowableText(ex), "Local History Validation Error")
}
}
}.queue()
}
}
@@ -152,6 +152,8 @@
<separator/>
<action internal="true" id="PruneEmptyDirectories" class="com.intellij.ide.actions.PruneEmptyDirectoriesAction" text="Prune Empty Directories"/>
<action internal="true" id="FixLineSeparators" class="com.intellij.ide.actions.FixLineSeparatorsAction" text="Fix Line Separators"/>
<separator/>
<action internal="true" id="ValidateLocalHistory" class="com.intellij.history.integration.ValidateHistoryAction" text="Validate Local History Storage"/>
</group>
<separator/>