• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Camelcade / Perl5-IDEA / #525521586

19 Jun 2025 10:27AM UTC coverage: 82.376% (+0.03%) from 82.349%
#525521586

push

github

hurricup
Migrated to NioFiles.deleteRecursively

1 of 1 new or added line in 1 file covered. (100.0%)

54 existing lines in 7 files now uncovered.

30872 of 37477 relevant lines covered (82.38%)

0.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.75
/plugin/debugger/src/main/java/com/perl5/lang/perl/debugger/PerlStackFrame.java
1
/*
2
 * Copyright 2015-2025 Alexandr Evstigneev
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 * http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package com.perl5.lang.perl.debugger;
18

19
import com.google.gson.JsonDeserializationContext;
20
import com.google.gson.JsonObject;
21
import com.intellij.icons.AllIcons;
22
import com.intellij.openapi.application.ReadAction;
23
import com.intellij.openapi.util.NlsSafe;
24
import com.intellij.openapi.vfs.VfsUtil;
25
import com.intellij.openapi.vfs.VirtualFile;
26
import com.intellij.openapi.vfs.VirtualFileManager;
27
import com.intellij.ui.ColoredTextContainer;
28
import com.intellij.ui.SimpleTextAttributes;
29
import com.intellij.xdebugger.XSourcePosition;
30
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
31
import com.intellij.xdebugger.frame.XCompositeNode;
32
import com.intellij.xdebugger.frame.XStackFrame;
33
import com.intellij.xdebugger.frame.XValueChildrenList;
34
import com.intellij.xdebugger.impl.XSourcePositionImpl;
35
import com.perl5.PerlIcons;
36
import com.perl5.lang.perl.debugger.protocol.*;
37
import com.perl5.lang.perl.debugger.values.PerlXMainGroup;
38
import com.perl5.lang.perl.debugger.values.PerlXNamedValue;
39
import com.perl5.lang.perl.debugger.values.PerlXValueGroup;
40
import com.perl5.lang.perl.util.PerlPackageUtil;
41
import org.jetbrains.annotations.NotNull;
42
import org.jetbrains.annotations.Nullable;
43
import org.jetbrains.annotations.TestOnly;
44
import org.jetbrains.annotations.VisibleForTesting;
45

46
import java.io.File;
47

48

49
public class PerlStackFrame extends XStackFrame {
50
  private final @NotNull PerlStackFrameDescriptor myFrameDescriptor;
51
  private final @NotNull PerlExecutionStack myPerlExecutionStack;
52
  private final @NotNull PerlDebugThread myDebugThread;
53
  private final @Nullable VirtualFile myVirtualFile;
54

55
  public PerlStackFrame(@NotNull PerlStackFrameDescriptor frameDescriptor, @NotNull PerlExecutionStack stack) {
1✔
56
    myFrameDescriptor = frameDescriptor;
1✔
57
    myPerlExecutionStack = stack;
1✔
58
    myDebugThread = myPerlExecutionStack.getSuspendContext().getDebugThread();
1✔
59

60
    myVirtualFile = ReadAction.nonBlocking(() -> {
1✔
61
      String remoteFilePath = myFrameDescriptor.getFileDescriptor().getPath();
1✔
62
      String localFilePath = myDebugThread.getDebugProfileState().mapPathToLocal(remoteFilePath);
1✔
63
      VirtualFile result = VfsUtil.findFileByIoFile(new File(localFilePath), false);
1✔
64

65
      if (result == null) {
1✔
66
        String remoteFileUrl = PerlRemoteFileSystem.PROTOCOL_PREFIX + remoteFilePath;
1✔
67
        result = VirtualFileManager.getInstance().findFileByUrl(remoteFileUrl);
1✔
68

69
        if (result == null) {    // suppose that we need to fetch a file
1✔
70
          result = myDebugThread.loadRemoteSource(remoteFilePath);
1✔
71
        }
72
      }
73

74
      return result;
1✔
75
    }).executeSynchronously();
1✔
76

77
    PerlLoadedFileDescriptor fileDescriptor = myFrameDescriptor.getFileDescriptor();
1✔
78

79
    if (fileDescriptor.isEval()) {
1✔
80
      myDebugThread.getEvalsListPanel().add(fileDescriptor);
1✔
81
    }
82
    else {
83
      myDebugThread.getScriptListPanel().add(fileDescriptor);
1✔
84
    }
85
  }
1✔
86

87
  @Override
88
  public void customizePresentation(@NotNull ColoredTextContainer component) {
89
    doCustomizePresentation(myFrameDescriptor, component);
1✔
90
  }
1✔
91

92
  @VisibleForTesting
93
  public static void doCustomizePresentation(@NotNull PerlStackFrameDescriptor frameDescriptor, @NotNull ColoredTextContainer component) {
94
    var fileDescriptor = frameDescriptor.getFileDescriptor();
1✔
95
    var fqn = fileDescriptor.getName();
1✔
96
    var nameChunks = PerlPackageUtil.splitNames(fqn);
1✔
97
    var filePath = fileDescriptor.getPath();
1✔
98
    @NlsSafe var namespaceName = nameChunks == null ? null : nameChunks.getFirst();
1✔
99
    var subName = nameChunks == null ? null : nameChunks.getSecond();
1✔
100
    var firstName = subName == null ? filePath : subName;
1✔
101
    @NlsSafe var frameName =
1✔
102
      String.join(":", firstName, String.valueOf(frameDescriptor.getOneBasedLine()));
1✔
103
    component.append(frameName, SimpleTextAttributes.REGULAR_ATTRIBUTES);
1✔
104
    if (namespaceName != null) {
1✔
105
      component.append(", " + namespaceName, SimpleTextAttributes.REGULAR_ATTRIBUTES);
1✔
106
    }
107
    if (subName != null) {
1✔
108
      component.append(" (" + filePath + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES);
1✔
109
    }
110
    component.setIcon(AllIcons.Debugger.Frame);
1✔
111
  }
1✔
112

113
  @Override
114
  public @Nullable XSourcePosition getSourcePosition() {
115
    VirtualFile virtualFile = myVirtualFile;
1✔
116
    if (virtualFile != null) {
1✔
117
      return XSourcePositionImpl.create(virtualFile, myFrameDescriptor.getZeroBasedLine());
1✔
118
    }
119
    return super.getSourcePosition();
×
120
  }
121

122
  @Override
123
  public void computeChildren(@NotNull XCompositeNode node) {
124
    PerlValueDescriptor[] lexicals = myFrameDescriptor.getLexicals();
1✔
125
    PerlValueDescriptor[] globals = myFrameDescriptor.getGlobals();
1✔
126
    PerlValueDescriptor[] args = myFrameDescriptor.getArgs();
1✔
127
    int mainSize = myFrameDescriptor.getMainSize();
1✔
128

129
    boolean fallback = true;
1✔
130

131
    XValueChildrenList list = new XValueChildrenList();
1✔
132

133
    if (globals != null && globals.length > 0) {
1✔
134
      list.addTopGroup(new PerlXValueGroup("Global variables", "our", PerlIcons.OUR_GUTTER_ICON, globals, this, false));
1✔
135
      fallback = false;
1✔
136
    }
137
    if (mainSize > 0) {
1✔
138
      list.addTopGroup(new PerlXMainGroup(this, mainSize));
1✔
139
      fallback = false;
1✔
140
    }
141
    if (args != null && args.length > 0) {
1✔
142
      list.addTopGroup(new PerlXValueGroup("Arguments", null, PerlIcons.ARGS_GUTTER_ICON, args, this, true));
×
143
      fallback = false;
×
144
    }
145
    if (lexicals != null && lexicals.length > 0) {
1✔
146
      list.addTopGroup(new PerlXValueGroup("Lexical variables", "my/state", PerlIcons.MY_GUTTER_ICON, lexicals, this, true));
1✔
147
      fallback = false;
1✔
148
    }
149

150

151
    if (fallback) {
1✔
152
      super.computeChildren(node);
×
153
    }
154
    else {
155
      node.addChildren(list, true);
1✔
156
    }
157
  }
1✔
158

159
  public @NotNull PerlExecutionStack getPerlExecutionStack() {
160
    return myPerlExecutionStack;
1✔
161
  }
162

163
  @TestOnly
164
  public @NotNull PerlStackFrameDescriptor getFrameDescriptor() {
165
    return myFrameDescriptor;
1✔
166
  }
167

168
  @Override
169
  public @Nullable XDebuggerEvaluator getEvaluator() {
UNCOV
170
    return new XDebuggerEvaluator() {
×
171
      @Override
172
      public void evaluate(@NotNull String expression,
173
                           final @NotNull XEvaluationCallback callback,
174
                           @Nullable XSourcePosition expressionPosition) {
175
        PerlDebugThread thread = myPerlExecutionStack.getSuspendContext().getDebugThread();
×
176

177
        thread.sendCommandAndGetResponse("e", new PerlEvalRequestDescriptor(expression), new PerlDebuggingTransactionHandler() {
×
178
          @Override
179
          public void run(JsonObject jsonObject, JsonDeserializationContext jsonDeserializationContext) {
180
            PerlEvalResponseDescriptor descriptor = jsonDeserializationContext.deserialize(
×
181
              jsonObject.getAsJsonObject("data"), PerlEvalResponseDescriptor.class
×
182
            );
183

184
            if (descriptor == null) {
×
185
              callback.errorOccurred(
×
186
                PerlDebuggerBundle.message("dialog.message.something.bad.happened.on.perl.side.report.to.plugin.devs"));
×
187
            }
188
            else if (descriptor.isError()) {
×
189
              callback.errorOccurred(descriptor.getResult().getValue());
×
190
            }
191
            else {
192
              callback.evaluated(new PerlXNamedValue(descriptor.getResult(), PerlStackFrame.this));
×
193
            }
194
          }
×
195
        });
196
      }
×
197
    };
198
  }
199

200
  @Override
201
  public String toString() {
202
    return "PerlStackFrame{" +
1✔
203
           "myFrameDescriptor=" + myFrameDescriptor +
204
           ", myVirtualFile=" + myVirtualFile +
205
           '}';
206
  }
207
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc