• 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.5
/plugin/core/src/main/java/com/perl5/lang/perl/idea/editor/smartkeys/PerlEditorUtil.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.editor.smartkeys;
18

19
import com.intellij.openapi.editor.Editor;
20
import com.intellij.openapi.editor.ex.EditorEx;
21
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
22
import com.intellij.psi.TokenType;
23
import com.intellij.psi.tree.IElementType;
24
import com.intellij.psi.tree.TokenSet;
25
import com.perl5.lang.perl.lexer.PerlTokenSetsEx;
26
import org.jetbrains.annotations.Contract;
27
import org.jetbrains.annotations.NotNull;
28
import org.jetbrains.annotations.Nullable;
29

30
import static com.perl5.lang.perl.parser.PerlElementTypesGenerated.*;
31

32
public class PerlEditorUtil {
×
33
  /**
34
   * Iterates back until atEnd or non-space token
35
   */
36
  public static @NotNull HighlighterIterator moveToPreviousMeaningfulToken(@NotNull HighlighterIterator iterator, boolean ignoreComments) {
37
    while (!iterator.atEnd()) {
1✔
38
      IElementType tokenType = iterator.getTokenType();
1✔
39
      if (tokenType != TokenType.WHITE_SPACE && !(ignoreComments && PerlTokenSetsEx.getCOMMENTS().contains(tokenType))) {
1✔
40
        break;
1✔
41
      }
42
      iterator.retreat();
1✔
43
    }
1✔
44
    return iterator;
1✔
45
  }
46

47
  /**
48
   * Iterates forward until atEnd or non-space token
49
   */
50
  public static void moveToNextMeaningfulToken(@NotNull HighlighterIterator iterator, boolean ignoreComments) {
51
    iterator.advance();
1✔
52
    while (!iterator.atEnd()) {
1✔
53
      IElementType tokenType = iterator.getTokenType();
1✔
54
      if (tokenType != TokenType.WHITE_SPACE && !(ignoreComments && PerlTokenSetsEx.getCOMMENTS().contains(tokenType))) {
1✔
55
        break;
×
56
      }
57
      iterator.advance();
1✔
58
    }
1✔
59
  }
1✔
60

61
  /**
62
   * @return previous non-space token type
63
   */
64
  @Contract("null,_->null")
65
  public static @Nullable IElementType getPreviousTokenType(@Nullable HighlighterIterator iterator, boolean ignoreComments) {
66
    if (iterator == null) {
1✔
67
      return null;
1✔
68
    }
69
    moveToPreviousMeaningfulToken(iterator, ignoreComments);
1✔
70
    return getTokenType(iterator);
1✔
71
  }
72

73
  @Contract("null->null")
74
  public static @Nullable IElementType getTokenType(@Nullable HighlighterIterator iterator) {
75
    return iterator == null || iterator.atEnd() ? null : iterator.getTokenType();
1✔
76
  }
77

78
  public static int getTokenLength(@Nullable HighlighterIterator iterator) {
79
    return iterator == null || iterator.atEnd() ? -1 : iterator.getEnd() - iterator.getStart();
1✔
80
  }
81

82
  @Contract("null->null")
83
  public static @Nullable CharSequence getTokenChars(@Nullable HighlighterIterator iterator) {
84
    return iterator == null || iterator.atEnd() ?
1✔
UNCOV
85
           null :
×
86
           iterator.getDocument().getCharsSequence().subSequence(iterator.getStart(), iterator.getEnd());
1✔
87
  }
88

89
  /**
90
   * @return next non-space token type; NB: current token is skipped
91
   */
92
  public static @Nullable IElementType getNextTokenType(@NotNull HighlighterIterator iterator, boolean ignoreComments) {
93
    moveToNextMeaningfulToken(iterator, ignoreComments);
1✔
94
    return getTokenType(iterator);
1✔
95
  }
96

97
  /**
98
   * Returns true if text in editor contains balanced {@code leftType}s and {@code rightType}s for the {@code offset}.
99
   * Meaning: even number and left is always before the right.
100
   *
101
   * @apiNote actually this algorithm is pretty dumb, but, probably, good enough. For the better we should control nesting of braces, brackets and parens.
102
   * @implSpec we a starting from the beginning and counting open and close markers. If we meet close before open - we fail. If all markers are
103
   * closed after {@code offset}, we think it's ok.
104
   */
105
  public static boolean areMarkersBalanced(@NotNull EditorEx editor,
106
                                           int offset,
107
                                           @NotNull IElementType leftType,
108
                                           @NotNull IElementType rightType) {
109
    HighlighterIterator highlighterIterator = editor.getHighlighter().createIterator(0);
1✔
110
    int level = 0;
1✔
111
    while (!highlighterIterator.atEnd()) {
1✔
112
      IElementType tokenType = highlighterIterator.getTokenType();
1✔
113
      if (tokenType == leftType) {
1✔
114
        level++;
1✔
115
      }
116
      else if (tokenType == rightType) {
1✔
UNCOV
117
        level--;
×
118
      }
119
      if (level < 0) {
1✔
UNCOV
120
        return false;
×
121
      }
122
      else if (level == 0 && highlighterIterator.getEnd() > offset) {
1✔
123
        return true;
1✔
124
      }
125
      highlighterIterator.advance();
1✔
126
    }
1✔
127
    return level == 0;
1✔
128
  }
129

130
  public static boolean areMarkersBalanced(@NotNull EditorEx editor, int offset, char openChar) {
131
    return switch (openChar) {
1✔
132
      case '[' -> areMarkersBalanced(editor, offset, LEFT_BRACKET, RIGHT_BRACKET);
1✔
133
      case '{' -> areMarkersBalanced(editor, offset, LEFT_BRACE, RIGHT_BRACE);
1✔
134
      case '(' -> areMarkersBalanced(editor, offset, LEFT_PAREN, RIGHT_PAREN);
1✔
UNCOV
135
      default -> throw new RuntimeException("Incorrect char: " + openChar);
×
136
    };
137
  }
138

139
  /**
140
   * True iff previous non-space token is one of the {@code elementTypes}
141
   */
142
  public static boolean isPreviousToken(@NotNull Editor editor, int offset, @NotNull TokenSet elementTypes) {
143
    return elementTypes.contains(getPreviousTokenType(editor.getHighlighter().createIterator(offset), false));
1✔
144
  }
145
}
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