Merge remote branch 'origin/master'

This commit is contained in:
Kirill Kalishev
2011-10-26 17:21:55 +04:00
9 changed files with 153 additions and 85 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -45,6 +45,7 @@ import com.sun.jdi.event.Event;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.regex.PatternSyntaxException;
@@ -373,6 +374,18 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils {
public abstract CompletionEditor createEditor(Project project, PsiElement context, @NonNls String recentsId);
@Nullable
public static CodeFragmentFactory getEffectiveCodeFragmentFactory(final PsiElement psiContext) {
final CodeFragmentFactory factory = ApplicationManager.getApplication().runReadAction(new Computable<CodeFragmentFactory>() {
public CodeFragmentFactory compute() {
final List<CodeFragmentFactory> codeFragmentFactories = getCodeFragmentFactories(psiContext);
// the list always contains at least DefaultCodeFragmentFactory
return codeFragmentFactories.get(0);
}
});
return factory != null? new CodeFragmentFactoryContextWrapper(factory) : null;
}
private static class SigReader {
final String buffer;
int pos = 0;
@@ -564,4 +577,6 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils {
return DebuggerBundle.message("status.thread.undefined");
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -17,6 +17,8 @@ package com.intellij.debugger.impl;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.lang.LanguageExtension;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
@@ -29,4 +31,7 @@ public interface EditorTextProvider {
@Nullable
TextWithImports getEditorText(PsiElement elementAtCaret);
@Nullable
Pair<PsiElement, TextRange> findExpression(PsiElement elementAtCaret, boolean allowMethodCalls);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -15,16 +15,23 @@
*/
package com.intellij.debugger.impl;
import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.debugger.engine.evaluation.CodeFragmentKind;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nullable;
/**
* @author Maxim.Medvedev
*/
public class JavaEditorTextProviderImpl implements EditorTextProvider {
private static final Logger LOG = Logger.getInstance(JavaEditorTextProviderImpl.class);
@Override
public TextWithImports getEditorText(PsiElement elementAtCaret) {
String result = null;
@@ -68,4 +75,55 @@ public class JavaEditorTextProviderImpl implements EditorTextProvider {
}
return null;
}
@Nullable
public Pair<PsiElement, TextRange> findExpression(PsiElement element, boolean allowMethodCalls) {
if (!(element instanceof PsiIdentifier || element instanceof PsiKeyword)) {
return null;
}
PsiElement expression = null;
PsiElement parent = element.getParent();
if (parent instanceof PsiVariable) {
expression = element;
}
else if (parent instanceof PsiReferenceExpression) {
final PsiElement pparent = parent.getParent();
if (pparent instanceof PsiCallExpression) {
parent = pparent;
}
if (allowMethodCalls || !DebuggerUtils.hasSideEffects(parent)) {
expression = parent;
}
}
else if (parent instanceof PsiThisExpression) {
expression = parent;
}
if (expression != null) {
try {
PsiElement context = element;
if(parent instanceof PsiParameter) {
try {
context = ((PsiMethod)((PsiParameter)parent).getDeclarationScope()).getBody();
}
catch (Throwable ignored) {
}
}
else {
while(context != null && !(context instanceof PsiStatement) && !(context instanceof PsiClass)) {
context = context.getParent();
}
}
TextRange textRange = expression.getTextRange();
PsiElement psiExpression = JavaPsiFacade.getInstance(expression.getProject()).getElementFactory().createExpressionFromText(expression.getText(), context);
return Pair.create(psiExpression, textRange);
}
catch (IncorrectOperationException e) {
LOG.debug(e);
}
}
return null;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -20,7 +20,6 @@ import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.DebuggerInvocationUtil;
import com.intellij.debugger.DebuggerManagerEx;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.debugger.engine.JVMName;
import com.intellij.debugger.engine.JVMNameUtil;
import com.intellij.debugger.engine.evaluation.*;
@@ -29,6 +28,8 @@ import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
import com.intellij.debugger.impl.DebuggerContextImpl;
import com.intellij.debugger.impl.DebuggerSession;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.impl.EditorTextProvider;
import com.intellij.debugger.ui.impl.DebuggerTreeRenderer;
import com.intellij.debugger.ui.impl.InspectDebuggerTree;
import com.intellij.debugger.ui.impl.watch.WatchItemDescriptor;
@@ -39,6 +40,7 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.ui.SimpleColoredText;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.IncorrectOperationException;
@@ -60,16 +62,16 @@ import java.awt.*;
*/
public class ValueHint extends AbstractValueHint {
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.ValueHint");
private PsiExpression myCurrentExpression = null;
private PsiElement myCurrentExpression = null;
private Value myValueToShow = null;
private ValueHint(Project project, Editor editor, Point point, ValueHintType type, final PsiExpression selectedExpression, final TextRange textRange) {
private ValueHint(Project project, Editor editor, Point point, ValueHintType type, final PsiElement selectedExpression, final TextRange textRange) {
super(project, editor, point, type, textRange);
myCurrentExpression = selectedExpression;
}
public static ValueHint createValueHint(Project project, Editor editor, Point point, ValueHintType type) {
Trinity<PsiExpression, TextRange, Value> trinity = getSelectedExpression(project, editor, point, type);
Trinity<PsiElement, TextRange, Value> trinity = getSelectedExpression(project, editor, point, type);
final ValueHint hint = new ValueHint(project, editor, point, type, trinity.getFirst(), trinity.getSecond());
hint.myValueToShow = trinity.getThird();
return hint;
@@ -79,6 +81,22 @@ public class ValueHint extends AbstractValueHint {
return myCurrentExpression != null;
}
@Nullable
private ExpressionEvaluator getExpressionEvaluator(DebuggerContextImpl debuggerContext) throws EvaluateException {
if (myCurrentExpression instanceof PsiExpression) {
return EvaluatorBuilderImpl.getInstance().build(myCurrentExpression, debuggerContext.getSourcePosition());
}
CodeFragmentFactory factory = DebuggerUtilsEx.getEffectiveCodeFragmentFactory(myCurrentExpression);
TextWithImportsImpl textWithImports = new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, myCurrentExpression.getText());
if (factory == null) return null;
JavaCodeFragment codeFragment = factory.createCodeFragment(textWithImports, myCurrentExpression.getContext(), getProject());
codeFragment.forceResolveScope(GlobalSearchScope.allScope(getProject()));
return factory.getEvaluatorBuilder().build(codeFragment, debuggerContext.getSourcePosition());
}
protected void evaluateAndShowHint() {
final DebuggerContextImpl debuggerContext = DebuggerManagerEx.getInstanceEx(getProject()).getContext();
@@ -86,7 +104,9 @@ public class ValueHint extends AbstractValueHint {
if(debuggerSession == null || !debuggerSession.isPaused()) return;
try {
final ExpressionEvaluator evaluator = EvaluatorBuilderImpl.getInstance().build(myCurrentExpression, debuggerContext.getSourcePosition());
final ExpressionEvaluator evaluator = getExpressionEvaluator(debuggerContext);
if (evaluator == null) return;
debuggerContext.getDebugProcess().getManagerThread().schedule(new DebuggerContextCommandImpl(debuggerContext) {
public Priority getPriority() {
@@ -201,57 +221,16 @@ public class ValueHint extends AbstractValueHint {
}
@Nullable
private static Pair<PsiExpression, TextRange> findExpression(PsiElement element, boolean allowMethodCalls) {
if (!(element instanceof PsiIdentifier || element instanceof PsiKeyword)) {
return null;
}
PsiElement expression = null;
PsiElement parent = element.getParent();
if (parent instanceof PsiVariable) {
expression = element;
}
else if (parent instanceof PsiReferenceExpression) {
final PsiElement pparent = parent.getParent();
if (pparent instanceof PsiMethodCallExpression) {
parent = pparent;
}
if (allowMethodCalls || !DebuggerUtils.hasSideEffects(parent)) {
expression = parent;
}
}
else if (parent instanceof PsiThisExpression) {
expression = parent;
}
if (expression != null) {
try {
PsiElement context = element;
if(parent instanceof PsiParameter) {
try {
context = ((PsiMethod)((PsiParameter)parent).getDeclarationScope()).getBody();
}
catch (Throwable ignored) {
}
}
else {
while(context != null && !(context instanceof PsiStatement) && !(context instanceof PsiClass)) {
context = context.getParent();
}
}
TextRange textRange = expression.getTextRange();
PsiExpression psiExpression = JavaPsiFacade.getInstance(expression.getProject()).getElementFactory().createExpressionFromText(expression.getText(), context);
return Pair.create(psiExpression, textRange);
}
catch (IncorrectOperationException e) {
LOG.debug(e);
}
private static Pair<PsiElement, TextRange> findExpression(PsiElement element, boolean allowMethodCalls) {
final EditorTextProvider textProvider = EditorTextProvider.EP.forLanguage(element.getLanguage());
if (textProvider != null) {
return textProvider.findExpression(element, allowMethodCalls);
}
return null;
}
private static Trinity<PsiExpression, TextRange, Value> getSelectedExpression(final Project project, final Editor editor, final Point point, final ValueHintType type) {
final Ref<PsiExpression> selectedExpression = Ref.create(null);
private static Trinity<PsiElement, TextRange, Value> getSelectedExpression(final Project project, final Editor editor, final Point point, final ValueHintType type) {
final Ref<PsiElement> selectedExpression = Ref.create(null);
final Ref<TextRange> currentRange = Ref.create(null);
final Ref<Value> preCalculatedValue = Ref.create(null);
@@ -273,7 +252,7 @@ public class ValueHint extends AbstractValueHint {
try {
String text = editor.getSelectionModel().getSelectedText();
if(text != null && ctx != null) {
selectedExpression.set(JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText(text, ctx));
selectedExpression.set(JVMElementFactories.getFactory(ctx.getLanguage(), project).createExpressionFromText(text, ctx));
currentRange.set(new TextRange(editor.getSelectionModel().getSelectionStart(), editor.getSelectionModel().getSelectionEnd()));
}
} catch (IncorrectOperationException e) {
@@ -286,7 +265,7 @@ public class ValueHint extends AbstractValueHint {
if (elementAtCursor == null) {
return;
}
Pair<PsiExpression, TextRange> pair = findExpression(elementAtCursor, type == ValueHintType.MOUSE_CLICK_HINT || type == ValueHintType.MOUSE_ALT_OVER_HINT);
Pair<PsiElement, TextRange> pair = findExpression(elementAtCursor, type == ValueHintType.MOUSE_CLICK_HINT || type == ValueHintType.MOUSE_ALT_OVER_HINT);
if (pair == null) {
if (type == ValueHintType.MOUSE_OVER_HINT) {
final DebuggerSession debuggerSession = DebuggerManagerEx.getInstanceEx(project).getContext().getDebuggerSession();
@@ -295,7 +274,7 @@ public class ValueHint extends AbstractValueHint {
if (lastExecuted != null) {
final Method method = lastExecuted.getFirst();
if (method != null) {
final Pair<PsiExpression, TextRange> expressionPair = findExpression(elementAtCursor, true);
final Pair<PsiElement, TextRange> expressionPair = findExpression(elementAtCursor, true);
if (expressionPair != null && expressionPair.getFirst() instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expressionPair.getFirst();
final PsiMethod psiMethod = methodCallExpression.resolveMethod();
@@ -311,7 +290,7 @@ public class ValueHint extends AbstractValueHint {
}
}
}
}
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -22,15 +22,12 @@ import com.intellij.debugger.EvaluatingComputable;
import com.intellij.debugger.engine.ContextUtil;
import com.intellij.debugger.engine.StackFrameContext;
import com.intellij.debugger.engine.evaluation.*;
import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl;
import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
import com.intellij.debugger.engine.evaluation.expression.Modifier;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.impl.PositionUtil;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiCodeFragment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
@@ -40,8 +37,6 @@ import com.sun.jdi.Value;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author lex
*/
@@ -74,14 +69,7 @@ public abstract class EvaluationDescriptor extends ValueDescriptorImpl{
if (myCodeFragmentFactory != null) {
return myCodeFragmentFactory;
}
final CodeFragmentFactory factory = ApplicationManager.getApplication().runReadAction(new Computable<CodeFragmentFactory>() {
public CodeFragmentFactory compute() {
final List<CodeFragmentFactory> codeFragmentFactories = DebuggerUtilsEx.getCodeFragmentFactories(psiContext);
// the list always contains at least DefaultCodeFragmentFactory
return codeFragmentFactories.get(0);
}
});
return factory != null? new CodeFragmentFactoryContextWrapper(factory) : null;
return DebuggerUtilsEx.getEffectiveCodeFragmentFactory(psiContext);
}
protected abstract EvaluationContextImpl getEvaluationContext (EvaluationContextImpl evaluationContext);
@@ -124,4 +124,6 @@ public interface JVMElementFactory {
@NotNull
PsiAnnotation createAnnotationFromText(@NotNull @NonNls String annotationText, @Nullable PsiElement context) throws IncorrectOperationException;
PsiElement createExpressionFromText(String text, PsiElement ctx) throws IncorrectOperationException;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -19,15 +19,18 @@ import com.intellij.debugger.engine.evaluation.CodeFragmentKind;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
import com.intellij.debugger.impl.EditorTextProvider;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiEnumConstant;
import com.intellij.psi.PsiVariable;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrThisReferenceExpression;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
/**
* @author Maxim.Medvedev
@@ -36,7 +39,7 @@ public class GroovyEditorTextProvider implements EditorTextProvider {
@Override
public TextWithImports getEditorText(PsiElement elementAtCaret) {
String result = "";
PsiElement element = findExpression(elementAtCaret);
PsiElement element = findExpressionInner(elementAtCaret, false);
if (element != null) {
if (element instanceof GrReferenceExpression) {
final GrReferenceExpression reference = (GrReferenceExpression)element;
@@ -59,18 +62,31 @@ public class GroovyEditorTextProvider implements EditorTextProvider {
}
@Nullable
private static PsiElement findExpression(PsiElement element) {
private static PsiElement findExpressionInner(PsiElement element, boolean allowMethodCalls) {
PsiElement parent = element.getParent();
if (parent instanceof GrVariable && element == ((GrVariable)parent).getNameIdentifierGroovy()) {
return element;
}
if (parent instanceof GrReferenceExpression) {
if (parent.getParent() instanceof GrCall) return parent.getParent();
return parent;
else if (parent instanceof GrReferenceExpression) {
final PsiElement pparent = parent.getParent();
if (pparent instanceof GrCall) {
parent = pparent;
}
if (allowMethodCalls || !GroovyRefactoringUtil.hasSideEffect((GroovyPsiElement)parent)) {
return parent;
}
}
if (parent instanceof GrThisReferenceExpression) {
return parent;
}
return null;
}
@Override
public Pair<PsiElement, TextRange> findExpression(PsiElement element, boolean allowMethodCalls) {
PsiElement expression = findExpressionInner(element, allowMethodCalls);
if (expression == null) return null;
return new Pair<PsiElement, TextRange>(expression, expression.getTextRange());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -143,8 +143,11 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory {
public GrExpression createExpressionFromText(String text, PsiElement context) {
GroovyFileImpl file = (GroovyFileImpl)createGroovyFile(text, false, context);
assert file.getTopStatements()[0] instanceof GrExpression;
return (GrExpression) file.getTopStatements()[0];
GrTopStatement[] topStatements = file.getTopStatements();
if (topStatements.length == 0 || !(topStatements[0] instanceof GrExpression)) {
throw new IncorrectOperationException("incorrect expression = '" + text + "'");
}
return (GrExpression) topStatements[0];
}
public GrVariableDeclaration createVariableDeclaration(@Nullable String[] modifiers,
@@ -615,7 +615,7 @@ public abstract class GroovyRefactoringUtil {
return GroovyPsiElementFactory.getInstance(project).createExpressionFromText(argText.toString());
}
public static boolean hasSideEffect(@NotNull GrStatement statement) {
public static boolean hasSideEffect(@NotNull GroovyPsiElement statement) {
final Ref<Boolean> hasSideEffect = new Ref<Boolean>(false);
statement.accept(new GroovyRecursiveElementVisitor() {
@Override
@@ -633,6 +633,8 @@ public abstract class GroovyRefactoringUtil {
hasSideEffect.set(true);
}
@Override
public void visitElement(GroovyPsiElement element) {
if (hasSideEffect.get()) return;