blob: 7a709aed4449c3a38b90131c63b1fd3212ce3e7c [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.debugger.engine.evaluation;
import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilder;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.JavaCodeFragment;
import com.intellij.psi.JavaRecursiveElementVisitor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLocalVariable;
import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerManager;
import com.intellij.xdebugger.impl.XDebugSessionImpl;
import com.intellij.xdebugger.impl.frame.XValueMarkers;
import com.intellij.xdebugger.impl.ui.tree.ValueMarkup;
import com.sun.jdi.ObjectCollectedException;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.Value;
import java.util.HashMap;
import java.util.Map;
/**
* @author Eugene Zhuravlev
* Date: Aug 30, 2010
*/
public class CodeFragmentFactoryContextWrapper extends CodeFragmentFactory {
public static final Key<Value> LABEL_VARIABLE_VALUE_KEY = Key.create("_label_variable_value_key_");
public static final String DEBUG_LABEL_SUFFIX = "_DebugLabel";
private final CodeFragmentFactory myDelegate;
public CodeFragmentFactoryContextWrapper(CodeFragmentFactory delegate) {
myDelegate = delegate;
}
public JavaCodeFragment createCodeFragment(TextWithImports item, PsiElement context, Project project) {
return myDelegate.createCodeFragment(item, wrapContext(project, context), project);
}
public JavaCodeFragment createPresentationCodeFragment(TextWithImports item, PsiElement context, Project project) {
return myDelegate.createPresentationCodeFragment(item, wrapContext(project, context), project);
}
public boolean isContextAccepted(PsiElement contextElement) {
return myDelegate.isContextAccepted(contextElement);
}
public LanguageFileType getFileType() {
return myDelegate.getFileType();
}
@Override
public EvaluatorBuilder getEvaluatorBuilder() {
return myDelegate.getEvaluatorBuilder();
}
private PsiElement wrapContext(Project project, final PsiElement originalContext) {
if (project.isDefault()) return originalContext;
PsiElement context = originalContext;
XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession();
if (session != null) {
XValueMarkers<?, ?> markers = ((XDebugSessionImpl)session).getValueMarkers();
Map<?, ValueMarkup> markupMap = markers != null ? markers.getAllMarkers() : null;
//final Map<ObjectReference, ValueMarkup> markupMap = ValueDescriptorImpl.getMarkupMap(process);
if (markupMap != null && markupMap.size() > 0) {
final Pair<String, Map<String, ObjectReference>> markupVariables = createMarkupVariablesText(markupMap);
int offset = markupVariables.getFirst().length() - 1;
final TextWithImportsImpl textWithImports = new TextWithImportsImpl(CodeFragmentKind.CODE_BLOCK, markupVariables.getFirst(), "", myDelegate.getFileType());
final JavaCodeFragment codeFragment = myDelegate.createCodeFragment(textWithImports, context, project);
codeFragment.accept(new JavaRecursiveElementVisitor() {
public void visitLocalVariable(PsiLocalVariable variable) {
final String name = variable.getName();
variable.putUserData(LABEL_VARIABLE_VALUE_KEY, markupVariables.getSecond().get(name));
}
});
final PsiElement newContext = codeFragment.findElementAt(offset);
if (newContext != null) {
context = newContext;
}
}
}
return context;
}
private static Pair<String, Map<String, ObjectReference>> createMarkupVariablesText(Map<?, ValueMarkup> markupMap) {
final Map<String, ObjectReference> reverseMap = new HashMap<String, ObjectReference>();
final StringBuilder buffer = StringBuilderSpinAllocator.alloc();
try {
for (Map.Entry<?, ValueMarkup> entry : markupMap.entrySet()) {
ObjectReference objectRef = (ObjectReference)entry.getKey();
final ValueMarkup markup = entry.getValue();
String labelName = markup.getText();
if (!StringUtil.isJavaIdentifier(labelName)) {
continue;
}
try {
final String typeName = objectRef.type().name();
labelName += DEBUG_LABEL_SUFFIX;
if (buffer.length() > 0) {
buffer.append("\n");
}
buffer.append(typeName).append(" ").append(labelName).append(";");
reverseMap.put(labelName, objectRef);
}
catch (ObjectCollectedException e) {
//it.remove();
}
}
buffer.append(" ");
return Pair.create(buffer.toString(), reverseMap);
}
finally {
StringBuilderSpinAllocator.dispose(buffer);
}
}
}