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

Camelcade / Perl5-IDEA / #525521660

24 Aug 2025 01:28PM UTC coverage: 75.89% (-6.3%) from 82.227%
#525521660

push

github

hurricup
Migrated coverage reporting to https://github.com/nbaztec/coveralls-jacoco-gradle-plugin

See: https://github.com/kt3k/coveralls-gradle-plugin/issues/119

14751 of 22639 branches covered (65.16%)

Branch coverage included in aggregate %.

31091 of 37767 relevant lines covered (82.32%)

0.82 hits per line

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

69.67
/plugin/debugger/src/main/java/com/perl5/lang/perl/debugger/values/PerlXNamedValue.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.values;
18

19
import com.intellij.openapi.application.ReadAction;
20
import com.intellij.openapi.editor.Document;
21
import com.intellij.openapi.project.Project;
22
import com.intellij.openapi.util.text.StringUtil;
23
import com.intellij.openapi.vfs.VirtualFile;
24
import com.intellij.psi.PsiElement;
25
import com.intellij.psi.PsiFile;
26
import com.intellij.psi.PsiManager;
27
import com.intellij.psi.ResolveState;
28
import com.intellij.util.ThreeState;
29
import com.intellij.xdebugger.XSourcePosition;
30
import com.intellij.xdebugger.frame.*;
31
import com.intellij.xdebugger.impl.XSourcePositionImpl;
32
import com.perl5.PerlIcons;
33
import com.perl5.lang.perl.debugger.PerlDebugUtil;
34
import com.perl5.lang.perl.debugger.PerlStackFrame;
35
import com.perl5.lang.perl.debugger.protocol.PerlLayersDescriptor;
36
import com.perl5.lang.perl.debugger.protocol.PerlValueDescriptor;
37
import com.perl5.lang.perl.psi.PerlVariable;
38
import com.perl5.lang.perl.psi.PerlVariableDeclarationElement;
39
import com.perl5.lang.perl.psi.impl.PerlFileImpl;
40
import com.perl5.lang.perl.psi.references.scopes.PerlVariableDeclarationSearcher;
41
import com.perl5.lang.perl.psi.utils.PerlResolveUtilCore;
42
import com.perl5.lang.perl.psi.utils.PerlVariableType;
43
import org.jetbrains.annotations.NotNull;
44
import org.jetbrains.annotations.Nullable;
45

46
import javax.swing.*;
47

48

49
public class PerlXNamedValue extends XNamedValue implements PerlLoadableXValueContainer {
50
  private final PerlStackFrame myStackFrame;
51
  private final PerlValueDescriptor myPerlValueDescriptor;
52
  private int myOffset = 0;
1✔
53

54
  public PerlXNamedValue(@NotNull PerlValueDescriptor descriptor, PerlStackFrame stackFrame) {
55
    super(descriptor.getName());
1✔
56
    myPerlValueDescriptor = descriptor;
1✔
57
    myStackFrame = stackFrame;
1✔
58
  }
1✔
59

60
  @Override
61
  public void computeChildren(@NotNull XCompositeNode node) {
62
    boolean isExpandable = myPerlValueDescriptor.isExpandable();
1✔
63
    PerlLayersDescriptor layers = myPerlValueDescriptor.getLayers();
1✔
64
    PerlValueDescriptor tiedWith = myPerlValueDescriptor.getTiedWith();
1✔
65
    if (!isExpandable && layers == null && tiedWith == null || StringUtil.isEmpty(myPerlValueDescriptor.getKey())) {
1!
66
      super.computeChildren(node);
×
67
    }
68

69
    XValueChildrenList childrenList = new XValueChildrenList();
1✔
70
    if (layers != null) {
1✔
71
      childrenList.add(new PerlXLayersNamedValue(layers));
1✔
72
    }
73

74
    if (tiedWith != null) {
1✔
75
      childrenList.addTopGroup(new PerlTiedNamedValue(tiedWith, myStackFrame));
1✔
76
    }
77

78
    node.addChildren(childrenList, !isExpandable);
1✔
79

80
    if (isExpandable) {
1✔
81
      PerlDebugUtil.requestAndComputeChildren(node, this);
1✔
82
    }
83
  }
1✔
84

85
  @Override
86
  public @NotNull PerlStackFrame getStackFrame() {
87
    return myStackFrame;
1!
88
  }
89

90
  @Override
91
  public @NotNull String getDataKey() {
92
    return myPerlValueDescriptor.getKey();
1!
93
  }
94

95
  @Override
96
  public int getCurrentOffset() {
97
    return myOffset;
1✔
98
  }
99

100
  @Override
101
  public int getSize() {
102
    return myPerlValueDescriptor.getSize();
1✔
103
  }
104

105
  @Override
106
  public void incCurrentOffset() {
107
    myOffset++;
1✔
108
  }
1✔
109

110
  @Override
111
  public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) {
112
    node.setPresentation(calculateIcon(), computeType(), computeValue(), myPerlValueDescriptor.isExpandableNode());
1✔
113
  }
