• 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

79.78
/plugin/backend/src/main/java/com/perl5/lang/perl/idea/codeInsight/PerlParameterInfoHandler.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.idea.codeInsight;
18

19
import com.intellij.lang.parameterInfo.*;
20
import com.intellij.openapi.util.Ref;
21
import com.intellij.psi.PsiElement;
22
import com.intellij.psi.tree.IElementType;
23
import com.intellij.psi.util.PsiUtilCore;
24
import com.perl5.lang.perl.lexer.PerlTokenSets;
25
import com.perl5.lang.perl.psi.*;
26
import com.perl5.lang.perl.psi.impl.PerlCompositeElementImpl;
27
import com.perl5.lang.perl.psi.impl.PsiPerlCallArgumentsImpl;
28
import com.perl5.lang.perl.psi.impl.PsiPerlCommaSequenceExprImpl;
29
import com.perl5.lang.perl.psi.impl.PsiPerlParenthesisedExprImpl;
30
import com.perl5.lang.perl.psi.mixins.PerlMethodMixin;
31
import com.perl5.lang.perl.psi.references.PerlImplicitDeclarationsService;
32
import com.perl5.lang.perl.psi.utils.PerlContextType;
33
import com.perl5.lang.perl.psi.utils.PerlPsiUtil;
34
import com.perl5.lang.perl.psi.utils.PerlResolveUtilCore;
35
import com.perl5.lang.perl.util.PerlContextUtil;
36
import org.jetbrains.annotations.NotNull;
37
import org.jetbrains.annotations.Nullable;
38

39
import static com.perl5.lang.perl.parser.PerlElementTypesGenerated.*;
40

41

