1818 */
1919package org .netbeans .modules .debugger .jpda .ui .models ;
2020
21- import com .sun .source .tree .ClassTree ;
22- import com .sun .source .tree .IdentifierTree ;
23- import com .sun .source .tree .LambdaExpressionTree ;
24- import com .sun .source .tree .LineMap ;
25- import com .sun .source .tree .Tree ;
26- import static com .sun .source .tree .Tree .Kind .BLOCK ;
27- import static com .sun .source .tree .Tree .Kind .LAMBDA_EXPRESSION ;
28- import static com .sun .source .tree .Tree .Kind .METHOD ;
29- import com .sun .source .tree .VariableTree ;
30- import com .sun .source .util .TreePath ;
3121import java .beans .PropertyChangeEvent ;
3222import java .beans .PropertyChangeListener ;
33- import java .io .IOException ;
3423import java .net .MalformedURLException ;
3524import java .net .URI ;
3625import java .util .ArrayList ;
4130import java .util .List ;
4231import java .util .Map ;
4332import java .util .Objects ;
44- import java .util .concurrent .CompletableFuture ;
4533import java .util .concurrent .CountDownLatch ;
4634import java .util .concurrent .atomic .AtomicBoolean ;
4735import java .util .concurrent .atomic .AtomicReference ;
4836import java .util .function .Consumer ;
37+ import java .util .logging .Level ;
4938import java .util .logging .Logger ;
5039import java .util .stream .Collectors ;
51- import javax .lang .model .element .Element ;
52- import javax .lang .model .element .ElementKind ;
5340import javax .swing .text .AttributeSet ;
5441import javax .swing .text .Document ;
5542import org .netbeans .api .debugger .DebuggerManagerAdapter ;
6552import org .netbeans .api .editor .settings .AttributesUtilities ;
6653import org .netbeans .api .java .source .CancellableTask ;
6754import org .netbeans .api .java .source .CompilationInfo ;
68- import org .netbeans .api .java .source .JavaSource ;
6955import org .netbeans .api .java .source .JavaSource .Phase ;
7056import org .netbeans .api .java .source .JavaSource .Priority ;
7157import org .netbeans .api .java .source .JavaSourceTaskFactory ;
72- import org .netbeans .api .java .source .TreeUtilities ;
73- import org .netbeans .api .java .source .support .CancellableTreePathScanner ;
74- import org .netbeans .api .lsp .InlineValue ;
75- import org .netbeans .api .lsp .Range ;
7658import org .netbeans .modules .debugger .jpda .JPDADebuggerImpl ;
7759import org .netbeans .modules .debugger .jpda .expr .formatters .Formatters ;
7860import org .netbeans .modules .debugger .jpda .expr .formatters .FormattersLoopControl ;
8163import org .netbeans .modules .debugger .jpda .jdi .InvalidStackFrameExceptionWrapper ;
8264import org .netbeans .modules .debugger .jpda .jdi .ObjectCollectedExceptionWrapper ;
8365import org .netbeans .modules .debugger .jpda .jdi .VMDisconnectedExceptionWrapper ;
66+ import org .netbeans .modules .debugger .jpda .ui .values .ComputeInlineValues ;
67+ import org .netbeans .modules .debugger .jpda .ui .values .ComputeInlineValues .InlineVariable ;
8468import org .netbeans .modules .parsing .spi .TaskIndexingMode ;
8569import org .netbeans .spi .debugger .ContextProvider ;
8670import org .netbeans .spi .debugger .DebuggerServiceRegistration ;
8771import org .netbeans .spi .editor .highlighting .HighlightsLayer ;
8872import org .netbeans .spi .editor .highlighting .HighlightsLayerFactory ;
73+ import org .netbeans .spi .editor .highlighting .HighlightsSequence ;
8974import org .netbeans .spi .editor .highlighting .ZOrder ;
9075import org .netbeans .spi .editor .highlighting .support .OffsetsBag ;
91- import org .netbeans .spi .lsp .InlineValuesProvider ;
9276import org .openide .cookies .EditorCookie ;
9377import org .openide .filesystems .FileObject ;
9478import org .openide .filesystems .URLMapper ;
10286@ DebuggerServiceRegistration (path ="netbeans-JPDASession/inlineValue" , types =InlineValueComputer .class )
10387public class InlineValueComputerImpl implements InlineValueComputer , PropertyChangeListener {
10488
105- private static final RequestProcessor EVALUATOR = new RequestProcessor (InlineValueProviderImpl .class .getName (), 1 , false , false );
89+ private static final Logger LOG = Logger .getLogger (InlineValueComputerImpl .class .getName ());
90+ private static final RequestProcessor EVALUATOR = new RequestProcessor (InlineValueComputerImpl .class .getName (), 1 , false , false );
10691 private static final String JAVA_STRATUM = "Java" ; //XXX: this is probably already defined somewhere
10792 private final JPDADebuggerImpl debugger ;
10893 private TaskDescription currentTask ;
@@ -163,7 +148,6 @@ public void propertyChange(PropertyChangeEvent evt) {
163148 AtomicReference <Collection <InlineVariable >> values = new AtomicReference <>();
164149
165150 EVALUATOR .post (() -> {
166- OffsetsBag currentDocumentBag = getHighlightsBag (newTask .frameDocument );
167151 OffsetsBag runningBag = new OffsetsBag (newTask .frameDocument );
168152
169153 Lookup .getDefault ().lookup (ComputeInlineVariablesFactory .class ).set (newTask .frameFile , newTask .frameLineNumber , variables -> {
@@ -199,8 +183,9 @@ public void propertyChange(PropertyChangeEvent evt) {
199183 try {
200184 return debugger .evaluate (expr );
201185 } catch (InvalidExpressionException ex ) {
202- Exceptions .printStackTrace (ex );
203- return null ; //TODO: avoid re-evaluation(!)
186+ //the variable may not exist
187+ LOG .log (Level .FINE , null , ex );
188+ return null ;
204189 }
205190 });
206191 if (value != null ) {
@@ -217,10 +202,7 @@ public void propertyChange(PropertyChangeEvent evt) {
217202
218203 runningBag .addHighlight (v .lineEnd , v .lineEnd + 1 , attrs );
219204
220- if (!newTask .isCancelled ()) {
221- //TODO: a slight race condition:
222- currentDocumentBag .setHighlights (runningBag );
223- }
205+ setHighlights (newTask , runningBag );
224206 }
225207 }
226208 });
@@ -305,6 +287,12 @@ private synchronized boolean setNewTask(TaskDescription newTask) {
305287 return false ;
306288 }
307289
290+ private synchronized void setHighlights (TaskDescription task , OffsetsBag highlights ) {
291+ if (!task .isCancelled ()) {
292+ getHighlightsBag (currentTask .frameDocument ).setHighlights (highlights );
293+ }
294+ }
295+
308296 @ DebuggerServiceRegistration (types =LazyDebuggerManagerListener .class )
309297 public static final class Init extends DebuggerManagerAdapter {
310298 @ Override
@@ -353,7 +341,7 @@ public void run(CompilationInfo info) throws Exception {
353341 target = currentTarget ;
354342 }
355343
356- Collection <InlineVariable > variables = computeVariables (info , line , 1 , cancel );
344+ Collection <InlineVariable > variables = ComputeInlineValues . computeVariables (info , line , 1 , cancel );
357345
358346 target .accept (variables );
359347 }
@@ -376,99 +364,6 @@ public synchronized void set(FileObject currentFile, int lineNumber, Consumer<Co
376364 }
377365 }
378366
379- static Collection <InlineVariable > computeVariables (CompilationInfo info , int stackLine , int stackCol , AtomicBoolean cancel ) {
380- Collection <InlineVariable > result = new ArrayList <>();
381- int donePos = (int ) info .getCompilationUnit ().getLineMap ().getPosition (stackLine , stackCol );
382- int upcomingPos = (int ) info .getCompilationUnit ().getLineMap ().getStartPosition (stackLine + 1 );
383- TreePath relevantPoint = info .getTreeUtilities ().pathFor (donePos );
384- OUTER : while (relevantPoint != null ) {
385- Tree leaf = relevantPoint .getLeaf ();
386- switch (leaf .getKind ()) {
387- case METHOD : case LAMBDA_EXPRESSION : break OUTER ;
388- case BLOCK :
389- if (relevantPoint .getParentPath () != null && TreeUtilities .CLASS_TREE_KINDS .contains (relevantPoint .getParentPath ().getLeaf ().getKind ())) {
390- break OUTER ;
391- }
392- }
393- relevantPoint = relevantPoint .getParentPath ();
394- }
395- LineMap lm = info .getCompilationUnit ().getLineMap ();
396- new CancellableTreePathScanner <Void , Void >(cancel ) {
397- @ Override
398- public Void visitVariable (VariableTree node , Void p ) {
399- int end = (int ) info .getTrees ().getSourcePositions ().getEndPosition (info .getCompilationUnit (), node );
400- if (end < donePos ) {
401- int [] span = info .getTreeUtilities ().findNameSpan (node );
402-
403- if (span != null ) {
404- int lineEnd = (int ) (lm .getStartPosition (lm .getLineNumber (span [1 ]) + 1 ) - 1 );
405-
406- result .add (new InlineVariable (span [0 ], span [1 ], lineEnd , node .getName ().toString ()));
407- }
408- }
409- return super .visitVariable (node , p );
410- }
411-
412- @ Override
413- public Void visitIdentifier (IdentifierTree node , Void p ) {
414- Element el = info .getTrees ().getElement (getCurrentPath ());
415-
416- if (el != null && el .getKind ().isVariable () && el .getKind () != ElementKind .ENUM_CONSTANT ) {
417- int start = (int ) info .getTrees ().getSourcePositions ().getStartPosition (info .getCompilationUnit (), node );
418- int end = (int ) info .getTrees ().getSourcePositions ().getEndPosition (info .getCompilationUnit (), node );
419-
420- if (start != (-1 ) && end != (-1 )) {
421- int lineEnd = (int ) (lm .getStartPosition (lm .getLineNumber (end ) + 1 ) - 1 );
422-
423- result .add (new InlineVariable (start , end , lineEnd , node .getName ().toString ()));
424- }
425- }
426-
427- return super .visitIdentifier (node , p );
428- }
429-
430- @ Override
431- public Void visitClass (ClassTree node , Void p ) {
432- return null ;
433- }
434-
435- @ Override
436- public Void visitLambdaExpression (LambdaExpressionTree node , Void p ) {
437- return null ;
438- }
439-
440- @ Override
441- public Void scan (Tree tree , Void p ) {
442- if (tree != null ) {
443- int start = (int ) info .getTrees ().getSourcePositions ().getStartPosition (info .getCompilationUnit (), tree );
444-
445- if (start > upcomingPos ) {
446- return null ;
447- }
448- }
449- return super .scan (tree , p );
450- }
451-
452- }.scan (relevantPoint , null );
453-
454- return result ;
455- }
456-
457- public static final class InlineVariable {
458- public final int start ;
459- public final int end ;
460- public final int lineEnd ;
461- public final String expression ;
462-
463- public InlineVariable (int start , int end , int lineEnd , String expression ) {
464- this .start = start ;
465- this .end = end ;
466- this .lineEnd = lineEnd ;
467- this .expression = expression ;
468- }
469-
470- }
471-
472367 private static final class TaskDescription {
473368 public final FileObject frameFile ;
474369 public final int frameLineNumber ;
@@ -546,48 +441,18 @@ public static HighlightsLayerFactory createHighlightsLayerFactory() {
546441 @ Override
547442 public HighlightsLayer [] createLayers (HighlightsLayerFactory .Context context ) {
548443 return new HighlightsLayer [] {
549- HighlightsLayer .create (InlineValueProviderImpl .class .getName (), ZOrder .SYNTAX_RACK .forPosition (1400 ), false , getHighlightsBag (context .getDocument ()))
444+ HighlightsLayer .create (InlineValueComputerImpl .class .getName (), ZOrder .SYNTAX_RACK .forPosition (1400 ), false , getHighlightsBag (context .getDocument ()))
550445 };
551446 }
552447 };
553448 }
554449
555450 private static OffsetsBag getHighlightsBag (Document doc ) {
556- OffsetsBag bag = (OffsetsBag ) doc .getProperty (InlineValueProviderImpl .class );
451+ OffsetsBag bag = (OffsetsBag ) doc .getProperty (InlineValueComputerImpl .class );
557452 if (bag == null ) {
558- doc .putProperty (InlineValueProviderImpl .class , bag = new OffsetsBag (doc , true ));
453+ doc .putProperty (InlineValueComputerImpl .class , bag = new OffsetsBag (doc , true ));
559454 }
560455 return bag ;
561456 }
562457
563- @ MimeRegistration (mimeType ="text/x-java" , service =InlineValuesProvider .class )
564- public static final class InlineValueProviderImpl implements InlineValuesProvider {
565-
566- @ Override
567- public CompletableFuture <List <? extends InlineValue >> inlineValues (FileObject file , int currentExecutionPosition ) {
568- //TODO: proper cancellability
569- JavaSource js = JavaSource .forFileObject (file );
570- CompletableFuture <List <? extends InlineValue >> result = new CompletableFuture <>();
571- List <InlineValue > resultValues = new ArrayList <>();
572- if (js != null ) {
573- try {
574- js .runUserActionTask (cc -> {
575- cc .toPhase (JavaSource .Phase .RESOLVED );
576- int stackLine = (int ) cc .getCompilationUnit ().getLineMap ().getLineNumber (currentExecutionPosition );
577- int stackCol = (int ) cc .getCompilationUnit ().getLineMap ().getColumnNumber (currentExecutionPosition );
578-
579- for (InlineVariable var : computeVariables (cc , stackLine , stackCol , new AtomicBoolean ())) {
580- resultValues .add (InlineValue .createInlineVariable (new Range (var .start , var .end ), var .expression ));
581- }
582- }, true );
583- } catch (IOException ex ) {
584- result .completeExceptionally (ex );
585- return result ;
586- }
587- }
588- result .complete (resultValues );
589- return result ;
590- }
591-
592- }
593458}
0 commit comments