mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
annotation support for debugger renderers - IDEA-144797
This commit is contained in:
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
*/
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.debugger.actions;
|
||||
|
||||
import com.intellij.debugger.engine.DebugProcessImpl;
|
||||
@@ -26,6 +12,7 @@ import com.intellij.debugger.ui.tree.render.NodeRenderer;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
|
||||
@@ -102,10 +89,10 @@ public class ViewAsGroup extends ActionGroup implements DumbAware {
|
||||
return myChildren;
|
||||
}
|
||||
|
||||
private static AnAction [] calcChildren(List<JavaValue> values) {
|
||||
private static AnAction [] calcChildren(List<JavaValue> values, Project project) {
|
||||
List<AnAction> renderers = new ArrayList<>();
|
||||
|
||||
List<NodeRenderer> allRenderers = NodeRendererSettings.getInstance().getAllRenderers();
|
||||
List<NodeRenderer> allRenderers = NodeRendererSettings.getInstance().getAllRenderers(project);
|
||||
|
||||
boolean anyValueDescriptor = false;
|
||||
|
||||
@@ -178,7 +165,7 @@ public class ViewAsGroup extends ActionGroup implements DumbAware {
|
||||
process.getManagerThread().schedule(new DebuggerContextCommandImpl(debuggerContext) {
|
||||
@Override
|
||||
public void threadAction(@NotNull SuspendContextImpl suspendContext) {
|
||||
myChildren = calcChildren(values);
|
||||
myChildren = calcChildren(values, process.getProject());
|
||||
DebuggerAction.enableAction(event, myChildren.length > 0);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.debugger.engine;
|
||||
|
||||
import com.intellij.Patches;
|
||||
@@ -161,7 +161,9 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
myNodeRenderersMap.clear();
|
||||
myRenderers.clear();
|
||||
try {
|
||||
NodeRendererSettings.getInstance().getAllRenderers().stream().filter(NodeRenderer::isEnabled).forEachOrdered(myRenderers::add);
|
||||
NodeRendererSettings.getInstance().getAllRenderers(myProject).stream()
|
||||
.filter(NodeRenderer::isEnabled)
|
||||
.forEachOrdered(myRenderers::add);
|
||||
}
|
||||
finally {
|
||||
DebuggerInvocationUtil.swingInvokeLater(myProject, () -> {
|
||||
|
||||
@@ -14,20 +14,27 @@ import com.intellij.debugger.ui.tree.DebuggerTreeNode;
|
||||
import com.intellij.debugger.ui.tree.ValueDescriptor;
|
||||
import com.intellij.debugger.ui.tree.render.*;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.CommonClassNames;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.AnnotatedElementsSearch;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.sun.jdi.Value;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.Debugger;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -41,6 +48,8 @@ import java.util.List;
|
||||
@Storage(value = "debugger.renderers.xml", deprecated = true),
|
||||
})
|
||||
public class NodeRendererSettings implements PersistentStateComponent<Element> {
|
||||
private static final Logger LOG = Logger.getInstance(NodeRendererSettings.class);
|
||||
|
||||
@NonNls private static final String REFERENCE_RENDERER = "Reference renderer";
|
||||
@NonNls public static final String RENDERER_TAG = "Renderer";
|
||||
@NonNls private static final String RENDERER_ID = "ID";
|
||||
@@ -218,7 +227,7 @@ public class NodeRendererSettings implements PersistentStateComponent<Element> {
|
||||
myDispatcher.getMulticaster().renderersChanged();
|
||||
}
|
||||
|
||||
public List<NodeRenderer> getAllRenderers() {
|
||||
public List<NodeRenderer> getAllRenderers(Project project) {
|
||||
// the order is important as the renderers are applied according to it
|
||||
final List<NodeRenderer> allRenderers = new ArrayList<>();
|
||||
|
||||
@@ -228,6 +237,10 @@ public class NodeRendererSettings implements PersistentStateComponent<Element> {
|
||||
return true;
|
||||
});
|
||||
|
||||
if (Registry.is("debugger.renderers.annotations")) {
|
||||
ReadAction.run(() -> addAnnotationRenderers(allRenderers, project));
|
||||
}
|
||||
|
||||
// plugins registered renderers come after that
|
||||
allRenderers.addAll(NodeRenderer.EP_NAME.getExtensionList());
|
||||
|
||||
@@ -241,6 +254,49 @@ public class NodeRendererSettings implements PersistentStateComponent<Element> {
|
||||
return allRenderers;
|
||||
}
|
||||
|
||||
private void addAnnotationRenderers(List<NodeRenderer> renderers, Project project) {
|
||||
try {
|
||||
GlobalSearchScope allScope = GlobalSearchScope.allScope(project);
|
||||
String annotationFqn = Debugger.Renderer.class.getName().replace("$", ".");
|
||||
PsiClass annotationClass =
|
||||
JavaPsiFacade.getInstance(project).findClass(annotationFqn, allScope);
|
||||
if (annotationClass != null) {
|
||||
AnnotatedElementsSearch.searchPsiClasses(annotationClass, allScope)
|
||||
.forEach(e -> {
|
||||
PsiAnnotation annotation = e.getAnnotation(annotationFqn);
|
||||
if (annotation != null) {
|
||||
String text = getAttributeValue(annotation, "text");
|
||||
LabelRenderer labelRenderer = StringUtil.isEmpty(text) ? null : createLabelRenderer(null, text, null);
|
||||
String childrenArray = getAttributeValue(annotation, "childrenArray");
|
||||
String isLeaf = getAttributeValue(annotation, "hasChildren");
|
||||
ExpressionChildrenRenderer childrenRenderer =
|
||||
StringUtil.isEmpty(childrenArray) ? null : createExpressionArrayChildrenRenderer(childrenArray, isLeaf, myArrayRenderer);
|
||||
CompoundReferenceRenderer renderer = createCompoundReferenceRenderer(
|
||||
e.getQualifiedName(), e.getQualifiedName(), labelRenderer, childrenRenderer);
|
||||
renderer.setEnabled(true);
|
||||
renderers.add(renderer);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (IndexNotReadyException | ProcessCanceledException ignore) {
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getAttributeValue(PsiAnnotation annotation, String attribute) {
|
||||
PsiAnnotationMemberValue value = annotation.findAttributeValue(attribute);
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (value instanceof PsiLiteralValue) {
|
||||
return String.valueOf(((PsiLiteralValue)value).getValue());
|
||||
}
|
||||
throw new IllegalStateException("String literal expected, but was " + value);
|
||||
}
|
||||
|
||||
public Renderer readRenderer(Element root) throws InvalidDataException {
|
||||
if (root == null) {
|
||||
return null;
|
||||
|
||||
@@ -367,6 +367,7 @@ debugger.evaluate.single.threaded.timeout=1000
|
||||
debugger.evaluate.single.threaded.timeout.description=Number of milliseconds to evaluate resuming only the current thread, then resume all threads
|
||||
debugger.call.tracing=false
|
||||
debugger.call.tracing.arguments=true
|
||||
debugger.renderers.annotations=false
|
||||
|
||||
execution.java.always.debug=false
|
||||
execution.java.always.debug.description=Always run java processes with the debug agent
|
||||
|
||||
Reference in New Issue
Block a user