1✔
114

115
  private String computeValue() {
116
    String value = myPerlValueDescriptor.getValue();
1✔
117

118
    String rendered = myPerlValueDescriptor.getRendered();
1✔
119
    return StringUtil.isEmpty(rendered) ? value : rendered + " (" + value + ")";
1✔
120
  }
121

122
  protected String computeType() {
123
    String type = myPerlValueDescriptor.getType();
1✔
124

125
    int refDepth = myPerlValueDescriptor.getRefDepth();
1✔
126
    if (refDepth == 1) {
1✔
127
      type = "REF to " + type;
1✔
128
    }
129
    else if (refDepth > 0) {
1!
130
      type = "REF(" + refDepth + ") to " + type;
×
131
    }
132

133
    if (myPerlValueDescriptor.getLayers() != null) {
1✔
134
      type += ", IOLayers";
1✔
135
    }
136

137
    if (myPerlValueDescriptor.getTiedWith() != null) {
1✔
138
      type += ", Tied";
1✔
139
    }
140

141
    if (myPerlValueDescriptor.getFileno() != null) {
1✔
142
      type += ", fileno: " + myPerlValueDescriptor.getFileno();
1✔
143
    }
144

145
    return type;
1✔
146
  }
147

148
  protected @Nullable Icon calculateIcon() {
149
    String type = myPerlValueDescriptor.getType();
1✔
150
    if (StringUtil.isEmpty(type)) {
1!
151
      return null;
×
152
    }
153
    else if (StringUtil.startsWith(type, "SCALAR")) {
1✔
154
      return myPerlValueDescriptor.isUtf() ? PerlIcons.UTF_SCALAR_GUTTER_ICON : PerlIcons.SCALAR_GUTTER_ICON;
1✔
155
    }
156
    else if (StringUtil.startsWith(type, "ARRAY")) {
1✔
157
      return PerlIcons.ARRAY_GUTTER_ICON;
1✔
158
    }
159
    else if (StringUtil.startsWith(type, "HASH")) {
1✔
160
      return PerlIcons.HASH_GUTTER_ICON;
1✔
161
    }
162
    else if (StringUtil.startsWith(type, "CODE")) {
1✔
163
      return PerlIcons.SUB_GUTTER_ICON;
1✔
164
    }
165
    else if (StringUtil.startsWith(type, "GLOB")) {
1✔
166
      return PerlIcons.GLOB_GUTTER_ICON;
1✔
167
    }
168
    else if (StringUtil.startsWith(type, "FORMAT")) {
1✔
169
      return PerlIcons.FORMAT_GUTTER_ICON;
1✔
170
    }
171
    else if (StringUtil.startsWith(type, "IO::File")) {
1✔
172
      return PerlIcons.HANDLE_GUTTER_ICON;
1✔
173
    }
174
    else if (StringUtil.startsWith(type, "Regexp")) {
1✔
175
      return PerlIcons.REGEX_GUTTER_ICON;
1✔
176
    }
177
    else if (myPerlValueDescriptor.isBlessed()) {
1✔
178
      return PerlIcons.PACKAGE_GUTTER_ICON;
1✔
179
    }
180
    return null;
1✔
181
  }
