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

Camelcade / Perl5-IDEA / #525521563

01 Jun 2025 02:15PM UTC coverage: 82.332% (+0.04%) from 82.289%
#525521563

push

github

hurricup
Bounded wildcards

2 of 2 new or added lines in 2 files covered. (100.0%)

69 existing lines in 17 files now uncovered.

30882 of 37509 relevant lines covered (82.33%)

0.82 hits per line

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

89.83
/plugin/core/src/main/java/com/perl5/lang/perl/lexer/PerlProtoLexer.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.lexer;
18

19
import com.intellij.lexer.FlexLexer;
20
import com.intellij.openapi.diagnostic.Logger;
21
import com.intellij.openapi.util.text.StringUtil;
22
import com.intellij.psi.TokenType;
23
import com.intellij.psi.tree.IElementType;
24
import it.unimi.dsi.fastutil.ints.IntArrayList;
25
import org.jetbrains.annotations.Nullable;
26

27
import java.io.IOException;
28
import java.util.LinkedList;
29

30

31
public abstract class PerlProtoLexer implements FlexLexer {
1✔
32
  private static final Logger LOG = Logger.getInstance(PerlProtoLexer.class);
1✔
33
  protected final LinkedList<CustomToken> myPreparsedTokensList = new LinkedList<>();
1✔
34
  protected final IntArrayList myStateStack = new IntArrayList();
1✔
35
  private IElementType myLastTokenType = null;
1✔
36

37
  @SuppressWarnings("override")
38
  public abstract void setTokenStart(int position);
39

40
  @SuppressWarnings("override")
41
  public abstract void setTokenEnd(int position);
42

43
  @SuppressWarnings("override")
44
  public abstract CharSequence getBuffer();
45

46
  @SuppressWarnings("override")
47
  public abstract int getBufferStart();
48

49
  @SuppressWarnings("override")
50
  public abstract int getBufferEnd();
51

52
  @SuppressWarnings("override")
53
  public abstract int getNextTokenStart();
54

55
  protected void pushback() {
56
    yypushback(yylength());
1✔
57
  }
1✔
58

59
  @SuppressWarnings("override")
60
  public abstract void yypushback(int number);
61

62
  @SuppressWarnings("override")
63
  public abstract int yylength();
64

65
  @SuppressWarnings("override")
66
  public abstract IElementType perlAdvance() throws IOException;
67

68
  @SuppressWarnings("override")
69
  public abstract int getRealLexicalState();
70

71
  @SuppressWarnings("override")
72
  public abstract CharSequence yytext();
73

74
  public boolean hasPreparsedTokens() {
75
    return !myPreparsedTokensList.isEmpty();
1✔
76
  }
77

78
  /**
79
   * Checks internal lexer state aside of flex states
80
   *
81
   * @return true if it's safe to return YYINITIAL from yystate
82
   */
83
  public boolean isInitialState() {
84
    return myPreparsedTokensList.isEmpty() && myStateStack.isEmpty();
1✔
85
  }
86

87
  @Override
88
  public IElementType advance() throws IOException {
89
    IElementType tokenType;
90

91
    if (!myPreparsedTokensList.isEmpty()) {
1✔
92
      tokenType = getPreParsedToken();
1✔
93
    }
94
    else {
95
      tokenType = perlAdvance();
1✔
96
    }
97

98
    if (tokenType != null) {
1✔
99
      myLastTokenType = tokenType;
1✔
100
    }
101

102
    return tokenType;
1✔
103
  }
104

105
  protected @Nullable IElementType getLastTokenType() {
106
    return myLastTokenType;
1✔
107
  }
108

109
  /**
110
   * Reading tokens from parsed queue, setting start and end and returns them one by one
111
   *
112
   * @return token type or null if queue is empty
113
   */
114
  public IElementType getPreParsedToken() {
115
    return restoreToken(myPreparsedTokensList.removeFirst());
1✔
116
  }
117

118
  private IElementType restoreToken(CustomToken token) {
119
    setTokenStart(token.getTokenStart());
1✔
120
    setTokenEnd(token.getTokenEnd());
1✔
121
    return token.getTokenType();
1✔
122
  }
123

124
  public void pushStateAndBegin(int newState) {
125
    pushState();
1✔
126
    yybegin(newState);
1✔
127
  }
1✔
128

129
  public void pushStateAndBegin(int stateToPush, int newState) {
130
    yybegin(stateToPush);
1✔
131
    pushStateAndBegin(newState);
1✔
132
  }
1✔
133

134
  public void pushState() {
135
    myStateStack.push(getRealLexicalState());
1✔
136
  }
1✔
137

138
  public void popState() {
139
    if (myStateStack.isEmpty()) {
1✔
UNCOV
140
      LOG.error("Empty stack at " + getRealLexicalState() + "-" + yystate() +
×
UNCOV
141
                "; tokenText: '" + yytext() + "'"
×
142
      );
UNCOV
143
      return;
×
144
    }
145
    yybegin(myStateStack.popInt());
1✔
146
  }
1✔
147

148
  /**
149
   * Adds preparsed token to the queue with consistency control
150
   *
151
   * @param start     token start
152
   * @param end       token end
153
   * @param tokenType token type
154
   */
155
  protected void pushPreparsedToken(int start, int end, IElementType tokenType) {
156
    pushPreparsedToken(getCustomToken(start, end, tokenType));
1✔
157
  }
1✔
158

159
  /**
160
   * Checks if range contains only whitespace chars and pushes whitespace or passed tokentype
161
   *
162
   * @param start     start offset
163
   * @param end       end offset
164
   * @param tokenType tokentype to push if there are non-space chars
165
   */
166
  protected void pushPreparsedSpaceOrToken(int start, int end, IElementType tokenType) {
167
    pushPreparsedToken(start, end, isWhiteSpacesOnly(start, end) ? TokenType.WHITE_SPACE : tokenType);
1✔
168
  }
1✔
169

170
  /**
171
   * Checks if specified range contains only spaces
172
   *
173
   * @param start start offset
174
   * @param end   end offset
175
   * @return check result
176
   */
177
  protected boolean isWhiteSpacesOnly(int start, int end) {
178
    LOG.assertTrue(end <= getBufferEnd());
1✔
179
    LOG.assertTrue(start >= 0);
1✔
180
    CharSequence buffer = getBuffer();
1✔
181

182
    while (start < end) {
1✔
183
      if (!Character.isWhitespace(buffer.charAt(start))) {
1✔
184
        return false;
1✔
185
      }
186
      start++;
1✔
187
    }
188

189
    return true;
1✔
190
  }
191

192

193
  /**
194
   * Helper for creating custom token object
195
   *
196
   * @param start     token start
197
   * @param end       token end
198
   * @param tokenType token type
199
   * @return custom token object
200
   */
201
  protected CustomToken getCustomToken(int start, int end, IElementType tokenType) {
202
    return new CustomToken(start, end, tokenType);
1✔
203
  }
204

205
  /**
206
   * Adds preparsed token to the queue with consistency control
207
   *
208
   * @param token token to add
209
   */
210
  protected void pushPreparsedToken(CustomToken token) {
211
    if (!myPreparsedTokensList.isEmpty() && myPreparsedTokensList.getLast().getTokenEnd() != token.getTokenStart()) {
1✔
UNCOV
212
      LOG.error("Tokens list size=" + myPreparsedTokensList.size() +
×
UNCOV
213
                "; new token start=" + token.getTokenStart() +
×
UNCOV
214
                (myPreparsedTokensList.isEmpty() ? "" : " last token end=" + myPreparsedTokensList.getLast().getTokenEnd()));
×
215
    }
216

217
    myPreparsedTokensList.add(token);
1✔
218
  }
1✔
219

220
  protected void resetInternals() {
221
    myLastTokenType = null;
1✔
222
    myPreparsedTokensList.clear();
1✔
223
    myStateStack.clear();
1✔
224
  }
1✔
225

226
  /**
227
   * Checks if buffer at current offset contains specific string
228
   *
229
   * @param buffer  CharSequence buffer
230
   * @param offset  offset
231
   * @param pattern string to search
232
   * @return search result
233
   */
234
  public boolean isBufferAtString(CharSequence buffer, int offset, CharSequence pattern) {
235
    int patternEnd = offset + pattern.length();
1✔
236
    return getBufferEnd() >= patternEnd && StringUtil.equals(buffer.subSequence(offset, patternEnd), pattern);
1✔
237
  }
238
}
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