• 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

92.16
/plugin/backend/src/main/java/com/perl5/lang/perl/idea/annotators/PerlAnnotator.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.annotators;
18

19

20
import com.intellij.codeInspection.util.InspectionMessage;
21
import com.intellij.lang.annotation.AnnotationHolder;
22
import com.intellij.lang.annotation.HighlightSeverity;
23
import com.intellij.openapi.editor.colors.CodeInsightColors;
24
import com.intellij.openapi.editor.colors.TextAttributesKey;
25
import com.intellij.openapi.util.NlsSafe;
26
import com.intellij.openapi.util.NotNullLazyValue;
27
import com.intellij.openapi.util.text.StringUtil;
28
import com.intellij.psi.ElementManipulators;
29
import com.intellij.psi.PsiElement;
30
import com.intellij.psi.PsiReference;
31
import com.intellij.psi.tree.IElementType;
32
import com.intellij.psi.util.PsiUtilCore;
33
import com.perl5.PerlBundle;
34
import com.perl5.lang.perl.extensions.packageprocessor.impl.ConstantProcessor;
35
import com.perl5.lang.perl.idea.highlighter.PerlSyntaxHighlighter;
36
import com.perl5.lang.perl.psi.*;
37
import com.perl5.lang.perl.psi.impl.*;
38
import com.perl5.lang.perl.psi.light.PerlDelegatingLightNamedElement;
39
import com.perl5.lang.perl.psi.references.PerlSubReference;
40
import com.perl5.lang.perl.util.PerlSubUtilCore;
41
import org.jetbrains.annotations.NonNls;
42
import org.jetbrains.annotations.NotNull;
43

44
import java.util.Map;
45
import java.util.function.BiConsumer;
46
import java.util.function.Consumer;
47

48
import static com.perl5.lang.perl.idea.highlighter.PerlSyntaxHighlighter.*;
49
import static com.perl5.lang.perl.parser.PerlElementTypesGenerated.*;
50

