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

Camelcade / Perl5-IDEA / #525521553

27 May 2025 10:24AM UTC coverage: 82.286% (-0.03%) from 82.32%
#525521553

push

github

hurricup
Removed redundant implementations, moved up to the abstract class

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

128 existing lines in 30 files now uncovered.

30886 of 37535 relevant lines covered (82.29%)

0.82 hits per line

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

87.83
/plugin/core/src/main/java/com/perl5/lang/perl/idea/completion/util/PerlSubCompletionUtil.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.completion.util;
18

19
import com.intellij.codeInsight.lookup.LookupElementBuilder;
20
import com.intellij.openapi.util.text.StringUtil;
21
import com.intellij.psi.PsiElement;
22
import com.intellij.psi.PsiFile;
23
import com.intellij.psi.PsiNamedElement;
24
import com.intellij.psi.PsiReference;
25
import com.intellij.psi.util.PsiTreeUtil;
26
import com.perl5.lang.perl.extensions.packageprocessor.PerlExportDescriptor;
27
import com.perl5.lang.perl.idea.codeInsight.typeInference.value.*;
28
import com.perl5.lang.perl.idea.completion.inserthandlers.SubSelectionHandler;
29
import com.perl5.lang.perl.idea.completion.providers.processors.PerlCompletionProcessor;
30
import com.perl5.lang.perl.idea.completion.providers.processors.PerlSimpleCompletionProcessor;
31
import com.perl5.lang.perl.idea.completion.providers.processors.PerlSimpleDelegatingCompletionProcessor;
32
import com.perl5.lang.perl.idea.completion.providers.processors.PerlVariableCompletionProcessor;
33
import com.perl5.lang.perl.psi.*;
34
import com.perl5.lang.perl.psi.impl.PerlImplicitSubDefinition;
35
import com.perl5.lang.perl.psi.references.PerlImplicitDeclarationsService;
36
import com.perl5.lang.perl.util.PerlPackageUtil;
37
import org.jetbrains.annotations.NotNull;
38
import org.jetbrains.annotations.Nullable;
39

40
import java.util.Collections;
41
import java.util.HashSet;
42
import java.util.Set;
43

44