182

183

184
  @Override
185
  public void computeSourcePosition(@NotNull XNavigatable navigatable) {
186
    if (!computeMySourcePosition(navigatable, null)) {
1✔
187
      super.computeSourcePosition(navigatable);
1✔
188
    }
189
  }
1✔
190

191
  protected boolean computeMySourcePosition(@Nullable XNavigatable navigatable, final @Nullable XInlineDebuggerDataCallback callback) {
192
    String name = myPerlValueDescriptor.getName();
1✔
193

194
    if (StringUtil.isEmpty(name) || name.length() < 2) {
1!
195
      return false;
×
196
    }
197

198
    final PerlVariableType variableType = PerlVariableType.bySigilOrNull(name.charAt(0));
1✔
199
    if (variableType == null) {
1✔
200
      return false;
1✔
201
    }
202
    if (variableType == PerlVariableType.CODE) {
1!
203
      return false;
×
204
    }
205

206
    final String variableName = name.substring(1);
1✔
207

208
    final XSourcePosition sourcePosition = myStackFrame.getSourcePosition();
1✔
209
    if (sourcePosition == null) {
1!
210
      return false;
×
211
    }
212

213
    final Project project = myStackFrame.getPerlExecutionStack().getSuspendContext().getDebugSession().getProject();
1✔
214
    final VirtualFile virtualFile = sourcePosition.getFile();
1✔
215
    PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
1✔
216

217
    if (!(psiFile instanceof PerlFileImpl)) {
1!
218
      return false;
×
219
    }
220

221
    PsiElement element = psiFile.findElementAt(sourcePosition.getOffset());
1✔
222

223
    if (element == null) {
1!
224
      return false;
×
225
    }
226

227
    if (navigatable != null) {
1!
228
      PerlVariableDeclarationSearcher variableProcessor = new PerlVariableDeclarationSearcher(variableName, variableType, element);
1✔
229
      PerlResolveUtilCore.treeWalkUp(element, variableProcessor);
1✔
230

231
      PerlVariableDeclarationElement result = variableProcessor.getResult();
1✔
232
      if (result == null) {
1!
233
        return false;
×
234
      }
235

236
      navigatable.setSourcePosition(XSourcePositionImpl.createByElement(result));
1✔
237
    }
1✔
238
    else if (callback != null) {
×
239
      final Document document = psiFile.getViewProvider().getDocument();
×
240
      if (document == null) {
×
241
        return false;
×
242
      }
243

244
      final boolean[] found = new boolean[]{false};
×
245

246
      PerlVariableDeclarationSearcher variableProcessor = new PerlVariableDeclarationSearcher(variableName, variableType, element) {
×
247
        @Override
248
        public boolean execute(@NotNull PsiElement possibleElement, @NotNull ResolveState state) {
249
          boolean result = super.execute(possibleElement, state);
×
250

251
          if (!result) {
×
252
            registerElement(getResult());
×
253
          }
254
          else if (possibleElement instanceof PerlVariable perlVariable &&
×
255
                   perlVariable.getActualType() == variableType &&
×
256
                   StringUtil.equals(variableName, perlVariable.getName())) {
×
257
            registerElement(possibleElement);
×
258
          }
259

260
          return result;
×
261
        }
262

263
        private void registerElement(@Nullable PsiElement targetElement) {
264
          if (targetElement == null) {
×
265
            return;
×
266
          }
267

268
          found[0] = true;
×
269
          callback.computed(XSourcePositionImpl.createByElement(targetElement));
×
270
        }
×
271
      };
272

273
      PerlResolveUtilCore.treeWalkUp(element, variableProcessor);
×
274
      return found[0];
×
275
    }
276
    return true;
1✔
277
  }
278

279

280
  @Override
281
  public @NotNull ThreeState computeInlineDebuggerData(@NotNull XInlineDebuggerDataCallback callback) {
282
    return ReadAction.compute(() -> computeMySourcePosition(null, callback) ? ThreeState.YES : ThreeState.NO);
×
283
  }
284
}
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