51
public class PerlAnnotator extends PerlBaseAnnotator {
1✔
52
  private static final NotNullLazyValue<Map<Class<? extends PerlVariable>, TextAttributesKey>> VARIABLE_KEYS_MAP =
1✔
53
    NotNullLazyValue.createValue(
1✔
54
      () -> Map.of(
1✔
55
        PsiPerlScalarVariableImpl.class, PERL_SCALAR_BUILTIN,
56
        PsiPerlArrayIndexVariableImpl.class, PERL_SCALAR_BUILTIN,
57
        PsiPerlHashVariableImpl.class, PERL_HASH_BUILTIN,
58
        PsiPerlArrayVariableImpl.class, PERL_ARRAY_BUILTIN)
59
    );
60

61
  @Override
62
  public void annotate(final @NotNull PsiElement element, @NotNull AnnotationHolder holder) {
63
    IElementType elementType = PsiUtilCore.getElementType(element);
1✔
64
    BiConsumer<@InspectionMessage String, TextAttributesKey> defaultAnnotationProducer =
1✔
65
      (var msg, var key) -> createInfoAnnotation(holder, element, msg, key);
1✔
66
    Consumer<TextAttributesKey> defaultSilentProducer = (key) -> createInfoAnnotation(holder, element, null, key);
1✔
67

68
    if (elementType == NYI_STATEMENT) {
1✔
69
      defaultAnnotationProducer.accept(PerlBundle.message("inspection.message.unimplemented.statement"),
1✔
70
                                       CodeInsightColors.TODO_DEFAULT_ATTRIBUTES);
71
    }
72
    else if (element instanceof PerlGlobVariableElement globalVariableElement && globalVariableElement.isBuiltIn()) {
1✔
73
      defaultSilentProducer.accept(PERL_GLOB_BUILTIN);
1✔
74
    }
75
    else if (element instanceof PerlVariable perlVariable && perlVariable.isBuiltIn()) {
1✔
76
      defaultSilentProducer.accept(VARIABLE_KEYS_MAP.get().get(element.getClass()));
1✔
77
    }
78
    else if (elementType == LABEL_DECLARATION || elementType == LABEL_EXPR) {
1✔
79
      createInfoAnnotation(holder, element.getFirstChild(), null, PerlSyntaxHighlighter.PERL_LABEL);
1✔
80
    }
81
    else if (elementType == PACKAGE) {
1✔
82
      assert element instanceof PerlNamespaceElement;
1!
83
      PerlNamespaceElement namespaceElement = (PerlNamespaceElement)element;
1✔
84

85
      PsiElement parent = namespaceElement.getParent();
1✔
86

87
      if (parent instanceof PerlNamespaceDefinitionWithIdentifier) {
1✔
88
        createInfoAnnotation(holder, namespaceElement, null, PerlSyntaxHighlighter.PERL_PACKAGE_DEFINITION);
1✔
89
      }
90
      else {
91
        if (namespaceElement.isPragma()) {
1✔
92
          createInfoAnnotation(holder, namespaceElement, null, PerlSyntaxHighlighter.PERL_PACKAGE_PRAGMA);
1✔
93
        }
94
        else if (namespaceElement.isBuiltin()) {
1✔
95
          createInfoAnnotation(holder, namespaceElement, null, PerlSyntaxHighlighter.PERL_PACKAGE_CORE);
1✔
96
        }
97
      }
98
    }
1✔
99
    else if (element instanceof PerlCharSubstitution charSubstitution) {
1✔
100
      int codePoint = charSubstitution.getCodePoint();
1✔
101
      if (codePoint >= 0 && Character.isValidCodePoint(codePoint)) {
1!
102
        @NlsSafe StringBuilder sb = new StringBuilder("<ul>");
1✔
103
        @NonNls String chars = charSubstitution.getNonIgnorableChars();
1✔
104
        if (StringUtil.isEmptyOrSpaces(chars)) {
1✔
105
          chars = PerlBundle.message("perl.annotator.char.non.printable");
1✔
106
        }
107

108
        sb.append("<li>").append(PerlBundle.message("perl.annotator.char.character")).append(": ")
1✔
109
          .append(chars).append(" (").append(Character.getName(codePoint)).append(")").append("</li>");
1✔
110
        sb.append("<li>").append(PerlBundle.message("perl.annotator.char.codepoint")).append(": ")
1✔
111
          .append("0x").append(Integer.toHexString(codePoint).toUpperCase()).append(" (").append(codePoint).append(")").append("</li>");
1✔
112
        sb.append("</ul>");
1✔
113

114
        holder.newAnnotation(HighlightSeverity.INFORMATION, chars).range(element).tooltip(sb.toString()).create();
1✔
115
      }
116
    }
1✔
117
    else if (element instanceof PerlPolyNamedElement<?> polyNamedElement) {
1✔
118
      TextAttributesKey subAttribute = PerlSyntaxHighlighter.PERL_SUB_DEFINITION;
1✔
119
      if (element instanceof PerlUseStatementElement useStatementElement &&
1✔
120
          useStatementElement.getPackageProcessor() instanceof ConstantProcessor) {
1✔
121
        subAttribute = PerlSyntaxHighlighter.PERL_CONSTANT;
1✔
122
      }
123
      for (PerlDelegatingLightNamedElement<?> lightNamedElement : polyNamedElement.getLightElements()) {
1✔
124
        if (lightNamedElement.isImplicit()) {
1!
125
          continue;
×
126
        }
127
        TextAttributesKey currentKey =
128
          lightNamedElement instanceof PerlSubDefinition ? subAttribute : PerlSyntaxHighlighter.PERL_PACKAGE_DEFINITION;
1✔
129
        PsiElement navigationElement = lightNamedElement.getNavigationElement();
1✔
130
        holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
1✔
131
          .range(ElementManipulators.getValueTextRange(navigationElement).shiftRight(lightNamedElement.getTextOffset()))
1✔
132
          .enforcedTextAttributes(adjustTextAttributes(currentScheme.getAttributes(currentKey), false))
1✔
133
          .create();
1✔
134
      }
1✔
135
    }
1✔
136
    else if (elementType == SUB_NAME) {
1✔
137
      PsiElement parent = element.getParent();
1✔
138
      if (parent instanceof PsiPerlSubDeclaration) {
1✔
139
        defaultSilentProducer.accept(PerlSyntaxHighlighter.PERL_SUB_DECLARATION);
1✔
140
      }
141
      else if (parent instanceof PerlSubDefinitionElement) {
1✔
142
        if (PerlSubUtilCore.SUB_AUTOLOAD.equals(((PerlSubNameElement)element).getName())) {
1!
143
          defaultSilentProducer.accept(PerlSyntaxHighlighter.PERL_AUTOLOAD);
×
144
        }
145
        else {
146
          defaultSilentProducer.accept(PerlSyntaxHighlighter.PERL_SUB_DEFINITION);
1✔
147
        }
148
      }
149
      else if (parent instanceof PerlMethod perlMethod) {
1✔
150
        // fixme don't we need to take multiple references here?
151
        PsiElement grandParent = perlMethod.getParent();
1✔
152
        PerlNamespaceElement methodNamespace = perlMethod.getNamespaceElement();
1✔
153

154
        if (
1✔
155
          !PerlSubCallElement.isNestedCall(grandParent) /// not ...->method fixme shouldn't we use isObjectMethod here?
1✔
156
          && (methodNamespace == null || methodNamespace.isCORE())// no explicit NS or it's core
1✔
157
          && ((PerlSubNameElement)element).isBuiltIn()
1✔
158
        ) {
159
          createInfoAnnotation(holder, element, null, PerlSyntaxHighlighter.PERL_SUB_BUILTIN);
1✔
160
        }
161
        else {
162

163
          PsiReference reference = element.getReference();
1✔
164

165
          if (reference instanceof PerlSubReference perlSubReference) {
1!
166
            perlSubReference.multiResolve(false);
1✔
167

168
            if (perlSubReference.isConstant()) {
1✔
169
              defaultAnnotationProducer.accept(PerlBundle.message("inspection.message.constant"), PerlSyntaxHighlighter.PERL_CONSTANT);
1✔
170
            }
171
            else if (perlSubReference.isAutoloaded()) {
1!
172
              defaultAnnotationProducer.accept(PerlBundle.message("inspection.message.auto.loaded.sub"),
×
173
                                               PerlSyntaxHighlighter.PERL_AUTOLOAD);
174
            }
175
            else if (perlSubReference.isXSub()) {
1!
176
              defaultAnnotationProducer.accept("XSub", PerlSyntaxHighlighter.PERL_XSUB);
×
177
            }
178
          }
179
        }
180
      }
181
    }
182
  }
1✔
183
}
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