45
public class PerlSubCompletionUtil {
×
46
  public static final SubSelectionHandler SUB_SELECTION_HANDLER = new SubSelectionHandler();
1✔
47

48

49
  public static boolean processSubDefinitionLookupElement(@NotNull PerlSubDefinitionElement subDefinition,
50
                                                          @NotNull PerlCompletionProcessor completionProcessor) {
51
    return processSubDefinitionLookupElement(subDefinition, null, completionProcessor);
1✔
52
  }
53

54
  public static boolean processSubDefinitionLookupElement(@NotNull PerlSubDefinitionElement subDefinition,
55
                                                          @Nullable PerlExportDescriptor exportDescriptor,
56
                                                          @NotNull PerlCompletionProcessor completionProcessor) {
57
    return processSubDefinitionLookupElement(
1✔
58
      exportDescriptor == null ? subDefinition.getSubName() : exportDescriptor.getImportedName(),
1✔
59
      subDefinition, completionProcessor);
60
  }
61

62
  public static boolean processSubDefinitionLookupElement(@NotNull String nameToUse,
63
                                                          @NotNull PerlSubDefinitionElement subDefinition,
64
                                                          @NotNull PerlCompletionProcessor completionProcessor) {
65
    if (!completionProcessor.matches(nameToUse)) {
1✔
66
      return completionProcessor.result();
1✔
67
    }
68
    LookupElementBuilder newElement = LookupElementBuilder
1✔
69
      .create(subDefinition, nameToUse)
1✔
70
      .withIcon(subDefinition.getIcon(0))
1✔
71
      .withStrikeoutness(subDefinition.isDeprecated())
1✔
72
      .withTypeText(subDefinition.getNamespaceName(), true);
1✔
73

74
    String argsString = subDefinition.getSubArgumentsListAsString();
1✔
75

76
    if (!argsString.isEmpty()) {
1✔
77
      newElement = newElement
1✔
78
        .withInsertHandler(SUB_SELECTION_HANDLER)
1✔
79
        .withTailText(argsString);
1✔
80
    }
81

82
    return completionProcessor.process(newElement);
1✔
83
  }
84

85
  public static boolean processImportedEntityLookupElement(@NotNull PsiElement element,
86
                                                           @NotNull PerlExportDescriptor exportDescriptor,
87
                                                           @NotNull PerlCompletionProcessor completionProcessor) {
88
    return switch (element) {
1✔
89
      case PerlSubDefinitionElement subDefinitionElement ->
1✔
90
        processSubDefinitionLookupElement(subDefinitionElement, exportDescriptor, completionProcessor);
1✔
91
      case PerlSubDeclarationElement subDeclarationElement ->
1✔
92
        processSubDeclarationLookupElement(subDeclarationElement, exportDescriptor, completionProcessor);
1✔
93
      case PerlGlobVariableElement globVariableElement ->
×
94
        processGlobLookupElement(globVariableElement, exportDescriptor, completionProcessor);
×
95
      default -> throw new RuntimeException("Don't know how to make lookup element for " + element.getClass());
×
96
    };
97
  }
98

99
  public static boolean processSubDeclarationLookupElement(@NotNull PerlSubDeclarationElement subDeclaration,
100
                                                           @NotNull PerlCompletionProcessor completionProcessor) {
101
    return processSubDeclarationLookupElement(subDeclaration, null, completionProcessor);
1✔
102
  }
103

104
  public static boolean processSubDeclarationLookupElement(@NotNull PerlSubDeclarationElement subDeclaration,
105
                                                           @Nullable PerlExportDescriptor exportDescriptor,
106
                                                           @NotNull PerlCompletionProcessor completionProcessor) {
107

108
    String lookupString = exportDescriptor == null ? subDeclaration.getSubName() : exportDescriptor.getImportedName();
1✔
109
    if (!completionProcessor.matches(lookupString)) {
1✔
110
      return completionProcessor.result();
×
111
    }
112

113
    return completionProcessor.process(LookupElementBuilder
1✔
114
                                         .create(subDeclaration, lookupString)
1✔
115
                                         .withIcon(subDeclaration.getIcon(0))
1✔
116
                                         .withStrikeoutness(subDeclaration.isDeprecated())
1✔
117
                                         .withInsertHandler(SUB_SELECTION_HANDLER)
1✔
118
                                         .withTypeText(subDeclaration.getNamespaceName(), true)
1✔
119
    );
120
  }
121

122
  public static boolean processGlobLookupElement(@NotNull PerlGlobVariableElement globVariable,
123
                                                 @NotNull PerlCompletionProcessor completionProcessor) {
124
    return processGlobLookupElement(globVariable, null, completionProcessor);
1✔
125
  }
126

127
  /**
128
   * Probably duplicate of {@link PerlVariableCompletionUtil#processVariableLookupElement(PerlGlobVariableElement, boolean, PerlVariableCompletionProcessor)}
129
   */
130
  public static boolean processGlobLookupElement(@NotNull PerlGlobVariableElement globVariable,
131
                                                 @Nullable PerlExportDescriptor exportDescriptor,
132
                                                 @NotNull PerlCompletionProcessor completionProcessor) {
133
    String lookupString = exportDescriptor == null ? globVariable.getName() : exportDescriptor.getImportedName();
1✔
134
    if (!completionProcessor.matches(lookupString)) {
1✔
135
      return completionProcessor.result();
×
136
    }
137

138
    return completionProcessor.process(LookupElementBuilder
1✔
139
                                         .create(globVariable, StringUtil.notNullize(lookupString))
1✔
140
                                         .withIcon(globVariable.getIcon(0))
1✔
141
                                         .withInsertHandler(SUB_SELECTION_HANDLER)
1✔
142
                                         .withTypeText(globVariable.getNamespaceName(), true)
1✔
143
    );
144
  }
145

146
  @SuppressWarnings("UnusedReturnValue")
147
  public static boolean processUnresolvedSubsLookups(@NotNull PerlSubElement subDefinition,
148
                                                     @NotNull PerlCompletionProcessor completionProcessor) {
149
    final String packageName = subDefinition.getNamespaceName();
1✔
150
    if (packageName == null) {
1✔
UNCOV
151
      return completionProcessor.result();
×
152
    }
153

154
    final Set<String> namesSet = new HashSet<>();
1✔
155
    PsiFile containingFile = subDefinition.getContainingFile();
1✔
156
    containingFile.accept(new PerlCompletionRecursiveVisitor(completionProcessor) {
1✔
157
      @Override
158
      protected boolean shouldVisitLightElements() {
159
        return true;
1✔
160
      }
161

162
      @Override
163
      public void visitMethod(@NotNull PsiPerlMethod method) {
164
        doVisitMethod(method);
1✔
165
        super.visitMethod(method);
1✔
166
      }
1✔
167

168
      private void doVisitMethod(@NotNull PsiPerlMethod method) {
169
        PerlCallValue methodValue = PerlCallValue.from(method);
1✔
170
        if (methodValue == null) {
1✔
UNCOV
171
          return;
×
172
        }
173

174
        PerlValue namespaceValue = methodValue.getNamespaceNameValue();
1✔
175

176
        if (!namespaceValue.canRepresentNamespace(packageName)) {
1✔
UNCOV
177
          return;
×
178
        }
179
        PerlSubNameElement subNameElement = method.getSubNameElement();
1✔
180

181
        if (subNameElement == null || !subNameElement.isValid()) {
1✔
UNCOV
182
          return;
×
183
        }
184

185
        String subName = subNameElement.getName();
1✔
186

187
        if (StringUtil.isEmpty(subName) || namesSet.contains(subName) || !completionProcessor.matches(subName)) {
1✔
UNCOV
188
          return;
×
189
        }
190
        PsiReference[] references = subNameElement.getReferences();
1✔
191
        if (references.length == 0) {
1✔
UNCOV
192
          return;
×
193
        }
194

195
        for (PsiReference reference : references) {
1✔
196
          if (reference.resolve() != null) {
1✔
197
            return;
1✔
198
          }
199
        }
200
        // unresolved
201
        namesSet.add(subName);
1✔
202
        completionProcessor.process(LookupElementBuilder.create(subName));
1✔
203
      }
1✔
204
    });
205
    return completionProcessor.result();
1✔
206
  }
207

208
  public static void processWithNotOverriddenSubs(@NotNull PerlSubElement subDefinition,
209
                                                  @NotNull PerlCompletionProcessor completionProcessor) {
210
    PerlPackageUtil.processNotOverridedMethods(
1✔
211
      PsiTreeUtil.getParentOfType(subDefinition, PerlNamespaceDefinitionElement.class),
1✔
212
      subDefinitionBase -> {
213
        String lookupString = subDefinitionBase.getSubName();
1✔
214
        if (completionProcessor.matches(lookupString)) {
1✔
215
          return completionProcessor.process(LookupElementBuilder.create(subDefinitionBase, lookupString));
1✔
216
        }
UNCOV
217
        return completionProcessor.result();
×
218
      }
219
    );
220
  }
1✔
221

222
  public static boolean processSubsCompletionsForCallValue(@NotNull PerlSimpleCompletionProcessor completionProcessor,
223
                                                           @NotNull PerlCallValue perlValue,
224
                                                           boolean isStatic) {
225
    return perlValue.processTargetNamespaceElements(
1✔
226
      completionProcessor.getLeafElement(), new PerlNamespaceItemProcessor<>() {
1✔
227
        @Override
228
        public boolean processItem(@NotNull PsiNamedElement element) {
229
          return switch (element) {
1✔
230
            case PerlImplicitSubDefinition implicitSubDefinition
1✔
231
              when implicitSubDefinition.isAnonymous() -> completionProcessor.result();
1✔
232
            case PerlSubDefinitionElement subDefinitionElement
1✔
233
              when !subDefinitionElement.isAnonymous() &&
1✔
234
                   (isStatic && subDefinitionElement.isStatic() || subDefinitionElement.isMethod()) ->
1✔
235
              processSubDefinitionLookupElement(subDefinitionElement, completionProcessor);
1✔
236
            case PerlSubDeclarationElement subDeclarationElement
1✔
237
              when (isStatic && subDeclarationElement.isStatic() || subDeclarationElement.isMethod()) ->
1✔
238
              processSubDeclarationLookupElement(subDeclarationElement, completionProcessor);
1✔
239
            case PerlGlobVariableElement perlGlobVariableElement
1✔
240
              when perlGlobVariableElement.isLeftSideOfAssignment() && StringUtil.isNotEmpty(element.getName()) ->
1✔
241
              processGlobLookupElement(perlGlobVariableElement, completionProcessor);
1✔
242
            default -> completionProcessor.result();
1✔
243
          };
244
        }
245

246
        @Override
247
        public boolean processImportedItem(@NotNull PsiNamedElement element,
248
                                           @NotNull PerlExportDescriptor exportDescriptor) {
249
          return processImportedEntityLookupElement(element, exportDescriptor, completionProcessor);
1✔
250
        }
251

252
        @Override
253
        public boolean processOrphanDescriptor(@NotNull PerlExportDescriptor exportDescriptor) {
254
          if (exportDescriptor.isSub()) {
1✔
255
            return exportDescriptor.processLookupElement(completionProcessor);
1✔
256
          }
257
          return completionProcessor.result();
1✔
258
        }
259
      });
260
  }
261

262
  public static boolean processBuiltInSubsLookupElements(PerlSimpleCompletionProcessor completionProcessor) {
263
    PerlCompletionProcessor builtInCompletionProcessor = new PerlSimpleDelegatingCompletionProcessor(completionProcessor) {
1✔
264
      @Override
265
      public void addElement(@NotNull LookupElementBuilder lookupElement) {
266
        super.addElement(lookupElement.withBoldness(true));
1✔
267
      }
1✔
268
    };
269

270
    return PerlImplicitDeclarationsService.getInstance(completionProcessor.getProject()).processSubs(
1✔
271
      sub -> sub.isBuiltIn() ? processSubDefinitionLookupElement(sub, builtInCompletionProcessor)
1✔
272
                             : builtInCompletionProcessor.result());
1✔
273
  }
274

275
  /**
276
   * Processes all subs applicable at current context. Declarations, imports, built-ins.
277
   */
278
  @SuppressWarnings("UnusedReturnValue")
279
  public static boolean processContextSubsLookupElements(@NotNull PerlSimpleCompletionProcessor completionProcessor) {
280
    if (!PerlSubCompletionUtil.processBuiltInSubsLookupElements(completionProcessor)) {
1✔
UNCOV
281
      return false;
×
282
    }
283
    PerlCallStaticValue callValue = new PerlCallStaticValue(
1✔
284
      PerlPackageUtil.getContextType(completionProcessor.getLeafElement()), PerlScalarValue.create("dummy"), Collections.emptyList(),
1✔
285
      false);
286
    return processSubsCompletionsForCallValue(completionProcessor, callValue, true);
1✔
287
  }
288
}
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