• 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

88.3
/plugin/common/src/main/java/com/perl5/lang/perl/parser/elementTypes/PerlHeredocElementType.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.parser.elementTypes;
18

19
import com.intellij.lang.ASTNode;
20
import com.intellij.lang.Language;
21
import com.intellij.openapi.project.Project;
22
import com.intellij.openapi.util.text.StringUtil;
23
import com.intellij.psi.TokenType;
24
import com.intellij.psi.tree.IElementType;
25
import com.intellij.psi.util.PsiUtilCore;
26
import com.intellij.util.text.CharArrayUtil;
27
import org.jetbrains.annotations.ApiStatus;
28
import org.jetbrains.annotations.NotNull;
29

30
import java.util.HashSet;
31
import java.util.Set;
32
import java.util.regex.Pattern;
33

34
import static com.perl5.lang.perl.parser.PerlElementTypesGenerated.HEREDOC_END;
35
import static com.perl5.lang.perl.parser.PerlElementTypesGenerated.HEREDOC_END_INDENTABLE;
36

37

38
public class PerlHeredocElementType extends PerlReparseableElementType {
39
  public PerlHeredocElementType(@NotNull String debugName) {
40
    super(debugName);
1✔
41
  }
1✔
42

43
  /**
44
   * @implSpec this is low-performance heuristic reparsing detection. See #2243
45
   */
46
  @ApiStatus.ScheduledForRemoval(inVersion = "2020.3")
47
  @Deprecated
48
  @Override
49
  protected boolean isReparseableOld(@NotNull ASTNode parent,
50
                                     @NotNull CharSequence buffer,
51
                                     @NotNull Language fileLanguage,
52
                                     @NotNull Project project) {
53
    ASTNode run = parent.getFirstChildNode();
1✔
54
    if (run == null) {
1!
55
      return false;
×
56
    }
57

58
    Checker checker = new Checker(buffer);
1✔
59

60
    while (run != null) {
1✔
61
      if (!checker.check(run)) {
1✔
62
        return false;
1✔
63
      }
64
      run = run.getTreeNext();
1✔
65
    }
66

67
    if (LOG.isDebugEnabled()) {
1!
68
      LOG.debug("Heredoc reparseable: ", checker.result(),
1✔
69
                "; heredocs checked: ", checker.myNormalEndsChecked,
70
                "; indented checked: ", checker.myIndentedEndsChecked);
71
    }
72
    return checker.result();
1✔
73
  }
74

75
  private class Checker {
76
    private Set<String> myNormalEndsChecked = null;
1✔
77
    private Set<String> myIndentedEndsChecked = null;
1✔
78
    private final @NotNull CharSequence myNodeText;
79

80
    public Checker(@NotNull CharSequence nodeText) {
1✔
81
      int index = CharArrayUtil.shiftForward(nodeText, 0, " \t");
1✔
82
      myNodeText = index == 0 ? nodeText : nodeText.subSequence(index, nodeText.length());
1✔
83
    }
1✔
84

85
    /**
86
     * @return true iff it's ok to continue iteration, false otherwise.
87
     */
88
    boolean check(@NotNull ASTNode node) {
89
      IElementType elementType = node.getElementType();
1✔
90
      if (elementType != PerlHeredocElementType.this) {
1✔
91
        return true;
1✔
92
      }
93

94
      ASTNode closeMarker = node.getTreeNext();
1✔
95
      if (PsiUtilCore.getElementType(closeMarker) == TokenType.WHITE_SPACE) {
1✔
96
        closeMarker = closeMarker.getTreeNext();
1✔
97
      }
98
      if (closeMarker == null) {
1✔
99
        return true;
1✔
100
      }
101

102
      String closeMarkerText = closeMarker.getText() + "\n";
1✔
103
      IElementType closeMarkerType = closeMarker.getElementType();
1✔
104
      if (closeMarkerType == HEREDOC_END) {
1✔
105
        if (myNormalEndsChecked == null) {
1✔
106
          myNormalEndsChecked = new HashSet<>();
1✔
107
        }
108
        if (!myNormalEndsChecked.add(closeMarkerText)) {
1✔
109
          return true;
1✔
110
        }
111
        return !(StringUtil.startsWith(myNodeText, closeMarkerText) || StringUtil.contains(myNodeText, "\n" + closeMarkerText));
1!
112
      }
113
      else if (closeMarkerType == HEREDOC_END_INDENTABLE) {
1!
114
        if (myNormalEndsChecked == null) {
1✔
115
          myNormalEndsChecked = new HashSet<>();
1✔
116
        }
117
        if (myIndentedEndsChecked == null) {
1✔
118
          myIndentedEndsChecked = new HashSet<>();
1✔
119
        }
120
        myNormalEndsChecked.add(closeMarkerText);
1✔
121
        if (!myIndentedEndsChecked.add(closeMarkerText)) {
1✔
122
          return true;
1✔
123
        }
124
        if (StringUtil.startsWith(myNodeText, closeMarkerText)) {
1!
125
          return false;
×
126
        }
127
        if (myNodeText.length() < closeMarkerText.length()) {
1!
128
          return true;
×
129
        }
130
        return !Pattern.compile("\n\\s*" + closeMarkerText).matcher(myNodeText).find();
1✔
131
      }
132
      else {
133
        return false;
×
134
      }
135
    }
136

137
    boolean result() {
138
      return myNormalEndsChecked != null || myIndentedEndsChecked != null;
1!
139
    }
140
  }
141
}
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