Skip to content

Commit 7551692

Browse files
committed
Adding a setting to switch inline values on/off.
1 parent 93ca0a7 commit 7551692

File tree

7 files changed

+175
-84
lines changed

7 files changed

+175
-84
lines changed

ide/editor.actions/src/org/netbeans/modules/editor/actions/ShowInlineHintsAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
@EditorActionRegistration(name="toggle-inline-hints",
2626
menuPath="View",
27-
menuPosition=899,
27+
menuPosition=897,
2828
preferencesKey=ShowInlineHintsAction.KEY_LINES,
2929
preferencesDefault=ShowInlineHintsAction.DEF_LINES)
3030
public class ShowInlineHintsAction extends AbstractAction {

ide/editor.actions/src/org/netbeans/modules/editor/actions/ShowLinesAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
@EditorActionRegistration(name="toggle-lines-view",
2626
menuPath="View",
27-
menuPosition=898,
27+
menuPosition=895,
2828
preferencesKey=ShowLinesAction.KEY_LINES,
2929
preferencesDefault=ShowLinesAction.DEF_LINES)
3030
public class ShowLinesAction extends AbstractAction {

ide/spi.debugger.ui/apichanges.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,25 @@
5151
<!-- ACTUAL CHANGES BEGIN HERE: -->
5252

5353
<changes>
54+
<change id="inline-values-setting-keys">
55+
<api name="DebuggerCoreSPI"/>
56+
<summary><code>Constants</code> class enhanced with constants for inline values.</summary>
57+
<version major="2" minor="87"/>
58+
<date day="8" month="4" year="2025"/>
59+
<author login="jlahoda"/>
60+
<compatibility binary="compatible" source="compatible" modification="yes" semantic="compatible"/>
61+
<description>
62+
<p>
63+
Two new contants are added to <code>Constants</code>:
64+
<ul>
65+
<li><b>KEY_INLINE_VALUES</b>: the <code>Preferences</code> key for the inline value setting.</li>
66+
<li><b>DEF_INLINE_VALUES</b>: the default value of the inline value setting.</li>
67+
</ul>
68+
</p>
69+
</description>
70+
<class package="org.netbeans.spi.debugger.ui" name="Constants"/>
71+
</change>
72+
5473
<change id="annotation-to-breakpoint">
5574
<api name="DebuggerCoreSPI"/>
5675
<summary><code>BreakpointAnnotation</code> class added.</summary>

ide/spi.debugger.ui/manifest.mf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ Manifest-Version: 1.0
22
OpenIDE-Module: org.netbeans.spi.debugger.ui/1
33
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/debugger/ui/Bundle.properties
44
OpenIDE-Module-Layer: org/netbeans/modules/debugger/resources/mf-layer.xml
5-
OpenIDE-Module-Specification-Version: 2.86
5+
OpenIDE-Module-Specification-Version: 2.87
66
OpenIDE-Module-Provides: org.netbeans.spi.debugger.ui
77
OpenIDE-Module-Install: org/netbeans/modules/debugger/ui/DebuggerModule.class
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.netbeans.modules.debugger.ui.actions;
20+
21+
import java.awt.event.ActionEvent;
22+
import javax.swing.AbstractAction;
23+
import org.netbeans.api.editor.EditorActionRegistration;
24+
import org.netbeans.spi.debugger.ui.Constants;
25+
import org.openide.util.NbBundle.Messages;
26+
27+
@EditorActionRegistration(name="toggle-inline-values",
28+
menuPath="View",
29+
menuPosition=899,
30+
preferencesKey=Constants.KEY_INLINE_VALUES,
31+
preferencesDefault=Constants.DEF_INLINE_VALUES)
32+
@Messages({
33+
"toggle-inline-values=Show Inline Values",
34+
"toggle-inline-values_menu_text=Show Inline V&alues"
35+
})
36+
public class ShowInlineValuesAction extends AbstractAction {
37+
@Override
38+
public void actionPerformed(ActionEvent e) {
39+
}
40+
41+
}

ide/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/Constants.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,16 @@ public interface Constants {
149149
* @see org.netbeans.spi.viewmodel.ColumnModel#getNextColumnID
150150
*/
151151
public static final String SESSION_LANGUAGE_COLUMN_ID = "SessionLanguage";
152+
153+
/**Should the inline values be visible - preferences key.
154+
*
155+
* @since 2.87
156+
*/
157+
public static final String KEY_INLINE_VALUES = "enable.inline.values";
158+
159+
/**Should the inline values be visible - default value.
160+
*
161+
* @since 2.87
162+
*/
163+
public static final boolean DEF_INLINE_VALUES = true;
152164
}

java/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/models/InlineValueComputerImpl.java

Lines changed: 100 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
import java.util.function.Consumer;
3737
import java.util.logging.Level;
3838
import java.util.logging.Logger;
39+
import java.util.prefs.PreferenceChangeEvent;
40+
import java.util.prefs.PreferenceChangeListener;
41+
import java.util.prefs.Preferences;
3942
import java.util.stream.Collectors;
4043
import javax.swing.text.AttributeSet;
4144
import javax.swing.text.Document;
@@ -48,6 +51,7 @@
4851
import org.netbeans.api.debugger.jpda.JPDADebugger;
4952
import org.netbeans.api.debugger.jpda.ObjectVariable;
5053
import org.netbeans.api.debugger.jpda.Variable;
54+
import org.netbeans.api.editor.mimelookup.MimeLookup;
5155
import org.netbeans.api.editor.mimelookup.MimeRegistration;
5256
import org.netbeans.api.editor.settings.AttributesUtilities;
5357
import org.netbeans.api.java.source.CancellableTask;
@@ -68,6 +72,7 @@
6872
import org.netbeans.modules.parsing.spi.TaskIndexingMode;
6973
import org.netbeans.spi.debugger.ContextProvider;
7074
import org.netbeans.spi.debugger.DebuggerServiceRegistration;
75+
import org.netbeans.spi.debugger.ui.Constants;
7176
import org.netbeans.spi.editor.highlighting.HighlightsLayer;
7277
import org.netbeans.spi.editor.highlighting.HighlightsLayerFactory;
7378
import org.netbeans.spi.editor.highlighting.HighlightsSequence;
@@ -79,22 +84,26 @@
7984
import org.openide.util.Exceptions;
8085
import org.openide.util.Lookup;
8186
import org.openide.util.RequestProcessor;
87+
import org.openide.util.WeakListeners;
8288
import org.openide.util.lookup.ServiceProvider;
8389
import org.openide.util.lookup.ServiceProviders;
8490

8591

8692
@DebuggerServiceRegistration(path="netbeans-JPDASession/inlineValue", types=InlineValueComputer.class)
87-
public class InlineValueComputerImpl implements InlineValueComputer, PropertyChangeListener {
93+
public class InlineValueComputerImpl implements InlineValueComputer, PreferenceChangeListener, PropertyChangeListener {
8894

8995
private static final Logger LOG = Logger.getLogger(InlineValueComputerImpl.class.getName());
9096
private static final RequestProcessor EVALUATOR = new RequestProcessor(InlineValueComputerImpl.class.getName(), 1, false, false);
9197
private static final String JAVA_STRATUM = "Java"; //XXX: this is probably already defined somewhere
9298
private final JPDADebuggerImpl debugger;
99+
private final Preferences prefs;
93100
private TaskDescription currentTask;
94101

95102
public InlineValueComputerImpl(ContextProvider contextProvider) {
96103
debugger = (JPDADebuggerImpl) contextProvider.lookupFirst(null, JPDADebugger.class);
97104
debugger.addPropertyChangeListener(this);
105+
prefs = MimeLookup.getLookup("text/x-java").lookup(Preferences.class);
106+
prefs.addPreferenceChangeListener(WeakListeners.create(PreferenceChangeListener.class, this, prefs));
98107
}
99108

100109
@Override
@@ -105,108 +114,118 @@ public void propertyChange(PropertyChangeEvent evt) {
105114
}
106115

107116
if (JPDADebugger.PROP_CURRENT_CALL_STACK_FRAME.equals(evt.getPropertyName())) {
108-
CallStackFrame frame = debugger.getCurrentCallStackFrame();
117+
refreshVariables();
118+
}
119+
}
109120

110-
FileObject frameFile = null;
111-
int frameLineNumber = -1;
112-
Document frameDocument = null;
121+
@Override
122+
public void preferenceChange(PreferenceChangeEvent evt) {
123+
refreshVariables();
124+
}
113125

114-
if (frame != null && !frame.isObsolete() &&
115-
frame.getThread().isSuspended() &&
116-
JAVA_STRATUM.equals(frame.getDefaultStratum())) {
117-
try {
118-
String url = debugger.getEngineContext().getURL(frame, JAVA_STRATUM);
119-
frameFile = url != null ? URLMapper.findFileObject(URI.create(url).toURL()) : null;
120-
if (frameFile != null) {
121-
frameLineNumber = frame.getLineNumber(JAVA_STRATUM);
122-
EditorCookie ec = frameFile.getLookup().lookup(EditorCookie.class);
123-
frameDocument = ec != null ? ec.getDocument() : null;
124-
}
125-
} catch (InternalExceptionWrapper | InvalidStackFrameExceptionWrapper | ObjectCollectedExceptionWrapper | VMDisconnectedExceptionWrapper | MalformedURLException ex) {
126-
Exceptions.printStackTrace(ex);
126+
private void refreshVariables() {
127+
CallStackFrame frame = debugger.getCurrentCallStackFrame();
128+
129+
FileObject frameFile = null;
130+
int frameLineNumber = -1;
131+
Document frameDocument = null;
132+
133+
if (prefs.getBoolean(Constants.KEY_INLINE_VALUES, Constants.DEF_INLINE_VALUES) &&
134+
frame != null && !frame.isObsolete() &&
135+
frame.getThread().isSuspended() &&
136+
JAVA_STRATUM.equals(frame.getDefaultStratum())) {
137+
try {
138+
String url = debugger.getEngineContext().getURL(frame, JAVA_STRATUM);
139+
frameFile = url != null ? URLMapper.findFileObject(URI.create(url).toURL()) : null;
140+
if (frameFile != null) {
141+
frameLineNumber = frame.getLineNumber(JAVA_STRATUM);
142+
EditorCookie ec = frameFile.getLookup().lookup(EditorCookie.class);
143+
frameDocument = ec != null ? ec.getDocument() : null;
127144
}
145+
} catch (InternalExceptionWrapper | InvalidStackFrameExceptionWrapper | ObjectCollectedExceptionWrapper | VMDisconnectedExceptionWrapper | MalformedURLException ex) {
146+
Exceptions.printStackTrace(ex);
128147
}
148+
}
129149

130-
TaskDescription newTask;
150+
TaskDescription newTask;
131151

132-
if (frameFile != null && frameDocument != null) {
133-
newTask = new TaskDescription(frameFile, frameLineNumber, frameDocument);
134-
} else {
135-
newTask = null;
136-
}
152+
if (frameFile != null && frameDocument != null) {
153+
newTask = new TaskDescription(frameFile, frameLineNumber, frameDocument);
154+
} else {
155+
newTask = null;
156+
}
137157

138-
if (setNewTask(newTask)) {
139-
return;
140-
}
158+
if (setNewTask(newTask)) {
159+
return;
160+
}
141161

142-
if (newTask != null) {
143-
//TODO: cancel any already running computation if the configuration is different:
144-
CountDownLatch computationDone = new CountDownLatch(1);
162+
if (newTask != null) {
163+
//TODO: cancel any already running computation if the configuration is different:
164+
CountDownLatch computationDone = new CountDownLatch(1);
145165

146-
newTask.addCancelCallback(computationDone::countDown);
166+
newTask.addCancelCallback(computationDone::countDown);
147167

148-
AtomicReference<Collection<InlineVariable>> values = new AtomicReference<>();
168+
AtomicReference<Collection<InlineVariable>> values = new AtomicReference<>();
149169

150-
EVALUATOR.post(() -> {
151-
OffsetsBag runningBag = new OffsetsBag(newTask.frameDocument);
170+
EVALUATOR.post(() -> {
171+
OffsetsBag runningBag = new OffsetsBag(newTask.frameDocument);
152172

153-
Lookup.getDefault().lookup(ComputeInlineVariablesFactory.class).set(newTask.frameFile, newTask.frameLineNumber, variables -> {
154-
values.set(variables);
155-
computationDone.countDown();
156-
});
173+
Lookup.getDefault().lookup(ComputeInlineVariablesFactory.class).set(newTask.frameFile, newTask.frameLineNumber, variables -> {
174+
values.set(variables);
175+
computationDone.countDown();
176+
});
157177

158-
try {
159-
computationDone.await();
160-
} catch (InterruptedException ex) {
161-
Exceptions.printStackTrace(ex);
162-
}
178+
try {
179+
computationDone.await();
180+
} catch (InterruptedException ex) {
181+
Exceptions.printStackTrace(ex);
182+
}
163183

164-
if (newTask.isCancelled()) {
165-
return ;
166-
}
184+
if (newTask.isCancelled()) {
185+
return ;
186+
}
187+
188+
Collection<InlineVariable> variables = values.get();
167189

168-
Collection<InlineVariable> variables = values.get();
190+
if (values == null) {
191+
return ;
192+
}
169193

170-
if (values == null) {
194+
Map<String, Variable> expression2Value = new HashMap<>();
195+
Map<Integer, Map<String, String>> line2Values = new HashMap<>();
196+
197+
for (InlineVariable v : variables) {
198+
if (newTask.isCancelled()) {
171199
return ;
172200
}
173201

174-
Map<String, Variable> expression2Value = new HashMap<>();
175-
Map<Integer, Map<String, String>> line2Values = new HashMap<>();
176-
177-
for (InlineVariable v : variables) {
178-
if (newTask.isCancelled()) {
179-
return ;
202+
Variable value = expression2Value.computeIfAbsent(v.expression, expr -> {
203+
try {
204+
return debugger.evaluate(expr);
205+
} catch (InvalidExpressionException ex) {
206+
//the variable may not exist
207+
LOG.log(Level.FINE, null, ex);
208+
return null;
180209
}
181-
182-
Variable value = expression2Value.computeIfAbsent(v.expression, expr -> {
183-
try {
184-
return debugger.evaluate(expr);
185-
} catch (InvalidExpressionException ex) {
186-
//the variable may not exist
187-
LOG.log(Level.FINE, null, ex);
188-
return null;
189-
}
190-
});
191-
if (value != null) {
192-
String valueText;
193-
if (value instanceof ObjectVariable ov) {
194-
valueText = toValue(ov).replace("\n", "\\n");
195-
} else {
196-
valueText = value.getValue();
197-
}
198-
line2Values.computeIfAbsent(v.lineEnd, __ -> new LinkedHashMap<>())
199-
.putIfAbsent(v.expression, v.expression + " = " + valueText);
200-
String mergedValues = line2Values.get(v.lineEnd).values().stream().collect(Collectors.joining(", ", " ", ""));
201-
AttributeSet attrs = AttributesUtilities.createImmutable("virtual-text-prepend", mergedValues);
202-
203-
runningBag.addHighlight(v.lineEnd, v.lineEnd + 1, attrs);
204-
205-
setHighlights(newTask, runningBag);
210+
});
211+
if (value != null) {
212+
String valueText;
213+
if (value instanceof ObjectVariable ov) {
214+
valueText = toValue(ov).replace("\n", "\\n");
215+
} else {
216+
valueText = value.getValue();
206217
}
218+
line2Values.computeIfAbsent(v.lineEnd, __ -> new LinkedHashMap<>())
219+
.putIfAbsent(v.expression, v.expression + " = " + valueText);
220+
String mergedValues = line2Values.get(v.lineEnd).values().stream().collect(Collectors.joining(", ", " ", ""));
221+
AttributeSet attrs = AttributesUtilities.createImmutable("virtual-text-prepend", mergedValues);
222+
223+
runningBag.addHighlight(v.lineEnd, v.lineEnd + 1, attrs);
224+
225+
setHighlights(newTask, runningBag);
207226
}
208-
});
209-
}
227+
}
228+
});
210229
}
211230
}
212231

0 commit comments

Comments
 (0)