42
public class PerlParameterInfoHandler implements ParameterInfoHandler<PsiPerlCallArgumentsImpl, PerlParameterInfo> {
1✔
43
  @Override
44
  public @Nullable PsiPerlCallArgumentsImpl findElementForParameterInfo(@NotNull CreateParameterInfoContext context) {
45
    PsiPerlCallArgumentsImpl callArguments = findCallArguments(context);
1✔
46

47
    if (callArguments != null) {
1✔
48
      PerlParameterInfo[] methodParameterInfos = getMethodCallArguments(callArguments);
1✔
49
      if (methodParameterInfos == null || methodParameterInfos.length == 0) {
1!
50
        return null;
1✔
51
      }
52
      markActiveParameters(callArguments, methodParameterInfos, context.getOffset());
1✔
53
      context.setItemsToShow(methodParameterInfos);
1✔
54
    }
55

56
    return callArguments;
1✔
57
  }
58

59
  @Override
60
  public void showParameterInfo(@NotNull PsiPerlCallArgumentsImpl container, @NotNull CreateParameterInfoContext context) {
61
    context.showHint(container, container.getTextOffset(), this);
×
62
  }
×
63

64
  @Override
65
  public @Nullable PsiPerlCallArgumentsImpl findElementForUpdatingParameterInfo(@NotNull UpdateParameterInfoContext context) {
66
    return findCallArguments(context);
×
67
  }
68

69
  @Override
70
  public void updateParameterInfo(@NotNull PsiPerlCallArgumentsImpl container, @NotNull UpdateParameterInfoContext context) {
71
    markActiveParameters(container, (PerlParameterInfo[])context.getObjectsToView(), context.getOffset());
×
72
  }
×
73

74
  @Override
75
  public void updateUI(PerlParameterInfo parameterInfo, @NotNull ParameterInfoUIContext context) {
76
    parameterInfo.setUpUIPresentation(context);
×
77
  }
×
78

79
  /**
80
   * Method marks parameters as active/inactive
81
   *
82
   * @param container      arguments container
83
   * @param parameterInfos array of parameter infos
84
   */
85
  private static void markActiveParameters(@NotNull PsiPerlCallArgumentsImpl container, PerlParameterInfo[] parameterInfos, int offset) {
86
    for (PerlParameterInfo parameterInfo : parameterInfos) {
1✔
87
      parameterInfo.setSelected(false);
1✔
88
    }
89

90
    markActiveparametersRecursively(container.getFirstChild(), parameterInfos, 0, offset);
1✔
91
  }
1✔
92

93
  private static int markActiveparametersRecursively(PsiElement element, PerlParameterInfo[] parameterInfos, int currentIndex, int offset) {
94
    while (element != null) {
1✔
95
      if (parameterInfos.length <= currentIndex) {
1!
96
        return currentIndex;
×
97
      }
98

99
      IElementType elementType = PsiUtilCore.getElementType(element);
1✔
100
      if (element instanceof PsiPerlParenthesisedExprImpl || element instanceof PsiPerlCommaSequenceExprImpl) {
1!
101
        currentIndex = markActiveparametersRecursively(element.getFirstChild(), parameterInfos, currentIndex, offset);
1✔
102
      }
103
      else {
104
        if (isComma(elementType)) {
1✔
105
          if (parameterInfos[currentIndex].getArgument().getContextType() == PerlContextType.SCALAR) {
1✔
106
            currentIndex++;
1✔
107
          }
108
        }
109
      }
110

111
      if (element.getTextRange().getEndOffset() >= offset) {
1✔
112
        if (element instanceof PerlCompositeElementImpl) {
1✔
113
          PerlContextType valueContextType = PerlContextUtil.contextFrom(element);
1✔
114

115
          if (valueContextType == PerlContextType.SCALAR) {
1✔
116
            if (currentIndex < parameterInfos.length) {
1!
117
              parameterInfos[currentIndex].setSelected(true);
1✔
118
            }
119
            return parameterInfos.length;
1✔
120
          }
121
          else if (valueContextType == PerlContextType.LIST) // consumes all arguments to the end
1!
122
          {
123
            while (currentIndex < parameterInfos.length) {
1!
124
              parameterInfos[currentIndex++].setSelected(true);
×
125
            }
126
            return currentIndex;
1✔
127
          }
128
        }
129

130
        // space, comma or smth
131
        if (currentIndex < parameterInfos.length) {
1!
132
          parameterInfos[currentIndex].setSelected(true);
1✔
133
        }
134
        return parameterInfos.length;
1✔
135
      }
136
      else if (elementType == SUB_EXPR && element.getFirstChild() instanceof PsiPerlBlock) {
1!
137
        PsiElement nextSibling = PerlPsiUtil.getNextSignificantSibling(element);
1✔
138
        if (!isComma(PsiUtilCore.getElementType(nextSibling))) {
1✔
139
          currentIndex++;
1✔
140
        }
141
      }
1✔
142
      else if (isPrintHandleArgument(element)) {
1✔
143
        currentIndex++;
1✔
144
      }
145

146
      element = element.getNextSibling();
1✔
147
    }
1✔
148
    return currentIndex;
1✔
149
  }
150

151
  private static boolean isPrintHandleArgument(@NotNull PsiElement psiElement) {
152
    IElementType elementType = PsiUtilCore.getElementType(psiElement);
1✔
153
    if (elementType != BLOCK && elementType != PERL_HANDLE_EXPR && elementType != SCALAR_VARIABLE) {
1!
154
      return false;
1✔
155
    }
156
    PsiElement parent = psiElement.getParent();
1✔
157
    if (!(parent instanceof PsiPerlCommaSequenceExpr)) {
1!
158
      return false;
×
159
    }
160

161
    PsiElement grandParent = parent.getParent();
1✔
162
    if (!(grandParent instanceof PsiPerlCallArguments)) {
1!
163
      return false;
×
164
    }
165

166
    if (!(grandParent.getParent() instanceof PsiPerlPrintExpr)) {
1!
167
      return false;
×
168
    }
169

170
    PsiElement nextSibling = PerlPsiUtil.getNextSignificantSibling(psiElement);
1✔
171
    return !isComma(PsiUtilCore.getElementType(nextSibling));
1!
172
  }
173

174
  private static boolean isComma(IElementType elementType) {
175
    return elementType == FAT_COMMA || elementType == COMMA;
1✔
176
  }
177

178
  private static @Nullable PsiPerlCallArgumentsImpl findCallArguments(ParameterInfoContext context) {
179
    PsiPerlCallArgumentsImpl callArguments =
1✔
180
      ParameterInfoUtils.findParentOfType(context.getFile(), context.getOffset(), PsiPerlCallArgumentsImpl.class);
1✔
181
    if (callArguments != null || context.getOffset() == 0) {
1✔
182
      return callArguments;
1✔
183
    }
184

185
    callArguments = ParameterInfoUtils.findParentOfType(context.getFile(), context.getOffset() - 1, PsiPerlCallArgumentsImpl.class);
1✔
186
    if (callArguments != null) {
1✔
187
      return callArguments;
1✔
188
    }
189

190
    return ParameterInfoUtils.findParentOfType(context.getFile(), context.getOffset() + 1, PsiPerlCallArgumentsImpl.class);
1✔
191
  }
192

193
  private static PerlParameterInfo @Nullable [] getTargetParameterInfo(@Nullable PsiElement target) {
194
    if (!(target instanceof PerlSubDefinitionElement subDefinitionElement)) {
1!
195
      return null;
×
196
    }
197
    return PerlParameterInfo.wrapArguments(subDefinitionElement.getSubArgumentsListWithoutSelf());
1✔
198
  }
199

200
  private static PerlParameterInfo @Nullable [] getMethodCallArguments(@NotNull PsiPerlCallArgumentsImpl arguments) {
201
    PsiElement run = arguments.getPrevSibling();
1✔
202
    while (run != null) {
1!
203
      if (run instanceof PerlMethodMixin methodMixin) {
1✔
204
        PerlSubNameElement subNameElement = methodMixin.getSubNameElement();
1✔
205
        if (subNameElement == null) {
1!
206
          break;
×
207
        }
208

209
        Ref<PerlParameterInfo[]> parameterInfoRef = Ref.create();
1✔
210

211
        PerlResolveUtilCore.processResolveTargets((target, reference) -> {
1✔
212
          PerlParameterInfo[] parameterInfos = getTargetParameterInfo(target);
1✔
213
          if (parameterInfos != null) {
1!
214
            parameterInfoRef.set(parameterInfos);
1✔
215
            return false;
1✔
216
          }
217
          return true;
×
218
        }, subNameElement);
219

220
        if (!parameterInfoRef.isNull()) {
1!
221
          return parameterInfoRef.get();
1✔
222
        }
223
      }
×
224
      else if (PerlTokenSets.CUSTOM_EXPR_KEYWORDS.contains(PsiUtilCore.getElementType(run))) {
1✔
225
        return getTargetParameterInfo(PerlImplicitDeclarationsService.getInstance(run.getProject()).getCoreSub(run.getText()));
1✔
226
      }
227
      run = run.getPrevSibling();
1✔
228
    }
229
    return null;
×
230
  }
231
}
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