1 /*******************************************************************************
2 * Copyright (c) 2000, 2020 IBM Corporation and others.
3 *
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
8 *
9 * SPDX-License-Identifier: EPL-2.0
10 *
11 * Contributors:
12 * IBM Corporation - initial API and implementation
13 * Tom Tromey - patch for readTable(String) as described in http://bugs.eclipse.org/bugs/show_bug.cgi?id=32196
14 * Stephan Herrmann - Contributions for
15 * bug 366003 - CCE in ASTNode.resolveAnnotations(ASTNode.java:639)
16 * bug 374605 - Unreasonable warning for enum-based switch statements
17 * bug 393719 - [compiler] inconsistent warnings on iteration variables
18 * bug 382353 - [1.8][compiler] Implementation property modifiers should be accepted on default methods.
19 * bug 383973 - [1.8][compiler] syntax recovery in the presence of default methods
20 * bug 401035 - [1.8] A few tests have started failing recently
21 * Jesper S Moller - Contributions for
22 * bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
23 * bug 399695 - [1.8][compiler] [1.8][compiler] migrate parser to other syntax for default methods
24 * bug 384567 - [1.5][compiler] Compiler accepts illegal modifiers on package declaration
25 * bug 393192 - Incomplete type hierarchy with > 10 annotations
26 * bug 527554 - [18.3] Compiler support for JEP 286 Local-Variable Type
27 * Andy Clement - Contributions for
28 * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
29 * Bug 409250 - [1.8][compiler] Various loose ends in 308 code generation
30 * Bug 415821 - [1.8][compiler] CLASS_EXTENDS target type annotation missing for anonymous classes
31 *******************************************************************************/
32 package org.eclipse.jdt.internal.compiler.parser;
33
34 import java.io.BufferedInputStream;
35 import java.io.BufferedWriter;
36 import java.io.File;
37 import java.io.FileWriter;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.util.ArrayList;
41 import java.util.Collections;
42 import java.util.HashMap;
43 import java.util.HashSet;
44 import java.util.Iterator;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.Properties;
48 import java.util.Set;
49 import java.util.Stack;
50
51 import org.eclipse.jdt.core.compiler.CharOperation;
52 import org.eclipse.jdt.core.compiler.InvalidInputException;
53 import org.eclipse.jdt.internal.compiler.ASTVisitor;
54 import org.eclipse.jdt.internal.compiler.CompilationResult;
55 import org.eclipse.jdt.internal.compiler.ast.*;
56 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
57 import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
58 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
59 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
60 import org.eclipse.jdt.internal.compiler.impl.IrritantSet;
61 import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
62 import org.eclipse.jdt.internal.compiler.lookup.Binding;
63 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
64 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
65 import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
66 import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
67 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
68 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
69 import org.eclipse.jdt.internal.compiler.parser.diagnose.DiagnoseParser;
70 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
71 import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit;
72 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
73 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
74 import org.eclipse.jdt.internal.compiler.util.Messages;
75 import org.eclipse.jdt.internal.compiler.util.Util;
76
77 @SuppressWarnings({"rawtypes", "unchecked"})
78 public class Parser implements TerminalTokens, ParserBasicInformation, ConflictedParser, OperatorIds, TypeIds {
79
80 protected static final int THIS_CALL = ExplicitConstructorCall.This;
81 protected static final int SUPER_CALL = ExplicitConstructorCall.Super;
82 public static final char[] FALL_THROUGH_TAG = "$FALL-THROUGH$".toCharArray(); //$NON-NLS-1$
83 public static final char[] CASES_OMITTED_TAG = "$CASES-OMITTED$".toCharArray(); //$NON-NLS-1$
84
85 public static char asb[] = null;
86 public static char asr[] = null;
87 //ast stack
88 protected final static int AstStackIncrement = 100;
89 public static char base_action[] = null;
90 public static final int BracketKinds = 3;
91
92 public static short check_table[] = null;
93 public static final int CurlyBracket = 2;
94 private static final boolean DEBUG = false;
95 private static final boolean DEBUG_AUTOMATON = false;
96 private static final String EOF_TOKEN = "$eof" ; //$NON-NLS-1$
97 private static final String ERROR_TOKEN = "$error" ; //$NON-NLS-1$
98 //expression stack
99 protected final static int ExpressionStackIncrement = 100;
100
101 protected final static int GenericsStackIncrement = 10;
102
103 private final static String FILEPREFIX = "parser"; //$NON-NLS-1$
104 public static char in_symb[] = null;
105 private static final String INVALID_CHARACTER = "Invalid Character" ; //$NON-NLS-1$
106 public static char lhs[] = null;
107
108 public static String name[] = null;
109 public static char nasb[] = null;
110 public static char nasr[] = null;
111 public static char non_terminal_index[] = null;
112 private final static String READABLE_NAMES_FILE = "readableNames"; //$NON-NLS-1$
113
114 public static String readableName[] = null;
115
116 public static byte rhs[] = null;
117
118 public static int[] reverse_index = null;
119 public static char[] recovery_templates_index = null;
120 public static char[] recovery_templates = null;
121 public static char[] statements_recovery_filter = null;
122
123 public static long rules_compliance[] = null;
124
125 public static final int RoundBracket = 0;
126
127 public static char scope_la[] = null;
128 public static char scope_lhs[] = null;
129
130 public static char scope_prefix[] = null;
131 public static char scope_rhs[] = null;
132 public static char scope_state[] = null;
133
134 public static char scope_state_set[] = null;
135 public static char scope_suffix[] = null;
136 public static final int SquareBracket = 1;
137
138 //internal data for the automat
139 protected final static int StackIncrement = 255;
140
141 public static char term_action[] = null;
142 public static char term_check[] = null;
143
144 public static char terminal_index[] = null;
145
146 private static final String UNEXPECTED_EOF = "Unexpected End Of File" ; //$NON-NLS-1$
147 public static boolean VERBOSE_RECOVERY = false;
148
149 private static enum LocalTypeKind {
150 LOCAL,
151 METHOD_REFERENCE,
152 LAMBDA,
153 }
154
155 // resumeOnSyntaxError codes:
156 protected static final int HALT = 0; // halt and throw up hands.
157 protected static final int RESTART = 1; // stacks adjusted, alternate goal from check point.
158 protected static final int RESUME = 2; // stacks untouched, just continue from where left off.
159
160 public Scanner scanner;
161 public int currentToken;
162
163 static {
164 try{
initTables()165 initTables();
166 } catch(java.io.IOException ex){
167 throw new ExceptionInInitializerError(ex.getMessage());
168 }
169 }
asi(int state)170 public static int asi(int state) {
171
172 return asb[original_state(state)];
173 }
base_check(int i)174 public final static short base_check(int i) {
175 return check_table[i - (NUM_RULES + 1)];
176 }
buildFile(String filename, List listToDump)177 private final static void buildFile(String filename, List listToDump) {
178 BufferedWriter writer = null;
179 try {
180 writer = new BufferedWriter(new FileWriter(filename));
181 for (Iterator iterator = listToDump.iterator(); iterator.hasNext(); ) {
182 writer.write(String.valueOf(iterator.next()));
183 }
184 writer.flush();
185 } catch(IOException e) {
186 // ignore
187 } finally {
188 if (writer != null) {
189 try {
190 writer.close();
191 } catch (IOException e1) {
192 // ignore
193 }
194 }
195 }
196 System.out.println(filename + " creation complete"); //$NON-NLS-1$
197 }
buildFileForCompliance( String file, int length, String[] tokens)198 private static void buildFileForCompliance(
199 String file,
200 int length,
201 String[] tokens) {
202
203 byte[] result = new byte[length * 8];
204
205 for (int i = 0; i < tokens.length; i = i + 3) {
206 if("2".equals(tokens[i])) { //$NON-NLS-1$
207 int index = Integer.parseInt(tokens[i + 1]);
208 String token = tokens[i + 2].trim();
209 long compliance = 0;
210 if("1.4".equals(token)) { //$NON-NLS-1$
211 compliance = ClassFileConstants.JDK1_4;
212 } else if("1.5".equals(token)) { //$NON-NLS-1$
213 compliance = ClassFileConstants.JDK1_5;
214 } else if("1.6".equals(token)) { //$NON-NLS-1$
215 compliance = ClassFileConstants.JDK1_6;
216 } else if("1.7".equals(token)) { //$NON-NLS-1$
217 compliance = ClassFileConstants.JDK1_7;
218 } else if("1.8".equals(token)) { //$NON-NLS-1$
219 compliance = ClassFileConstants.JDK1_8;
220 } else if("9".equals(token)) { //$NON-NLS-1$
221 compliance = ClassFileConstants.JDK9;
222 } else if("10".equals(token)) { //$NON-NLS-1$
223 compliance = ClassFileConstants.JDK10;
224 } else if("11".equals(token)) { //$NON-NLS-1$
225 compliance = ClassFileConstants.JDK11;
226 } else if("12".equals(token)) { //$NON-NLS-1$
227 compliance = ClassFileConstants.JDK12;
228 } else if("13".equals(token)) { //$NON-NLS-1$
229 compliance = ClassFileConstants.JDK13;
230 } else if("14".equals(token)) { //$NON-NLS-1$
231 compliance = ClassFileConstants.JDK14;
232 } else if("recovery".equals(token)) { //$NON-NLS-1$
233 compliance = ClassFileConstants.JDK_DEFERRED;
234 }
235
236 int j = index * 8;
237 result[j] = (byte)(compliance >>> 56);
238 result[j + 1] = (byte)(compliance >>> 48);
239 result[j + 2] = (byte)(compliance >>> 40);
240 result[j + 3] = (byte)(compliance >>> 32);
241 result[j + 4] = (byte)(compliance >>> 24);
242 result[j + 5] = (byte)(compliance >>> 16);
243 result[j + 6] = (byte)(compliance >>> 8);
244 result[j + 7] = (byte)(compliance);
245 }
246 }
247
248 buildFileForTable(file, result);
249 }
buildFileForName(String filename, String contents)250 private final static String[] buildFileForName(String filename, String contents) {
251 String[] result = new String[contents.length()];
252 result[0] = null;
253 int resultCount = 1;
254
255 StringBuffer buffer = new StringBuffer();
256
257 int start = contents.indexOf("name[]"); //$NON-NLS-1$
258 start = contents.indexOf('\"', start);
259 int end = contents.indexOf("};", start); //$NON-NLS-1$
260
261 contents = contents.substring(start, end);
262
263 boolean addLineSeparator = false;
264 int tokenStart = -1;
265 StringBuffer currentToken = new StringBuffer();
266 for (int i = 0; i < contents.length(); i++) {
267 char c = contents.charAt(i);
268 if(c == '\"') {
269 if(tokenStart == -1) {
270 tokenStart = i + 1;
271 } else {
272 if(addLineSeparator) {
273 buffer.append('\n');
274 result[resultCount++] = currentToken.toString();
275 currentToken = new StringBuffer();
276 }
277 String token = contents.substring(tokenStart, i);
278 if(token.equals(ERROR_TOKEN)){
279 token = INVALID_CHARACTER;
280 } else if(token.equals(EOF_TOKEN)) {
281 token = UNEXPECTED_EOF;
282 }
283 buffer.append(token);
284 currentToken.append(token);
285 addLineSeparator = true;
286 tokenStart = -1;
287 }
288 }
289 if(tokenStart == -1 && c == '+'){
290 addLineSeparator = false;
291 }
292 }
293 if(currentToken.length() > 0) {
294 result[resultCount++] = currentToken.toString();
295 }
296
297 buildFileForTable(filename, buffer.toString().toCharArray());
298
299 System.arraycopy(result, 0, result = new String[resultCount], 0, resultCount);
300 return result;
301 }
buildFileForReadableName( String file, char[] newLhs, char[] newNonTerminalIndex, String[] newName, String[] tokens)302 private static void buildFileForReadableName(
303 String file,
304 char[] newLhs,
305 char[] newNonTerminalIndex,
306 String[] newName,
307 String[] tokens) {
308
309 ArrayList entries = new ArrayList();
310
311 boolean[] alreadyAdded = new boolean[newName.length];
312
313 for (int i = 0; i < tokens.length; i = i + 3) {
314 if("1".equals(tokens[i])) { //$NON-NLS-1$
315 int index = newNonTerminalIndex[newLhs[Integer.parseInt(tokens[i + 1])]];
316 StringBuffer buffer = new StringBuffer();
317 if(!alreadyAdded[index]) {
318 alreadyAdded[index] = true;
319 buffer.append(newName[index]);
320 buffer.append('=');
321 buffer.append(tokens[i+2].trim());
322 buffer.append('\n');
323 entries.add(String.valueOf(buffer));
324 }
325 }
326 }
327 int i = 1;
328 while(!INVALID_CHARACTER.equals(newName[i])) i++;
329 i++;
330 for (; i < alreadyAdded.length; i++) {
331 if(!alreadyAdded[i]) {
332 System.out.println(newName[i] + " has no readable name"); //$NON-NLS-1$
333 }
334 }
335 Collections.sort(entries);
336 buildFile(file, entries);
337 }
buildFileForTable(String filename, byte[] bytes)338 private final static void buildFileForTable(String filename, byte[] bytes) {
339 java.io.FileOutputStream stream = null;
340 try {
341 stream = new java.io.FileOutputStream(filename);
342 stream.write(bytes);
343 } catch(IOException e) {
344 // ignore
345 } finally {
346 if (stream != null) {
347 try {
348 stream.close();
349 } catch (IOException e) {
350 // ignore
351 }
352 }
353 }
354 System.out.println(filename + " creation complete"); //$NON-NLS-1$
355 }
buildFileForTable(String filename, char[] chars)356 private final static void buildFileForTable(String filename, char[] chars) {
357 byte[] bytes = new byte[chars.length * 2];
358 for (int i = 0; i < chars.length; i++) {
359 bytes[2 * i] = (byte) (chars[i] >>> 8);
360 bytes[2 * i + 1] = (byte) (chars[i] & 0xFF);
361 }
362
363 java.io.FileOutputStream stream = null;
364 try {
365 stream = new java.io.FileOutputStream(filename);
366 stream.write(bytes);
367 } catch(IOException e) {
368 // ignore
369 } finally {
370 if (stream != null) {
371 try {
372 stream.close();
373 } catch (IOException e) {
374 // ignore
375 }
376 }
377 }
378 System.out.println(filename + " creation complete"); //$NON-NLS-1$
379 }
buildFileOfByteFor(String filename, String tag, String[] tokens)380 private final static byte[] buildFileOfByteFor(String filename, String tag, String[] tokens) {
381
382 //transform the String tokens into chars before dumping then into file
383
384 int i = 0;
385 //read upto the tag
386 while (!tokens[i++].equals(tag)){/*empty*/}
387 //read upto the }
388
389 byte[] bytes = new byte[tokens.length]; //can't be bigger
390 int ic = 0;
391 String token;
392 while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
393 int c = Integer.parseInt(token);
394 bytes[ic++] = (byte) c;
395 }
396
397 //resize
398 System.arraycopy(bytes, 0, bytes = new byte[ic], 0, ic);
399
400 buildFileForTable(filename, bytes);
401 return bytes;
402 }
buildFileOfIntFor(String filename, String tag, String[] tokens)403 private final static char[] buildFileOfIntFor(String filename, String tag, String[] tokens) {
404
405 //transform the String tokens into chars before dumping then into file
406
407 int i = 0;
408 //read upto the tag
409 while (!tokens[i++].equals(tag)){/*empty*/}
410 //read upto the }
411
412 char[] chars = new char[tokens.length]; //can't be bigger
413 int ic = 0;
414 String token;
415 while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
416 int c = Integer.parseInt(token);
417 chars[ic++] = (char) c;
418 }
419
420 //resize
421 System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
422
423 buildFileForTable(filename, chars);
424 return chars;
425 }
buildFileOfShortFor(String filename, String tag, String[] tokens)426 private final static void buildFileOfShortFor(String filename, String tag, String[] tokens) {
427
428 //transform the String tokens into chars before dumping then into file
429
430 int i = 0;
431 //read upto the tag
432 while (!tokens[i++].equals(tag)){/*empty*/}
433 //read upto the }
434
435 char[] chars = new char[tokens.length]; //can't be bigger
436 int ic = 0;
437 String token;
438 while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
439 int c = Integer.parseInt(token);
440 chars[ic++] = (char) (c + 32768);
441 }
442
443 //resize
444 System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
445
446 buildFileForTable(filename, chars);
447 }
buildFilesForRecoveryTemplates( String indexFilename, String templatesFilename, char[] newTerminalIndex, char[] newNonTerminalIndex, String[] newName, char[] newLhs, String[] tokens)448 private static void buildFilesForRecoveryTemplates(
449 String indexFilename,
450 String templatesFilename,
451 char[] newTerminalIndex,
452 char[] newNonTerminalIndex,
453 String[] newName,
454 char[] newLhs,
455 String[] tokens) {
456
457 int[] newReverse = computeReverseTable(newTerminalIndex, newNonTerminalIndex, newName);
458
459 char[] newRecoveyTemplatesIndex = new char[newNonTerminalIndex.length];
460 char[] newRecoveyTemplates = new char[newNonTerminalIndex.length];
461 int newRecoveyTemplatesPtr = 0;
462
463 for (int i = 0; i < tokens.length; i = i + 3) {
464 if("3".equals(tokens[i])) { //$NON-NLS-1$
465 int length = newRecoveyTemplates.length;
466 if(length == newRecoveyTemplatesPtr + 1) {
467 System.arraycopy(newRecoveyTemplates, 0, newRecoveyTemplates = new char[length * 2], 0, length);
468 }
469 newRecoveyTemplates[newRecoveyTemplatesPtr++] = 0;
470
471 int index = newLhs[Integer.parseInt(tokens[i + 1])];
472
473 newRecoveyTemplatesIndex[index] = (char)newRecoveyTemplatesPtr;
474
475 String token = tokens[i + 2].trim();
476 java.util.StringTokenizer st = new java.util.StringTokenizer(token, " "); //$NON-NLS-1$
477 String[] terminalNames = new String[st.countTokens()];
478 int t = 0;
479 while (st.hasMoreTokens()) {
480 terminalNames[t++] = st.nextToken();
481 }
482
483 for (int j = 0; j < terminalNames.length; j++) {
484 int symbol = getSymbol(terminalNames[j], newName, newReverse);
485 if(symbol > -1) {
486 length = newRecoveyTemplates.length;
487 if(length == newRecoveyTemplatesPtr + 1) {
488 System.arraycopy(newRecoveyTemplates, 0, newRecoveyTemplates = new char[length * 2], 0, length);
489 }
490 newRecoveyTemplates[newRecoveyTemplatesPtr++] = (char)symbol;
491 }
492 }
493 }
494 }
495 newRecoveyTemplates[newRecoveyTemplatesPtr++] = 0;
496 System.arraycopy(newRecoveyTemplates, 0, newRecoveyTemplates = new char[newRecoveyTemplatesPtr], 0, newRecoveyTemplatesPtr);
497
498 buildFileForTable(indexFilename, newRecoveyTemplatesIndex);
499 buildFileForTable(templatesFilename, newRecoveyTemplates);
500 }
buildFilesForStatementsRecoveryFilter( String filename, char[] newNonTerminalIndex, char[] newLhs, String[] tokens)501 private static void buildFilesForStatementsRecoveryFilter(
502 String filename,
503 char[] newNonTerminalIndex,
504 char[] newLhs,
505 String[] tokens) {
506
507 char[] newStatementsRecoveryFilter = new char[newNonTerminalIndex.length];
508
509 for (int i = 0; i < tokens.length; i = i + 3) {
510 if("4".equals(tokens[i])) { //$NON-NLS-1$
511 int index = newLhs[Integer.parseInt(tokens[i + 1])];
512
513 newStatementsRecoveryFilter[index] = 1;
514 }
515 }
516 buildFileForTable(filename, newStatementsRecoveryFilter);
517 }
buildFilesFromLPG(String dataFilename, String dataFilename2)518 public final static void buildFilesFromLPG(String dataFilename, String dataFilename2) {
519
520 //RUN THIS METHOD TO GENERATE PARSER*.RSC FILES
521
522 //build from the lpg javadcl.java files that represents the parser tables
523 //lhs check_table asb asr symbol_index
524
525 //[org.eclipse.jdt.internal.compiler.parser.Parser.buildFilesFromLPG("d:/leapfrog/grammar/javadcl.java")]
526 char[] contents = CharOperation.NO_CHAR;
527 try {
528 contents = Util.getFileCharContent(new File(dataFilename), null);
529 } catch (IOException ex) {
530 System.out.println(Messages.parser_incorrectPath);
531 return;
532 }
533 java.util.StringTokenizer st =
534 new java.util.StringTokenizer(new String(contents), " \t\n\r[]={,;"); //$NON-NLS-1$
535 String[] tokens = new String[st.countTokens()];
536 int j = 0;
537 while (st.hasMoreTokens()) {
538 tokens[j++] = st.nextToken();
539 }
540 final String prefix = FILEPREFIX;
541 int i = 0;
542
543 char[] newLhs = buildFileOfIntFor(prefix + (++i) + ".rsc", "lhs", tokens); //$NON-NLS-1$ //$NON-NLS-2$
544 buildFileOfShortFor(prefix + (++i) + ".rsc", "check_table", tokens); //$NON-NLS-2$ //$NON-NLS-1$
545 buildFileOfIntFor(prefix + (++i) + ".rsc", "asb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
546 buildFileOfIntFor(prefix + (++i) + ".rsc", "asr", tokens); //$NON-NLS-2$ //$NON-NLS-1$
547 buildFileOfIntFor(prefix + (++i) + ".rsc", "nasb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
548 buildFileOfIntFor(prefix + (++i) + ".rsc", "nasr", tokens); //$NON-NLS-2$ //$NON-NLS-1$
549 char[] newTerminalIndex = buildFileOfIntFor(prefix + (++i) + ".rsc", "terminal_index", tokens); //$NON-NLS-2$ //$NON-NLS-1$
550 char[] newNonTerminalIndex = buildFileOfIntFor(prefix + (++i) + ".rsc", "non_terminal_index", tokens); //$NON-NLS-1$ //$NON-NLS-2$
551 buildFileOfIntFor(prefix + (++i) + ".rsc", "term_action", tokens); //$NON-NLS-2$ //$NON-NLS-1$
552
553 buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_prefix", tokens); //$NON-NLS-2$ //$NON-NLS-1$
554 buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_suffix", tokens); //$NON-NLS-2$ //$NON-NLS-1$
555 buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_lhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
556 buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_state_set", tokens); //$NON-NLS-2$ //$NON-NLS-1$
557 buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_rhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
558 buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_state", tokens); //$NON-NLS-2$ //$NON-NLS-1$
559 buildFileOfIntFor(prefix + (++i) + ".rsc", "in_symb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
560
561 byte[] newRhs = buildFileOfByteFor(prefix + (++i) + ".rsc", "rhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
562 buildFileOfIntFor(prefix + (++i) + ".rsc", "term_check", tokens); //$NON-NLS-2$ //$NON-NLS-1$
563 buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_la", tokens); //$NON-NLS-2$ //$NON-NLS-1$
564
565 String[] newName = buildFileForName(prefix + (++i) + ".rsc", new String(contents)); //$NON-NLS-1$
566
567 contents = CharOperation.NO_CHAR;
568 try {
569 contents = Util.getFileCharContent(new File(dataFilename2), null);
570 } catch (IOException ex) {
571 System.out.println(Messages.parser_incorrectPath);
572 return;
573 }
574 st = new java.util.StringTokenizer(new String(contents), "\t\n\r#"); //$NON-NLS-1$
575 tokens = new String[st.countTokens()];
576 j = 0;
577 while (st.hasMoreTokens()) {
578 tokens[j++] = st.nextToken();
579 }
580
581 buildFileForCompliance(prefix + (++i) + ".rsc", newRhs.length, tokens);//$NON-NLS-1$
582 buildFileForReadableName(READABLE_NAMES_FILE+".props", newLhs, newNonTerminalIndex, newName, tokens);//$NON-NLS-1$
583
584 buildFilesForRecoveryTemplates(
585 prefix + (++i) + ".rsc", //$NON-NLS-1$
586 prefix + (++i) + ".rsc", //$NON-NLS-1$
587 newTerminalIndex,
588 newNonTerminalIndex,
589 newName,
590 newLhs,
591 tokens);
592
593 buildFilesForStatementsRecoveryFilter(
594 prefix + (++i) + ".rsc", //$NON-NLS-1$
595 newNonTerminalIndex,
596 newLhs,
597 tokens);
598
599
600 System.out.println(Messages.parser_moveFiles);
601 }
computeReverseTable(char[] newTerminalIndex, char[] newNonTerminalIndex, String[] newName)602 protected static int[] computeReverseTable(char[] newTerminalIndex, char[] newNonTerminalIndex, String[] newName) {
603 int[] newReverseTable = new int[newName.length];
604 for (int j = 0; j < newName.length; j++) {
605 found : {
606 for (int k = 0; k < newTerminalIndex.length; k++) {
607 if(newTerminalIndex[k] == j) {
608 newReverseTable[j] = k;
609 break found;
610 }
611 }
612 for (int k = 0; k < newNonTerminalIndex.length; k++) {
613 if(newNonTerminalIndex[k] == j) {
614 newReverseTable[j] = -k;
615 break found;
616 }
617 }
618 }
619 }
620 return newReverseTable;
621 }
622
getSymbol(String terminalName, String[] newName, int[] newReverse)623 private static int getSymbol(String terminalName, String[] newName, int[] newReverse) {
624 for (int j = 0; j < newName.length; j++) {
625 if(terminalName.equals(newName[j])) {
626 return newReverse[j];
627 }
628 }
629 return -1;
630 }
in_symbol(int state)631 public static int in_symbol(int state) {
632 return in_symb[original_state(state)];
633 }
initTables()634 public final static void initTables() throws java.io.IOException {
635
636 final String prefix = FILEPREFIX;
637 int i = 0;
638 lhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
639 char[] chars = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
640 check_table = new short[chars.length];
641 for (int c = chars.length; c-- > 0;) {
642 check_table[c] = (short) (chars[c] - 32768);
643 }
644 asb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
645 asr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
646 nasb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
647 nasr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
648 terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
649 non_terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
650 term_action = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
651
652 scope_prefix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
653 scope_suffix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
654 scope_lhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
655 scope_state_set = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
656 scope_rhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
657 scope_state = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
658 in_symb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
659
660 rhs = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
661 term_check = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
662 scope_la = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
663
664 name = readNameTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
665
666 rules_compliance = readLongTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
667
668 readableName = readReadableNameTable(READABLE_NAMES_FILE + ".props"); //$NON-NLS-1$
669
670 reverse_index = computeReverseTable(terminal_index, non_terminal_index, name);
671
672 recovery_templates_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
673 recovery_templates = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
674
675 statements_recovery_filter = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
676
677 base_action = lhs;
678 }
nasi(int state)679 public static int nasi(int state) {
680 return nasb[original_state(state)];
681 }
ntAction(int state, int sym)682 public static int ntAction(int state, int sym) {
683 return base_action[state + sym];
684 }
original_state(int state)685 protected static int original_state(int state) {
686 return -base_check(state);
687 }
688
readByteTable(String filename)689 protected static byte[] readByteTable(String filename) throws java.io.IOException {
690
691 //files are located at Parser.class directory
692
693 InputStream stream = Parser.class.getResourceAsStream(filename);
694 if (stream == null) {
695 throw new java.io.IOException(Messages.bind(Messages.parser_missingFile, filename));
696 }
697 byte[] bytes = null;
698 try {
699 stream = new BufferedInputStream(stream);
700 bytes = Util.getInputStreamAsByteArray(stream, -1);
701 } finally {
702 try {
703 stream.close();
704 } catch (IOException e) {
705 // ignore
706 }
707 }
708 return bytes;
709 }
readLongTable(String filename)710 protected static long[] readLongTable(String filename) throws java.io.IOException {
711
712 //files are located at Parser.class directory
713
714 InputStream stream = Parser.class.getResourceAsStream(filename);
715 if (stream == null) {
716 throw new java.io.IOException(Messages.bind(Messages.parser_missingFile, filename));
717 }
718 byte[] bytes = null;
719 try {
720 stream = new BufferedInputStream(stream);
721 bytes = Util.getInputStreamAsByteArray(stream, -1);
722 } finally {
723 try {
724 stream.close();
725 } catch (IOException e) {
726 // ignore
727 }
728 }
729
730 //minimal integrity check (even size expected)
731 int length = bytes.length;
732 if (length % 8 != 0)
733 throw new java.io.IOException(Messages.bind(Messages.parser_corruptedFile, filename));
734
735 // convert bytes into longs
736 long[] longs = new long[length / 8];
737 int i = 0;
738 int longIndex = 0;
739
740 while (true) {
741 longs[longIndex++] =
742 (((long) (bytes[i++] & 0xFF)) << 56)
743 + (((long) (bytes[i++] & 0xFF)) << 48)
744 + (((long) (bytes[i++] & 0xFF)) << 40)
745 + (((long) (bytes[i++] & 0xFF)) << 32)
746 + (((long) (bytes[i++] & 0xFF)) << 24)
747 + (((long) (bytes[i++] & 0xFF)) << 16)
748 + (((long) (bytes[i++] & 0xFF)) << 8)
749 + (bytes[i++] & 0xFF);
750
751 if (i == length)
752 break;
753 }
754 return longs;
755 }
756
readNameTable(String filename)757 protected static String[] readNameTable(String filename) throws java.io.IOException {
758 char[] contents = readTable(filename);
759 char[][] nameAsChar = CharOperation.splitOn('\n', contents);
760
761 String[] result = new String[nameAsChar.length + 1];
762 result[0] = null;
763 for (int i = 0; i < nameAsChar.length; i++) {
764 result[i + 1] = new String(nameAsChar[i]);
765 }
766
767 return result;
768 }
readReadableNameTable(String filename)769 protected static String[] readReadableNameTable(String filename){
770 String[] result = new String[name.length];
771
772 InputStream is = Parser.class.getResourceAsStream(filename);
773 Properties props = new Properties();
774 try {
775 props.load(is);
776 } catch (IOException e) {
777 result = name;
778 return result;
779 }
780 System.arraycopy(name, 0, result, 0, NT_OFFSET + 1);
781 for (int i = NT_OFFSET; i < name.length; i++) {
782 String n = props.getProperty(name[i]);
783 if (n != null && n.length() > 0) {
784 result[i] = n;
785 } else {
786 result[i] = name[i];
787 }
788 }
789 return result;
790 }
readTable(String filename)791 protected static char[] readTable(String filename) throws java.io.IOException {
792
793 //files are located at Parser.class directory
794
795 InputStream stream = Parser.class.getResourceAsStream(filename);
796 if (stream == null) {
797 throw new java.io.IOException(Messages.bind(Messages.parser_missingFile, filename));
798 }
799 byte[] bytes = null;
800 try {
801 stream = new BufferedInputStream(stream);
802 bytes = Util.getInputStreamAsByteArray(stream, -1);
803 } finally {
804 try {
805 stream.close();
806 } catch (IOException e) {
807 // ignore
808 }
809 }
810
811 //minimal integrity check (even size expected)
812 int length = bytes.length;
813 if ((length & 1) != 0)
814 throw new java.io.IOException(Messages.bind(Messages.parser_corruptedFile, filename));
815
816 // convert bytes into chars
817 char[] chars = new char[length / 2];
818 int i = 0;
819 int charIndex = 0;
820
821 while (true) {
822 chars[charIndex++] = (char) (((bytes[i++] & 0xFF) << 8) + (bytes[i++] & 0xFF));
823 if (i == length)
824 break;
825 }
826 return chars;
827 }
tAction(int state, int sym)828 public static int tAction(int state, int sym) {
829 return term_action[term_check[base_action[state]+sym] == sym ? base_action[state] + sym : base_action[state]];
830 }
831 /** Overridable hook, to allow CompletionParser to synthesize a few trailing tokens at (faked) EOF. */
actFromTokenOrSynthetic(int previousAct)832 protected int actFromTokenOrSynthetic(int previousAct) {
833 return tAction(previousAct, this.currentToken);
834 }
835 protected int astLengthPtr;
836
837 protected int[] astLengthStack;
838 protected int astPtr;
839 protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
840
841 protected int patternLengthPtr;
842
843 protected int[] patternLengthStack;
844 protected int patternPtr;
845 protected ASTNode[] patternStack = new ASTNode[AstStackIncrement];
846 public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
847
848 protected RecoveredElement currentElement;
849
850 protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies
851 protected int dietInt = 0; // if > 0 force the none-diet-parsing mode (even if diet if requested) [field parsing with anonymous inner classes...]
852 protected int endPosition; //accurate only when used ! (the start position is pushed into intStack while the end the current one)
853 protected int endStatementPosition;
854 protected int expressionLengthPtr;
855 protected int[] expressionLengthStack;
856 protected int expressionPtr;
857 protected Expression[] expressionStack = new Expression[ExpressionStackIncrement];
858 protected int rBracketPosition;
859 public int firstToken ; // handle for multiple parsing goals
860
861 /* jsr308 -- Type annotation management, we now maintain type annotations in a separate stack
862 as otherwise they get interspersed with other expressions and some of the code is not prepared
863 to handle such interleaving and will look ugly if changed.
864
865 See consumeArrayCreationExpressionWithoutInitializer for example.
866
867 Where SE8 annotations occur in a place SE5 annotations are legal, the SE8 annotations end up in
868 the expression stack as we have no way of distinguishing between the two.
869 */
870 protected int typeAnnotationPtr;
871 protected int typeAnnotationLengthPtr;
872 protected Annotation [] typeAnnotationStack = new Annotation[TypeAnnotationStackIncrement];
873 protected int [] typeAnnotationLengthStack;
874 // annotation stack
875 protected final static int TypeAnnotationStackIncrement = 100;
876
877 // generics management
878 protected int genericsIdentifiersLengthPtr;
879 protected int[] genericsIdentifiersLengthStack = new int[GenericsStackIncrement];
880 protected int genericsLengthPtr;
881 protected int[] genericsLengthStack = new int[GenericsStackIncrement];
882 protected int genericsPtr;
883 protected ASTNode[] genericsStack = new ASTNode[GenericsStackIncrement];
884 protected boolean hasError;
885 protected boolean hasReportedError;
886 //identifiers stacks
887 protected int identifierLengthPtr;
888 protected int[] identifierLengthStack;
889 protected long[] identifierPositionStack;
890 protected int identifierPtr;
891 protected char[][] identifierStack;
892 protected boolean ignoreNextOpeningBrace;
893 protected boolean ignoreNextClosingBrace;
894
895 //positions , dimensions , .... (int stacks)
896 protected int intPtr;
897
898 protected int[] intStack;
899 public int lastAct ; //handle for multiple parsing goals
900 //error recovery management
901 protected int lastCheckPoint;
902 protected int lastErrorEndPosition;
903 protected int lastErrorEndPositionBeforeRecovery = -1;
904 protected int lastIgnoredToken, nextIgnoredToken;
905
906 protected int listLength; // for recovering some incomplete list (interfaces, throws or parameters)
907
908 protected int listTypeParameterLength; // for recovering some incomplete list (type parameters)
909 protected int lParenPos,rParenPos; //accurate only when used !
910 protected int modifiers;
911 protected int modifiersSourceStart;
912 protected int colonColonStart = -1;
913 protected int[] nestedMethod; //the ptr is nestedType
914 protected int forStartPosition = 0;
915
916 protected int nestedType, dimensions, switchNestingLevel;
917 ASTNode [] noAstNodes = new ASTNode[AstStackIncrement];
918 public boolean switchWithTry = false;
919
920 Expression [] noExpressions = new Expression[ExpressionStackIncrement];
921 //modifiers dimensions nestedType etc.......
922 protected boolean optimizeStringLiterals =true;
923 protected CompilerOptions options;
924
925 protected ProblemReporter problemReporter;
926
927 protected int rBraceStart, rBraceEnd, rBraceSuccessorStart; //accurate only when used !
928 protected int realBlockPtr;
929 protected int[] realBlockStack;
930 protected int recoveredStaticInitializerStart;
931 public ReferenceContext referenceContext;
932 public boolean reportOnlyOneSyntaxError = false;
933 public boolean reportSyntaxErrorIsRequired = true;
934 protected boolean restartRecovery;
935 protected boolean annotationRecoveryActivated = true;
936 protected int lastPosistion;
937 // statement recovery
938 public boolean methodRecoveryActivated = false;
939 protected boolean statementRecoveryActivated = false;
940 protected TypeDeclaration[] recoveredTypes;
941 protected int recoveredTypePtr;
942 protected int nextTypeStart;
943 protected TypeDeclaration pendingRecoveredType;
944 public RecoveryScanner recoveryScanner;
945
946 protected int[] stack = new int[StackIncrement];
947 protected int stateStackTop;
948 protected int synchronizedBlockSourceStart;
949
950 protected int[] variablesCounter;
951
952 protected boolean checkExternalizeStrings;
953
954 protected boolean recordStringLiterals;
955 // javadoc
956 public Javadoc javadoc;
957 public JavadocParser javadocParser;
958 // used for recovery
959 protected int lastJavadocEnd;
960 public org.eclipse.jdt.internal.compiler.ReadManager readManager;
961 protected int valueLambdaNestDepth = -1;
962 private int stateStackLengthStack[] = new int[0];
963 protected boolean parsingJava8Plus;
964 protected boolean parsingJava9Plus;
965 protected boolean parsingJava14Plus;
966 protected boolean parsingJava11Plus;
967 protected int unstackedAct = ERROR_ACTION;
968 private boolean haltOnSyntaxError = false;
969 private boolean tolerateDefaultClassMethods = false;
970 private boolean processingLambdaParameterList = false;
971 private boolean expectTypeAnnotation = false;
972 private boolean reparsingLambdaExpression = false;
973
974 private Map<TypeDeclaration, Integer[]> recordNestedMethodLevels;
975
Parser()976 public Parser () {
977 // Caveat Emptor: For inheritance purposes and then only in very special needs. Only minimal state is initialized !
978 }
Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals)979 public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) {
980
981 this.problemReporter = problemReporter;
982 this.options = problemReporter.options;
983 this.optimizeStringLiterals = optimizeStringLiterals;
984 initializeScanner();
985 this.parsingJava8Plus = this.options.sourceLevel >= ClassFileConstants.JDK1_8;
986 this.parsingJava9Plus = this.options.sourceLevel >= ClassFileConstants.JDK9;
987 this.parsingJava14Plus = this.options.sourceLevel >= ClassFileConstants.JDK14;
988 this.parsingJava11Plus = this.options.sourceLevel >= ClassFileConstants.JDK11;
989 this.astLengthStack = new int[50];
990 this.patternLengthStack = new int[20];
991 this.expressionLengthStack = new int[30];
992 this.typeAnnotationLengthStack = new int[30];
993 this.intStack = new int[50];
994 this.identifierStack = new char[30][];
995 this.identifierLengthStack = new int[30];
996 this.nestedMethod = new int[30];
997 this.realBlockStack = new int[30];
998 this.identifierPositionStack = new long[30];
999 this.variablesCounter = new int[30];
1000
1001 this.recordNestedMethodLevels = new HashMap<>();
1002
1003 // javadoc support
1004 this.javadocParser = createJavadocParser();
1005 }
annotationRecoveryCheckPoint(int start, int end)1006 protected void annotationRecoveryCheckPoint(int start, int end) {
1007 if(this.lastCheckPoint < end) {
1008 this.lastCheckPoint = end + 1;
1009 }
1010 }
arrayInitializer(int length)1011 public void arrayInitializer(int length) {
1012 //length is the size of the array Initializer
1013 //expressionPtr points on the last elt of the arrayInitializer,
1014 // in other words, it has not been decremented yet.
1015
1016 ArrayInitializer ai = new ArrayInitializer();
1017 if (length != 0) {
1018 this.expressionPtr -= length;
1019 System.arraycopy(this.expressionStack, this.expressionPtr + 1, ai.expressions = new Expression[length], 0, length);
1020 }
1021 pushOnExpressionStack(ai);
1022 //positionning
1023 ai.sourceEnd = this.endStatementPosition;
1024 ai.sourceStart = this.intStack[this.intPtr--];
1025 }
blockReal()1026 protected void blockReal() {
1027 // See consumeLocalVariableDeclarationStatement in case of change: duplicated code
1028 // increment the amount of declared variables for this block
1029 this.realBlockStack[this.realBlockPtr]++;
1030 }
1031 /*
1032 * Build initial recovery state.
1033 * Recovery state is inferred from the current state of the parser (reduced node stack).
1034 */
buildInitialRecoveryState()1035 public RecoveredElement buildInitialRecoveryState(){
1036
1037 /* initialize recovery by retrieving available reduced nodes
1038 * also rebuild bracket balance
1039 */
1040 this.lastCheckPoint = 0;
1041 this.lastErrorEndPositionBeforeRecovery = this.scanner.currentPosition;
1042
1043 RecoveredElement element = null;
1044 if (this.referenceContext instanceof CompilationUnitDeclaration){
1045 element = new RecoveredUnit(this.compilationUnit, 0, this);
1046
1047 /* ignore current stack state, since restarting from the beginnning
1048 since could not trust simple brace count */
1049 // restart recovery from scratch
1050 this.compilationUnit.currentPackage = null;
1051 this.compilationUnit.imports = null;
1052 this.compilationUnit.types = null;
1053 this.currentToken = 0;
1054 this.listLength = 0;
1055 this.listTypeParameterLength = 0;
1056 this.endPosition = 0;
1057 this.endStatementPosition = 0;
1058 return element;
1059 } else {
1060 if (this.referenceContext instanceof AbstractMethodDeclaration){
1061 element = new RecoveredMethod((AbstractMethodDeclaration) this.referenceContext, null, 0, this);
1062 this.lastCheckPoint = ((AbstractMethodDeclaration) this.referenceContext).bodyStart;
1063 if(this.statementRecoveryActivated) {
1064 element = element.add(new Block(0), 0);
1065 }
1066 } else {
1067 /* Initializer bodies are parsed in the context of the type declaration, we must thus search it inside */
1068 if (this.referenceContext instanceof TypeDeclaration){
1069 TypeDeclaration type = (TypeDeclaration) this.referenceContext;
1070 FieldDeclaration[] fieldDeclarations = type.fields;
1071 int length = fieldDeclarations == null ? 0 : fieldDeclarations.length;
1072 for (int i = 0; i < length; i++){
1073 FieldDeclaration field = fieldDeclarations[i];
1074 if (field != null
1075 && field.getKind() == AbstractVariableDeclaration.INITIALIZER
1076 && ((Initializer) field).block != null
1077 && field.declarationSourceStart <= this.scanner.initialPosition
1078 && this.scanner.initialPosition <= field.declarationSourceEnd
1079 && this.scanner.eofPosition <= field.declarationSourceEnd+1){
1080 element = new RecoveredInitializer(field, null, 1, this);
1081 this.lastCheckPoint = field.declarationSourceStart;
1082 break;
1083 }
1084 }
1085 }
1086 }
1087 }
1088
1089 if (element == null) return element;
1090
1091 for(int i = 0; i <= this.astPtr; i++){
1092 ASTNode node = this.astStack[i];
1093 if (node instanceof AbstractMethodDeclaration){
1094 AbstractMethodDeclaration method = (AbstractMethodDeclaration) node;
1095 if (method.declarationSourceEnd == 0){
1096 element = element.add(method, 0);
1097 this.lastCheckPoint = method.bodyStart;
1098 } else {
1099 element = element.add(method, 0);
1100 this.lastCheckPoint = method.declarationSourceEnd + 1;
1101 }
1102 continue;
1103 }
1104 if (node instanceof Initializer){
1105 Initializer initializer = (Initializer) node;
1106 // ignore initializer with no block
1107 if (initializer.block == null) continue;
1108 if (initializer.declarationSourceEnd == 0){
1109 element = element.add(initializer, 1);
1110 this.lastCheckPoint = initializer.sourceStart;
1111 } else {
1112 element = element.add(initializer, 0);
1113 this.lastCheckPoint = initializer.declarationSourceEnd + 1;
1114 }
1115 continue;
1116 }
1117 if (node instanceof FieldDeclaration){
1118 FieldDeclaration field = (FieldDeclaration) node;
1119 if (field.declarationSourceEnd == 0){
1120 element = element.add(field, 0);
1121 if (field.initialization == null){
1122 this.lastCheckPoint = field.sourceEnd + 1;
1123 } else {
1124 this.lastCheckPoint = field.initialization.sourceEnd + 1;
1125 }
1126 } else {
1127 element = element.add(field, 0);
1128 this.lastCheckPoint = field.declarationSourceEnd + 1;
1129 }
1130 continue;
1131 }
1132 if (node instanceof TypeDeclaration){
1133 TypeDeclaration type = (TypeDeclaration) node;
1134 if ((type.modifiers & ClassFileConstants.AccEnum) != 0) {
1135 // do not allow enums to be build as recovery types
1136 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=340691
1137 continue;
1138 }
1139 if (type.declarationSourceEnd == 0){
1140 element = element.add(type, 0);
1141 this.lastCheckPoint = type.bodyStart;
1142 } else {
1143 element = element.add(type, 0);
1144 this.lastCheckPoint = type.declarationSourceEnd + 1;
1145 }
1146 continue;
1147 }
1148 if (node instanceof ImportReference){
1149 ImportReference importRef = (ImportReference) node;
1150 element = element.add(importRef, 0);
1151 this.lastCheckPoint = importRef.declarationSourceEnd + 1;
1152 }
1153 if(this.statementRecoveryActivated) {
1154 if(node instanceof Block) {
1155 Block block = (Block) node;
1156 element = element.add(block, 0);
1157 this.lastCheckPoint = block.sourceEnd + 1;
1158 } else if(node instanceof LocalDeclaration) {
1159 LocalDeclaration statement = (LocalDeclaration) node;
1160 element = element.add(statement, 0);
1161 this.lastCheckPoint = statement.sourceEnd + 1;
1162 } else if(node instanceof Expression && ((Expression) node).isTrulyExpression()) {
1163 if(node instanceof Assignment ||
1164 node instanceof PrefixExpression ||
1165 node instanceof PostfixExpression ||
1166 node instanceof MessageSend ||
1167 node instanceof AllocationExpression) {
1168 // recover only specific expressions
1169 Expression statement = (Expression) node;
1170 element = element.add(statement, 0);
1171 if(statement.statementEnd != -1) {
1172 this.lastCheckPoint = statement.statementEnd + 1;
1173 } else {
1174 this.lastCheckPoint = statement.sourceEnd + 1;
1175 }
1176 }
1177 } else if(node instanceof Statement) {
1178 Statement statement = (Statement) node;
1179 element = element.add(statement, 0);
1180 this.lastCheckPoint = statement.sourceEnd + 1;
1181 }
1182 }
1183 }
1184
1185 if (this.statementRecoveryActivated) {
1186 if (this.pendingRecoveredType != null &&
1187 this.scanner.startPosition - 1 <= this.pendingRecoveredType.declarationSourceEnd) {
1188 // Add the pending type to the AST if this type isn't already added in the AST.
1189 element = element.add(this.pendingRecoveredType, 0);
1190 this.lastCheckPoint = this.pendingRecoveredType.declarationSourceEnd + 1;
1191 this.pendingRecoveredType = null;
1192 }
1193 }
1194 return element;
1195 }
1196
checkAndSetModifiers(int flag)1197 protected void checkAndSetModifiers(int flag){
1198 /*modify the current modifiers buffer.
1199 When the startPosition of the modifiers is 0
1200 it means that the modifier being parsed is the first
1201 of a list of several modifiers. The startPosition
1202 is zeroed when a copy of modifiers-buffer is push
1203 onto the this.astStack. */
1204
1205 if ((this.modifiers & flag) != 0){ // duplicate modifier
1206 this.modifiers |= ExtraCompilerModifiers.AccAlternateModifierProblem;
1207 }
1208 this.modifiers |= flag;
1209
1210 if (this.modifiersSourceStart < 0) this.modifiersSourceStart = this.scanner.startPosition;
1211
1212 if (this.currentElement != null) {
1213 this.currentElement.addModifier(flag, this.modifiersSourceStart);
1214 }
1215 }
checkComment()1216 public void checkComment() {
1217
1218 // discard obsolete comments while inside methods or fields initializer (see bug 74369)
1219 if (!(this.diet && this.dietInt==0) && this.scanner.commentPtr >= 0) {
1220 flushCommentsDefinedPriorTo(this.endStatementPosition);
1221 }
1222
1223 int lastComment = this.scanner.commentPtr;
1224
1225 if (this.modifiersSourceStart >= 0) {
1226 // eliminate comments located after modifierSourceStart if positioned
1227 while (lastComment >= 0) {
1228 int commentSourceStart = this.scanner.commentStarts[lastComment];
1229 if (commentSourceStart < 0) commentSourceStart = -commentSourceStart;
1230 if (commentSourceStart <= this.modifiersSourceStart) break;
1231 lastComment--;
1232 }
1233 }
1234 if (lastComment >= 0) {
1235 // consider all remaining leading comments to be part of current declaration
1236 int lastCommentStart = this.scanner.commentStarts[0];
1237 if (lastCommentStart < 0) lastCommentStart = -lastCommentStart;
1238 if (this.forStartPosition != 0 || this.forStartPosition < lastCommentStart) {// if there is no 'for' in-between.
1239 this.modifiersSourceStart = lastCommentStart;
1240 }
1241
1242 // check deprecation in last comment if javadoc (can be followed by non-javadoc comments which are simply ignored)
1243 while (lastComment >= 0 && this.scanner.commentStops[lastComment] < 0) lastComment--; // non javadoc comment have negative end positions
1244 if (lastComment >= 0 && this.javadocParser != null) {
1245 int commentEnd = this.scanner.commentStops[lastComment] - 1; //stop is one over,
1246 // do not report problem before last parsed comment while recovering code...
1247 if (this.javadocParser.shouldReportProblems) {
1248 this.javadocParser.reportProblems = this.currentElement == null || commentEnd > this.lastJavadocEnd;
1249 } else {
1250 this.javadocParser.reportProblems = false;
1251 }
1252 if (this.javadocParser.checkDeprecation(lastComment)) {
1253 checkAndSetModifiers(ClassFileConstants.AccDeprecated);
1254 }
1255 this.javadoc = this.javadocParser.docComment; // null if check javadoc is not activated
1256 if (this.currentElement == null) this.lastJavadocEnd = commentEnd;
1257 }
1258 }
1259 }
checkNonNLSAfterBodyEnd(int declarationEnd)1260 protected void checkNonNLSAfterBodyEnd(int declarationEnd){
1261 if(this.scanner.currentPosition - 1 <= declarationEnd) {
1262 this.scanner.eofPosition = declarationEnd < Integer.MAX_VALUE ? declarationEnd + 1 : declarationEnd;
1263 try {
1264 while(this.scanner.getNextToken() != TokenNameEOF){/*empty*/}
1265 } catch (InvalidInputException e) {
1266 // Nothing to do
1267 }
1268 }
1269 }
1270 protected void classInstanceCreation(boolean isQualified) {
1271 // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
1272
1273 // ClassBodyopt produces a null item on the astStak if it produces NO class body
1274 // An empty class body produces a 0 on the length stack.....
1275
1276 AllocationExpression alloc;
1277 int length;
1278 if (((length = this.astLengthStack[this.astLengthPtr--]) == 1)
1279 && (this.astStack[this.astPtr] == null)) {
1280 //NO ClassBody
1281 this.astPtr--;
1282 if (isQualified) {
1283 alloc = new QualifiedAllocationExpression();
1284 } else {
1285 alloc = new AllocationExpression();
1286 }
1287 alloc.sourceEnd = this.endPosition; //the position has been stored explicitly
1288
1289 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
1290 this.expressionPtr -= length;
1291 System.arraycopy(
1292 this.expressionStack,
1293 this.expressionPtr + 1,
1294 alloc.arguments = new Expression[length],
1295 0,
1296 length);
1297 }
1298 alloc.type = getTypeReference(0);
1299 checkForDiamond(alloc.type);
1300
1301 //the default constructor with the correct number of argument
1302 //will be created and added by the TC (see createsInternalConstructorWithBinding)
1303 alloc.sourceStart = this.intStack[this.intPtr--];
1304 pushOnExpressionStack(alloc);
1305 } else {
1306 dispatchDeclarationInto(length);
1307 TypeDeclaration anonymousTypeDeclaration = (TypeDeclaration)this.astStack[this.astPtr];
1308 anonymousTypeDeclaration.declarationSourceEnd = this.endStatementPosition;
1309 anonymousTypeDeclaration.bodyEnd = this.endStatementPosition;
1310 if (anonymousTypeDeclaration.allocation != null) {
1311 anonymousTypeDeclaration.allocation.sourceEnd = this.endStatementPosition;
1312 checkForDiamond(anonymousTypeDeclaration.allocation.type);
1313 }
1314 if (length == 0 && !containsComment(anonymousTypeDeclaration.bodyStart, anonymousTypeDeclaration.bodyEnd)) {
1315 anonymousTypeDeclaration.bits |= ASTNode.UndocumentedEmptyBlock;
1316 }
1317 this.astPtr--;
1318 this.astLengthPtr--;
1319 }
1320 }
1321 protected void checkForDiamond(TypeReference allocType) {
1322 if (allocType instanceof ParameterizedSingleTypeReference) {
1323 ParameterizedSingleTypeReference type = (ParameterizedSingleTypeReference) allocType;
1324 if (type.typeArguments == TypeReference.NO_TYPE_ARGUMENTS) {
1325 if (this.options.sourceLevel < ClassFileConstants.JDK1_7) {
1326 problemReporter().diamondNotBelow17(allocType);
1327 }
1328 if (this.options.sourceLevel > ClassFileConstants.JDK1_4) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=351965
1329 type.bits |= ASTNode.IsDiamond;
1330 } // else don't even bother to recognize this as <>
1331 }
1332 }
1333 else if (allocType instanceof ParameterizedQualifiedTypeReference) {
1334 ParameterizedQualifiedTypeReference type = (ParameterizedQualifiedTypeReference) allocType;
1335 if (type.typeArguments[type.typeArguments.length - 1] == TypeReference.NO_TYPE_ARGUMENTS) { // Don't care for X<>.Y<> and X<>.Y<String>
1336 if (this.options.sourceLevel < ClassFileConstants.JDK1_7) {
1337 problemReporter().diamondNotBelow17(allocType, type.typeArguments.length - 1);
1338 }
1339 if (this.options.sourceLevel > ClassFileConstants.JDK1_4) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=351965
1340 type.bits |= ASTNode.IsDiamond;
1341 } // else don't even bother to recognize this as <>
1342 }
1343 }
1344 }
1345 protected ParameterizedQualifiedTypeReference computeQualifiedGenericsFromRightSide(TypeReference rightSide, int dim, Annotation [][] annotationsOnDimensions) {
1346 int nameSize = this.identifierLengthStack[this.identifierLengthPtr];
1347 int tokensSize = nameSize;
1348 if (rightSide instanceof ParameterizedSingleTypeReference) {
1349 tokensSize ++;
1350 } else if (rightSide instanceof SingleTypeReference) {
1351 tokensSize ++;
1352 } else if (rightSide instanceof ParameterizedQualifiedTypeReference) {
1353 tokensSize += ((QualifiedTypeReference) rightSide).tokens.length;
1354 } else if (rightSide instanceof QualifiedTypeReference) {
1355 tokensSize += ((QualifiedTypeReference) rightSide).tokens.length;
1356 }
1357 TypeReference[][] typeArguments = new TypeReference[tokensSize][];
1358 char[][] tokens = new char[tokensSize][];
1359 long[] positions = new long[tokensSize];
1360 Annotation [][] typeAnnotations = null;
1361 if (rightSide instanceof ParameterizedSingleTypeReference) {
1362 ParameterizedSingleTypeReference singleParameterizedTypeReference = (ParameterizedSingleTypeReference) rightSide;
1363 tokens[nameSize] = singleParameterizedTypeReference.token;
1364 positions[nameSize] = (((long) singleParameterizedTypeReference.sourceStart) << 32) + singleParameterizedTypeReference.sourceEnd;
1365 typeArguments[nameSize] = singleParameterizedTypeReference.typeArguments;
1366 if (singleParameterizedTypeReference.annotations != null) {
1367 typeAnnotations = new Annotation[tokensSize][];
1368 typeAnnotations[nameSize] = singleParameterizedTypeReference.annotations[0];
1369 }
1370 } else if (rightSide instanceof SingleTypeReference) {
1371 SingleTypeReference singleTypeReference = (SingleTypeReference) rightSide;
1372 tokens[nameSize] = singleTypeReference.token;
1373 positions[nameSize] = (((long) singleTypeReference.sourceStart) << 32) + singleTypeReference.sourceEnd;
1374 if (singleTypeReference.annotations != null) {
1375 typeAnnotations = new Annotation[tokensSize][];
1376 typeAnnotations[nameSize] = singleTypeReference.annotations[0];
1377 }
1378 } else if (rightSide instanceof ParameterizedQualifiedTypeReference) {
1379 ParameterizedQualifiedTypeReference parameterizedTypeReference = (ParameterizedQualifiedTypeReference) rightSide;
1380 TypeReference[][] rightSideTypeArguments = parameterizedTypeReference.typeArguments;
1381 System.arraycopy(rightSideTypeArguments, 0, typeArguments, nameSize, rightSideTypeArguments.length);
1382 char[][] rightSideTokens = parameterizedTypeReference.tokens;
1383 System.arraycopy(rightSideTokens, 0, tokens, nameSize, rightSideTokens.length);
1384 long[] rightSidePositions = parameterizedTypeReference.sourcePositions;
1385 System.arraycopy(rightSidePositions, 0, positions, nameSize, rightSidePositions.length);
1386 Annotation [][] rightSideAnnotations = parameterizedTypeReference.annotations;
1387 if (rightSideAnnotations != null) {
1388 typeAnnotations = new Annotation[tokensSize][];
1389 System.arraycopy(rightSideAnnotations, 0, typeAnnotations, nameSize, rightSideAnnotations.length);
1390 }
1391 } else if (rightSide instanceof QualifiedTypeReference) {
1392 QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) rightSide;
1393 char[][] rightSideTokens = qualifiedTypeReference.tokens;
1394 System.arraycopy(rightSideTokens, 0, tokens, nameSize, rightSideTokens.length);
1395 long[] rightSidePositions = qualifiedTypeReference.sourcePositions;
1396 System.arraycopy(rightSidePositions, 0, positions, nameSize, rightSidePositions.length);
1397 Annotation [][] rightSideAnnotations = qualifiedTypeReference.annotations;
1398 if (rightSideAnnotations != null) {
1399 typeAnnotations = new Annotation[tokensSize][];
1400 System.arraycopy(rightSideAnnotations, 0, typeAnnotations, nameSize, rightSideAnnotations.length);
1401 }
1402 }
1403
1404 int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
1405 TypeReference[] currentTypeArguments = new TypeReference[currentTypeArgumentsLength];
1406 this.genericsPtr -= currentTypeArgumentsLength;
1407 System.arraycopy(this.genericsStack, this.genericsPtr + 1, currentTypeArguments, 0, currentTypeArgumentsLength);
1408
1409 if (nameSize == 1) {
1410 tokens[0] = this.identifierStack[this.identifierPtr];
1411 positions[0] = this.identifierPositionStack[this.identifierPtr--];
1412 typeArguments[0] = currentTypeArguments;
1413 } else {
1414 this.identifierPtr -= nameSize;
1415 System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, nameSize);
1416 System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, nameSize);
1417 typeArguments[nameSize - 1] = currentTypeArguments;
1418 }
1419 this.identifierLengthPtr--;
1420 ParameterizedQualifiedTypeReference typeRef = new ParameterizedQualifiedTypeReference(tokens, typeArguments, dim, annotationsOnDimensions, positions);
1421
1422 while (nameSize > 0) {
1423 int length;
1424 if ((length = this.typeAnnotationLengthStack[this.typeAnnotationLengthPtr--]) != 0) {
1425 if (typeAnnotations == null)
1426 typeAnnotations = new Annotation[tokensSize][];
1427 System.arraycopy(
1428 this.typeAnnotationStack,
1429 (this.typeAnnotationPtr -= length) + 1,
1430 typeAnnotations[nameSize - 1] = new Annotation[length],
1431 0,
1432 length);
1433 if (nameSize == 1) {
1434 typeRef.sourceStart = typeAnnotations[0][0].sourceStart;
1435 }
1436 }
1437 nameSize--;
1438 }
1439
1440 if ((typeRef.annotations = typeAnnotations) != null) {
1441 typeRef.bits |= ASTNode.HasTypeAnnotations;
1442 }
1443 return typeRef;
1444 }
1445 protected void concatExpressionLists() {
1446 this.expressionLengthStack[--this.expressionLengthPtr]++;
1447 }
1448 protected void concatGenericsLists() {
1449 this.genericsLengthStack[this.genericsLengthPtr - 1] += this.genericsLengthStack[this.genericsLengthPtr--];
1450 }
1451 protected void concatNodeLists() {
1452 /*
1453 * This is a case where you have two sublists into the this.astStack that you want
1454 * to merge in one list. There is no action required on the this.astStack. The only
1455 * thing you need to do is merge the two lengths specified on the astStackLength.
1456 * The top two length are for example:
1457 * ... p n
1458 * and you want to result in a list like:
1459 * ... n+p
1460 * This means that the p could be equals to 0 in case there is no astNode pushed
1461 * on the this.astStack.
1462 * Look at the InterfaceMemberDeclarations for an example.
1463 */
1464
1465 this.astLengthStack[this.astLengthPtr - 1] += this.astLengthStack[this.astLengthPtr--];
1466 }
1467 protected void consumeAdditionalBound() {
1468 pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));
1469 }
1470 protected void consumeAdditionalBound1() {
1471 // nothing to be done.
1472 // The reference type1 is consumed by consumeReferenceType1 method.
1473 }
1474 protected void consumeAdditionalBoundList() {
1475 concatGenericsLists();
1476 }
1477 protected void consumeAdditionalBoundList1() {
1478 concatGenericsLists();
1479 }
1480 protected boolean isIndirectlyInsideLambdaExpression() {
1481 return false;
1482 }
1483 protected void consumeAllocationHeader() {
1484 // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
1485
1486 // ClassBodyopt produces a null item on the astStak if it produces NO class body
1487 // An empty class body produces a 0 on the length stack.....
1488
1489 if (this.currentElement == null){
1490 return; // should never occur, this consumeRule is only used in recovery mode
1491 }
1492 if (this.currentToken == TokenNameLBRACE){
1493 // beginning of an anonymous type
1494 TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult);
1495 anonymousType.name = CharOperation.NO_CHAR;
1496 anonymousType.bits |= (ASTNode.IsAnonymousType|ASTNode.IsLocalType);
1497 anonymousType.sourceStart = this.intStack[this.intPtr--];
1498 anonymousType.declarationSourceStart = anonymousType.sourceStart;
1499 anonymousType.sourceEnd = this.rParenPos; // closing parenthesis
1500 QualifiedAllocationExpression alloc = new QualifiedAllocationExpression(anonymousType);
1501 alloc.type = getTypeReference(0);
1502 alloc.sourceStart = anonymousType.sourceStart;
1503 alloc.sourceEnd = anonymousType.sourceEnd ;
1504 this.lastCheckPoint = anonymousType.bodyStart = this.scanner.currentPosition;
1505 this.currentElement = this.currentElement.add(anonymousType, 0);
1506 this.lastIgnoredToken = -1;
1507 if (isIndirectlyInsideLambdaExpression())
1508 this.ignoreNextOpeningBrace = true;
1509 else
1510 this.currentToken = 0; // opening brace already taken into account
1511 return;
1512 }
1513 this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
1514 this.restartRecovery = true; // request to restart from here on
1515 }
1516 protected void consumeAnnotationAsModifier() {
1517 Expression expression = this.expressionStack[this.expressionPtr];
1518 int sourceStart = expression.sourceStart;
1519 if (this.modifiersSourceStart < 0) {
1520 this.modifiersSourceStart = sourceStart;
1521 }
1522 }
1523 protected void consumeAnnotationName() {
1524 if(this.currentElement != null && !this.expectTypeAnnotation) {
1525 int start = this.intStack[this.intPtr];
1526 int end = (int) (this.identifierPositionStack[this.identifierPtr] & 0x00000000FFFFFFFFL);
1527 annotationRecoveryCheckPoint(start, end);
1528
1529 if (this.annotationRecoveryActivated) {
1530 this.currentElement = this.currentElement.addAnnotationName(this.identifierPtr, this.identifierLengthPtr, start, 0);
1531 }
1532 }
1533 this.recordStringLiterals = false;
1534 this.expectTypeAnnotation = false;
1535 }
1536 protected void consumeAnnotationTypeDeclaration() {
1537 int length;
1538 if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
1539 //there are length declarations
1540 //dispatch according to the type of the declarations
1541 dispatchDeclarationInto(length);
1542 }
1543
1544 TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
1545
1546 //convert constructor that do not have the type's name into methods
1547 typeDecl.checkConstructors(this);
1548
1549 //always add <clinit> (will be remove at code gen time if empty)
1550 if (this.scanner.containsAssertKeyword) {
1551 typeDecl.bits |= ASTNode.ContainsAssertion;
1552 }
1553 typeDecl.addClinit();
1554 typeDecl.bodyEnd = this.endStatementPosition;
1555 if (length == 0 && !containsComment(typeDecl.bodyStart, typeDecl.bodyEnd)) {
1556 typeDecl.bits |= ASTNode.UndocumentedEmptyBlock;
1557 }
1558 typeDecl.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
1559 }
1560 protected void consumeAnnotationTypeDeclarationHeader() {
1561 TypeDeclaration annotationTypeDeclaration = (TypeDeclaration) this.astStack[this.astPtr];
1562 if (this.currentToken == TokenNameLBRACE) {
1563 annotationTypeDeclaration.bodyStart = this.scanner.currentPosition;
1564 }
1565 if (this.currentElement != null) {
1566 this.restartRecovery = true; // used to avoid branching back into the regular automaton
1567 }
1568 // flush the comments related to the annotation type header
1569 this.scanner.commentPtr = -1;
1570 }
1571 protected void consumeAnnotationTypeDeclarationHeaderName() {
1572 // consumeAnnotationTypeDeclarationHeader ::= Modifiers '@' PushModifiers interface Identifier
1573 // consumeAnnotationTypeDeclarationHeader ::= '@' PushModifiers interface Identifier
1574 TypeDeclaration annotationTypeDeclaration = new TypeDeclaration(this.compilationUnit.compilationResult);
1575 if (this.nestedMethod[this.nestedType] == 0) {
1576 if (this.nestedType != 0) {
1577 annotationTypeDeclaration.bits |= ASTNode.IsMemberType;
1578 }
1579 } else {
1580 // Record that the block has a declaration for local types
1581 annotationTypeDeclaration.bits |= ASTNode.IsLocalType;
1582 markEnclosingMemberWithLocalType();
1583 blockReal();
1584 }
1585
1586 //highlight the name of the type
1587 long pos = this.identifierPositionStack[this.identifierPtr];
1588 annotationTypeDeclaration.sourceEnd = (int) pos;
1589 annotationTypeDeclaration.sourceStart = (int) (pos >>> 32);
1590 annotationTypeDeclaration.name = this.identifierStack[this.identifierPtr--];
1591 this.identifierLengthPtr--;
1592
1593 //compute the declaration source too
1594 // 'interface' push two int positions: the beginning of the class token and its end.
1595 // we want to keep the beginning position but get rid of the end position
1596 // it is only used for the ClassLiteralAccess positions.
1597 this.intPtr--; // remove the start position of the interface token
1598 this.intPtr--; // remove the end position of the interface token
1599
1600 annotationTypeDeclaration.modifiersSourceStart = this.intStack[this.intPtr--];
1601 annotationTypeDeclaration.modifiers = this.intStack[this.intPtr--] | ClassFileConstants.AccAnnotation | ClassFileConstants.AccInterface;
1602 if (annotationTypeDeclaration.modifiersSourceStart >= 0) {
1603 annotationTypeDeclaration.declarationSourceStart = annotationTypeDeclaration.modifiersSourceStart;
1604 this.intPtr--; // remove the position of the '@' token as we have modifiers
1605 } else {
1606 int atPosition = this.intStack[this.intPtr--];
1607 // remove the position of the '@' token as we don't have modifiers
1608 annotationTypeDeclaration.declarationSourceStart = atPosition;
1609 }
1610
1611 // Store secondary info
1612 if ((annotationTypeDeclaration.bits & ASTNode.IsMemberType) == 0 && (annotationTypeDeclaration.bits & ASTNode.IsLocalType) == 0) {
1613 if (this.compilationUnit != null && !CharOperation.equals(annotationTypeDeclaration.name, this.compilationUnit.getMainTypeName())) {
1614 annotationTypeDeclaration.bits |= ASTNode.IsSecondaryType;
1615 }
1616 }
1617
1618 // consume annotations
1619 int length;
1620 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
1621 System.arraycopy(
1622 this.expressionStack,
1623 (this.expressionPtr -= length) + 1,
1624 annotationTypeDeclaration.annotations = new Annotation[length],
1625 0,
1626 length);
1627 }
1628 annotationTypeDeclaration.bodyStart = annotationTypeDeclaration.sourceEnd + 1;
1629
1630 // javadoc
1631 annotationTypeDeclaration.javadoc = this.javadoc;
1632 this.javadoc = null;
1633 pushOnAstStack(annotationTypeDeclaration);
1634 if(!this.statementRecoveryActivated &&
1635 this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
1636 this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
1637 problemReporter().invalidUsageOfAnnotationDeclarations(annotationTypeDeclaration);
1638 }
1639
1640 // recovery
1641 if (this.currentElement != null){
1642 this.lastCheckPoint = annotationTypeDeclaration.bodyStart;
1643 this.currentElement = this.currentElement.add(annotationTypeDeclaration, 0);
1644 this.lastIgnoredToken = -1;
1645 }
1646 }
1647 protected void consumeAnnotationTypeDeclarationHeaderNameWithTypeParameters() {
1648 // consumeAnnotationTypeDeclarationHeader ::= Modifiers '@' PushModifiers interface Identifier TypeParameters
1649 // consumeAnnotationTypeDeclarationHeader ::= '@' PushModifiers interface Identifier TypeParameters
1650 TypeDeclaration annotationTypeDeclaration = new TypeDeclaration(this.compilationUnit.compilationResult);
1651 // consume type parameters
1652 int length = this.genericsLengthStack[this.genericsLengthPtr--];
1653 this.genericsPtr -= length;
1654 System.arraycopy(this.genericsStack, this.genericsPtr + 1, annotationTypeDeclaration.typeParameters = new TypeParameter[length], 0, length);
1655
1656 problemReporter().invalidUsageOfTypeParametersForAnnotationDeclaration(annotationTypeDeclaration);
1657
1658 annotationTypeDeclaration.bodyStart = annotationTypeDeclaration.typeParameters[length-1].declarationSourceEnd + 1;
1659
1660 // annotationTypeDeclaration.typeParameters = null;
1661
1662 this.listTypeParameterLength = 0;
1663
1664 if (this.nestedMethod[this.nestedType] == 0) {
1665 if (this.nestedType != 0) {
1666 annotationTypeDeclaration.bits |= ASTNode.IsMemberType;
1667 }
1668 } else {
1669 // Record that the block has a declaration for local types
1670 annotationTypeDeclaration.bits |= ASTNode.IsLocalType;
1671 markEnclosingMemberWithLocalType();
1672 blockReal();
1673 }
1674
1675 //highlight the name of the type
1676 long pos = this.identifierPositionStack[this.identifierPtr];
1677 annotationTypeDeclaration.sourceEnd = (int) pos;
1678 annotationTypeDeclaration.sourceStart = (int) (pos >>> 32);
1679 annotationTypeDeclaration.name = this.identifierStack[this.identifierPtr--];
1680 this.identifierLengthPtr--;
1681
1682 //compute the declaration source too
1683 // 'interface' push two int positions: the beginning of the class token and its end.
1684 // we want to keep the beginning position but get rid of the end position
1685 // it is only used for the ClassLiteralAccess positions.
1686 this.intPtr--; // remove the start position of the interface token
1687 this.intPtr--; // remove the end position of the interface token
1688
1689 annotationTypeDeclaration.modifiersSourceStart = this.intStack[this.intPtr--];
1690 annotationTypeDeclaration.modifiers = this.intStack[this.intPtr--] | ClassFileConstants.AccAnnotation | ClassFileConstants.AccInterface;
1691 if (annotationTypeDeclaration.modifiersSourceStart >= 0) {
1692 annotationTypeDeclaration.declarationSourceStart = annotationTypeDeclaration.modifiersSourceStart;
1693 this.intPtr--; // remove the position of the '@' token as we have modifiers
1694 } else {
1695 int atPosition = this.intStack[this.intPtr--];
1696 // remove the position of the '@' token as we don't have modifiers
1697 annotationTypeDeclaration.declarationSourceStart = atPosition;
1698 }
1699
1700 // Store secondary info
1701 if ((annotationTypeDeclaration.bits & ASTNode.IsMemberType) == 0 && (annotationTypeDeclaration.bits & ASTNode.IsLocalType) == 0) {
1702 if (this.compilationUnit != null && !CharOperation.equals(annotationTypeDeclaration.name, this.compilationUnit.getMainTypeName())) {
1703 annotationTypeDeclaration.bits |= ASTNode.IsSecondaryType;
1704 }
1705 }
1706
1707 // consume annotations
1708 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
1709 System.arraycopy(
1710 this.expressionStack,
1711 (this.expressionPtr -= length) + 1,
1712 annotationTypeDeclaration.annotations = new Annotation[length],
1713 0,
1714 length);
1715 }
1716 // javadoc
1717 annotationTypeDeclaration.javadoc = this.javadoc;
1718 this.javadoc = null;
1719 pushOnAstStack(annotationTypeDeclaration);
1720 if(!this.statementRecoveryActivated &&
1721 this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
1722 this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
1723 problemReporter().invalidUsageOfAnnotationDeclarations(annotationTypeDeclaration);
1724 }
1725
1726 // recovery
1727 if (this.currentElement != null){
1728 this.lastCheckPoint = annotationTypeDeclaration.bodyStart;
1729 this.currentElement = this.currentElement.add(annotationTypeDeclaration, 0);
1730 this.lastIgnoredToken = -1;
1731 }
1732 }
consumeAnnotationTypeMemberDeclaration()1733 protected void consumeAnnotationTypeMemberDeclaration() {
1734 // AnnotationTypeMemberDeclaration ::= AnnotationTypeMemberDeclarationHeader AnnotationTypeMemberHeaderExtendedDims DefaultValueopt ';'
1735 AnnotationMethodDeclaration annotationTypeMemberDeclaration = (AnnotationMethodDeclaration) this.astStack[this.astPtr];
1736 annotationTypeMemberDeclaration.modifiers |= ExtraCompilerModifiers.AccSemicolonBody;
1737 // store the this.endPosition (position just before the '}') in case there is
1738 // a trailing comment behind the end of the method
1739 int declarationEndPosition = flushCommentsDefinedPriorTo(this.endStatementPosition);
1740 annotationTypeMemberDeclaration.bodyStart = this.endStatementPosition;
1741 annotationTypeMemberDeclaration.bodyEnd = declarationEndPosition;
1742 annotationTypeMemberDeclaration.declarationSourceEnd = declarationEndPosition;
1743 }
consumeAnnotationTypeMemberDeclarations()1744 protected void consumeAnnotationTypeMemberDeclarations() {
1745 // AnnotationTypeMemberDeclarations ::= AnnotationTypeMemberDeclarations AnnotationTypeMemberDeclaration
1746 concatNodeLists();
1747 }
consumeAnnotationTypeMemberDeclarationsopt()1748 protected void consumeAnnotationTypeMemberDeclarationsopt() {
1749 this.nestedType-- ;
1750 }
consumeArgumentList()1751 protected void consumeArgumentList() {
1752 // ArgumentList ::= ArgumentList ',' Expression
1753 concatExpressionLists();
1754 }
consumeArguments()1755 protected void consumeArguments() {
1756 // Arguments ::= '(' ArgumentListopt ')'
1757 // nothing to do, the expression stack is already updated
1758 pushOnIntStack(this.rParenPos);
1759 }
consumeArrayAccess(boolean unspecifiedReference)1760 protected void consumeArrayAccess(boolean unspecifiedReference) {
1761 // ArrayAccess ::= Name '[' Expression ']' ==> true
1762 // ArrayAccess ::= PrimaryNoNewArray '[' Expression ']' ==> false
1763
1764
1765 //optimize push/pop
1766 Expression exp;
1767 if (unspecifiedReference) {
1768 exp =
1769 this.expressionStack[this.expressionPtr] =
1770 new ArrayReference(
1771 getUnspecifiedReferenceOptimized(),
1772 this.expressionStack[this.expressionPtr]);
1773 } else {
1774 this.expressionPtr--;
1775 this.expressionLengthPtr--;
1776 exp =
1777 this.expressionStack[this.expressionPtr] =
1778 new ArrayReference(
1779 this.expressionStack[this.expressionPtr],
1780 this.expressionStack[this.expressionPtr + 1]);
1781 }
1782 exp.sourceEnd = this.endStatementPosition;
1783 }
consumeArrayCreationExpressionWithInitializer()1784 protected void consumeArrayCreationExpressionWithInitializer() {
1785 // ArrayCreationWithArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializer
1786 // ArrayCreationWithArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializer
1787
1788 int length;
1789 ArrayAllocationExpression arrayAllocation = new ArrayAllocationExpression();
1790 this.expressionLengthPtr -- ;
1791 arrayAllocation.initializer = (ArrayInitializer) this.expressionStack[this.expressionPtr--];
1792
1793 length = (this.expressionLengthStack[this.expressionLengthPtr--]);
1794 this.expressionPtr -= length ;
1795 System.arraycopy(
1796 this.expressionStack,
1797 this.expressionPtr+1,
1798 arrayAllocation.dimensions = new Expression[length],
1799 0,
1800 length);
1801 Annotation[][] annotationsOnDimensions = getAnnotationsOnDimensions(length);
1802 arrayAllocation.annotationsOnDimensions = annotationsOnDimensions;
1803
1804 arrayAllocation.type = getTypeReference(0);
1805 arrayAllocation.type.bits |= ASTNode.IgnoreRawTypeCheck; // no need to worry about raw type usage
1806 if (annotationsOnDimensions != null) {
1807 arrayAllocation.bits |= ASTNode.HasTypeAnnotations;
1808 arrayAllocation.type.bits |= ASTNode.HasTypeAnnotations;
1809 }
1810
1811 arrayAllocation.sourceStart = this.intStack[this.intPtr--];
1812 if (arrayAllocation.initializer == null) {
1813 arrayAllocation.sourceEnd = this.endStatementPosition;
1814 } else {
1815 arrayAllocation.sourceEnd = arrayAllocation.initializer.sourceEnd ;
1816 }
1817 pushOnExpressionStack(arrayAllocation);
1818 }
consumeArrayCreationExpressionWithoutInitializer()1819 protected void consumeArrayCreationExpressionWithoutInitializer() {
1820 // ArrayCreationWithoutArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs
1821 // ArrayCreationWithoutArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs
1822
1823 int length;
1824 ArrayAllocationExpression arrayAllocation = new ArrayAllocationExpression();
1825 length = (this.expressionLengthStack[this.expressionLengthPtr--]);
1826 this.expressionPtr -= length ;
1827 System.arraycopy(
1828 this.expressionStack,
1829 this.expressionPtr+1,
1830 arrayAllocation.dimensions = new Expression[length],
1831 0,
1832 length);
1833 Annotation[][] annotationsOnDimensions = getAnnotationsOnDimensions(length);
1834 arrayAllocation.annotationsOnDimensions = annotationsOnDimensions;
1835 arrayAllocation.type = getTypeReference(0);
1836 arrayAllocation.type.bits |= ASTNode.IgnoreRawTypeCheck; // no need to worry about raw type usage
1837 if (annotationsOnDimensions != null) {
1838 arrayAllocation.bits |= ASTNode.HasTypeAnnotations;
1839 arrayAllocation.type.bits |= ASTNode.HasTypeAnnotations;
1840 }
1841 arrayAllocation.sourceStart = this.intStack[this.intPtr--];
1842 if (arrayAllocation.initializer == null) {
1843 arrayAllocation.sourceEnd = this.endStatementPosition;
1844 } else {
1845 arrayAllocation.sourceEnd = arrayAllocation.initializer.sourceEnd ;
1846 }
1847 pushOnExpressionStack(arrayAllocation);
1848 }
consumeArrayCreationHeader()1849 protected void consumeArrayCreationHeader() {
1850 // nothing to do
1851 }
consumeArrayInitializer()1852 protected void consumeArrayInitializer() {
1853 // ArrayInitializer ::= '{' VariableInitializers '}'
1854 // ArrayInitializer ::= '{' VariableInitializers , '}'
1855
1856 arrayInitializer(this.expressionLengthStack[this.expressionLengthPtr--]);
1857 }
consumeArrayTypeWithTypeArgumentsName()1858 protected void consumeArrayTypeWithTypeArgumentsName() {
1859 this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr] += this.identifierLengthStack[this.identifierLengthPtr];
1860 pushOnGenericsLengthStack(0); // handle type arguments
1861 }
consumeAssertStatement()1862 protected void consumeAssertStatement() {
1863 // AssertStatement ::= 'assert' Expression ':' Expression ';'
1864 this.expressionLengthPtr-=2;
1865 pushOnAstStack(new AssertStatement(this.expressionStack[this.expressionPtr--], this.expressionStack[this.expressionPtr--], this.intStack[this.intPtr--]));
1866 }
consumeAssignment()1867 protected void consumeAssignment() {
1868 // Assignment ::= LeftHandSide AssignmentOperator AssignmentExpression
1869 //optimize the push/pop
1870
1871 int op = this.intStack[this.intPtr--] ; //<--the encoded operator
1872
1873 this.expressionPtr -- ; this.expressionLengthPtr -- ;
1874 Expression expression = this.expressionStack[this.expressionPtr+1];
1875 this.expressionStack[this.expressionPtr] =
1876 (op != EQUAL ) ?
1877 new CompoundAssignment(
1878 this.expressionStack[this.expressionPtr] ,
1879 expression,
1880 op,
1881 expression.sourceEnd):
1882 new Assignment(
1883 this.expressionStack[this.expressionPtr] ,
1884 expression,
1885 expression.sourceEnd);
1886
1887 if (this.pendingRecoveredType != null) {
1888 // Used only in statements recovery.
1889 // This is not a real assignment but a placeholder for an existing anonymous type.
1890 // The assignment must be replace by the anonymous type.
1891 if (this.pendingRecoveredType.allocation != null &&
1892 this.scanner.startPosition - 1 <= this.pendingRecoveredType.declarationSourceEnd) {
1893 this.expressionStack[this.expressionPtr] = this.pendingRecoveredType.allocation;
1894 this.pendingRecoveredType = null;
1895 return;
1896 }
1897 this.pendingRecoveredType = null;
1898 }
1899 }
consumeAssignmentOperator(int pos)1900 protected void consumeAssignmentOperator(int pos) {
1901 // AssignmentOperator ::= '='
1902 // AssignmentOperator ::= '*='
1903 // AssignmentOperator ::= '/='
1904 // AssignmentOperator ::= '%='
1905 // AssignmentOperator ::= '+='
1906 // AssignmentOperator ::= '-='
1907 // AssignmentOperator ::= '<<='
1908 // AssignmentOperator ::= '>>='
1909 // AssignmentOperator ::= '>>>='
1910 // AssignmentOperator ::= '&='
1911 // AssignmentOperator ::= '^='
1912 // AssignmentOperator ::= '|='
1913
1914 pushOnIntStack(pos);
1915 }
consumeBinaryExpression(int op)1916 protected void consumeBinaryExpression(int op) {
1917 // MultiplicativeExpression ::= MultiplicativeExpression '*' UnaryExpression
1918 // MultiplicativeExpression ::= MultiplicativeExpression '/' UnaryExpression
1919 // MultiplicativeExpression ::= MultiplicativeExpression '%' UnaryExpression
1920 // AdditiveExpression ::= AdditiveExpression '+' MultiplicativeExpression
1921 // AdditiveExpression ::= AdditiveExpression '-' MultiplicativeExpression
1922 // ShiftExpression ::= ShiftExpression '<<' AdditiveExpression
1923 // ShiftExpression ::= ShiftExpression '>>' AdditiveExpression
1924 // ShiftExpression ::= ShiftExpression '>>>' AdditiveExpression
1925 // RelationalExpression ::= RelationalExpression '<' ShiftExpression
1926 // RelationalExpression ::= RelationalExpression '>' ShiftExpression
1927 // RelationalExpression ::= RelationalExpression '<=' ShiftExpression
1928 // RelationalExpression ::= RelationalExpression '>=' ShiftExpression
1929 // AndExpression ::= AndExpression '&' EqualityExpression
1930 // ExclusiveOrExpression ::= ExclusiveOrExpression '^' AndExpression
1931 // InclusiveOrExpression ::= InclusiveOrExpression '|' ExclusiveOrExpression
1932 // ConditionalAndExpression ::= ConditionalAndExpression '&&' InclusiveOrExpression
1933 // ConditionalOrExpression ::= ConditionalOrExpression '||' ConditionalAndExpression
1934
1935 //optimize the push/pop
1936
1937 this.expressionPtr--;
1938 this.expressionLengthPtr--;
1939 Expression expr1 = this.expressionStack[this.expressionPtr];
1940 Expression expr2 = this.expressionStack[this.expressionPtr + 1];
1941 switch(op) {
1942 case OR_OR :
1943 this.expressionStack[this.expressionPtr] =
1944 new OR_OR_Expression(
1945 expr1,
1946 expr2,
1947 op);
1948 break;
1949 case AND_AND :
1950 this.expressionStack[this.expressionPtr] =
1951 new AND_AND_Expression(
1952 expr1,
1953 expr2,
1954 op);
1955 break;
1956 case PLUS :
1957 // look for "string1" + "string2"
1958 if (this.optimizeStringLiterals) {
1959 if (expr1 instanceof StringLiteral) {
1960 if (((expr1.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0) {
1961 if (expr2 instanceof CharLiteral) { // string+char
1962 this.expressionStack[this.expressionPtr] =
1963 ((StringLiteral) expr1).extendWith((CharLiteral) expr2);
1964 } else if (expr2 instanceof StringLiteral) { //string+string
1965 this.expressionStack[this.expressionPtr] =
1966 ((StringLiteral) expr1).extendWith((StringLiteral) expr2);
1967 } else {
1968 this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
1969 }
1970 } else {
1971 this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
1972 }
1973 } else if (expr1 instanceof CombinedBinaryExpression) {
1974 CombinedBinaryExpression cursor;
1975 // left branch is comprised of PLUS BEs
1976 // cursor is shifted upwards, while needed BEs are added
1977 // on demand; past the arityMax-th
1978 // consecutive BE, a CBE is inserted that holds a
1979 // full-fledged references table
1980 if ((cursor = (CombinedBinaryExpression)expr1).arity < cursor.arityMax) {
1981 cursor.left = new BinaryExpression(cursor);
1982 cursor.arity++;
1983 } else {
1984 cursor.left = new CombinedBinaryExpression(cursor);
1985 cursor.arity = 0;
1986 cursor.tuneArityMax();
1987 }
1988 cursor.right = expr2;
1989 cursor.sourceEnd = expr2.sourceEnd;
1990 this.expressionStack[this.expressionPtr] = cursor;
1991 // BE_INSTRUMENTATION: neutralized in the released code
1992 // cursor.depthTracker = ((BinaryExpression)cursor.left).
1993 // depthTracker + 1;
1994 } else if (expr1 instanceof BinaryExpression &&
1995 // single out the a + b case, which is a BE
1996 // instead of a CBE (slightly more than a half of
1997 // strings concatenation are one-deep binary
1998 // expressions)
1999 ((expr1.bits & ASTNode.OperatorMASK) >>
2000 ASTNode.OperatorSHIFT) == OperatorIds.PLUS) {
2001 this.expressionStack[this.expressionPtr] =
2002 new CombinedBinaryExpression(expr1, expr2, PLUS, 1);
2003 } else {
2004 this.expressionStack[this.expressionPtr] =
2005 new BinaryExpression(expr1, expr2, PLUS);
2006 }
2007 } else if (expr1 instanceof StringLiteral) {
2008 if (expr2 instanceof StringLiteral
2009 && ((expr1.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0) {
2010 // string + string
2011 this.expressionStack[this.expressionPtr] =
2012 ((StringLiteral) expr1).extendsWith((StringLiteral) expr2);
2013 } else {
2014 // single out the a + b case
2015 this.expressionStack[this.expressionPtr] =
2016 new BinaryExpression(expr1, expr2, PLUS);
2017 }
2018 } else if (expr1 instanceof CombinedBinaryExpression) {
2019 CombinedBinaryExpression cursor;
2020 // shift cursor; create BE/CBE as needed
2021 if ((cursor = (CombinedBinaryExpression)expr1).arity < cursor.arityMax) {
2022 cursor.left = new BinaryExpression(cursor);
2023 // clear the bits on cursor
2024 cursor.bits &= ~ASTNode.ParenthesizedMASK;
2025 cursor.arity++;
2026 } else {
2027 cursor.left = new CombinedBinaryExpression(cursor);
2028 // clear the bits on cursor
2029 cursor.bits &= ~ASTNode.ParenthesizedMASK;
2030 cursor.arity = 0;
2031 cursor.tuneArityMax();
2032 }
2033 cursor.right = expr2;
2034 cursor.sourceEnd = expr2.sourceEnd;
2035 // BE_INSTRUMENTATION: neutralized in the released code
2036 // cursor.depthTracker = ((BinaryExpression)cursor.left).
2037 // depthTracker + 1;
2038 this.expressionStack[this.expressionPtr] = cursor;
2039 } else if (expr1 instanceof BinaryExpression
2040 && ((expr1.bits & ASTNode.OperatorMASK) >>
2041 ASTNode.OperatorSHIFT) == OperatorIds.PLUS) {
2042 // single out the a + b case
2043 this.expressionStack[this.expressionPtr] =
2044 new CombinedBinaryExpression(expr1, expr2, PLUS, 1);
2045 } else {
2046 this.expressionStack[this.expressionPtr] =
2047 new BinaryExpression(expr1, expr2, PLUS);
2048 }
2049 break;
2050 case LESS :
2051 case MULTIPLY :
2052 this.intPtr--; // star end position or starting position of angle bracket
2053 this.expressionStack[this.expressionPtr] =
2054 new BinaryExpression(
2055 expr1,
2056 expr2,
2057 op);
2058 break;
2059 default :
2060 this.expressionStack[this.expressionPtr] =
2061 new BinaryExpression(
2062 expr1,
2063 expr2,
2064 op);
2065 }
2066 }
2067 /**
2068 * @param op binary operator
2069 */
consumeBinaryExpressionWithName(int op)2070 protected void consumeBinaryExpressionWithName(int op) {
2071 pushOnExpressionStack(getUnspecifiedReferenceOptimized());
2072 this.expressionPtr--;
2073 this.expressionLengthPtr--;
2074 /*
2075 if (op == OR_OR) {
2076 this.expressionStack[this.expressionPtr] =
2077 new OR_OR_Expression(
2078 this.expressionStack[this.expressionPtr + 1],
2079 this.expressionStack[this.expressionPtr],
2080 op);
2081 } else {
2082 if (op == AND_AND) {
2083 this.expressionStack[this.expressionPtr] =
2084 new AND_AND_Expression(
2085 this.expressionStack[this.expressionPtr + 1],
2086 this.expressionStack[this.expressionPtr],
2087 op);
2088 } else {
2089 // look for "string1" + "string2"
2090 if ((op == PLUS) && this.optimizeStringLiterals) {
2091 Expression expr1, expr2;
2092 expr1 = this.expressionStack[this.expressionPtr + 1];
2093 expr2 = this.expressionStack[this.expressionPtr];
2094 if (expr1 instanceof StringLiteral) {
2095 if (expr2 instanceof CharLiteral) { // string+char
2096 this.expressionStack[this.expressionPtr] =
2097 ((StringLiteral) expr1).extendWith((CharLiteral) expr2);
2098 } else if (expr2 instanceof StringLiteral) { //string+string
2099 this.expressionStack[this.expressionPtr] =
2100 ((StringLiteral) expr1).extendWith((StringLiteral) expr2);
2101 } else {
2102 this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
2103 }
2104 } else {
2105 this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
2106 }
2107 } else {
2108 this.expressionStack[this.expressionPtr] =
2109 new BinaryExpression(
2110 this.expressionStack[this.expressionPtr + 1],
2111 this.expressionStack[this.expressionPtr],
2112 op);
2113 }
2114 }
2115 }
2116 */
2117 Expression expr1 = this.expressionStack[this.expressionPtr + 1];
2118 Expression expr2 = this.expressionStack[this.expressionPtr];
2119 // Note: we do not attempt to promote BinaryExpression-s to
2120 // IndexedBinaryExpression-s here since expr1 always holds a name
2121 switch(op) {
2122 case OR_OR :
2123 this.expressionStack[this.expressionPtr] =
2124 new OR_OR_Expression(
2125 expr1,
2126 expr2,
2127 op);
2128 break;
2129 case AND_AND :
2130 this.expressionStack[this.expressionPtr] =
2131 new AND_AND_Expression(
2132 expr1,
2133 expr2,
2134 op);
2135 break;
2136 case PLUS :
2137 // look for "string1" + "string2"
2138 if (this.optimizeStringLiterals) {
2139 if (expr1 instanceof StringLiteral
2140 && ((expr1.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0) {
2141 if (expr2 instanceof CharLiteral) { // string+char
2142 this.expressionStack[this.expressionPtr] =
2143 ((StringLiteral) expr1).extendWith((CharLiteral) expr2);
2144 } else if (expr2 instanceof StringLiteral) { //string+string
2145 this.expressionStack[this.expressionPtr] =
2146 ((StringLiteral) expr1).extendWith((StringLiteral) expr2);
2147 } else {
2148 this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
2149 }
2150 } else {
2151 this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
2152 }
2153 } else if (expr1 instanceof StringLiteral) {
2154 if (expr2 instanceof StringLiteral
2155 && ((expr1.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0) {
2156 // string + string
2157 this.expressionStack[this.expressionPtr] =
2158 ((StringLiteral) expr1).extendsWith((StringLiteral) expr2);
2159 } else {
2160 this.expressionStack[this.expressionPtr] =
2161 new BinaryExpression(
2162 expr1,
2163 expr2,
2164 op);
2165 }
2166 } else {
2167 this.expressionStack[this.expressionPtr] =
2168 new BinaryExpression(
2169 expr1,
2170 expr2,
2171 op);
2172 }
2173 break;
2174 case LESS :
2175 case MULTIPLY :
2176 this.intPtr--; // star end position or starting position of angle bracket
2177 this.expressionStack[this.expressionPtr] =
2178 new BinaryExpression(
2179 expr1,
2180 expr2,
2181 op);
2182 break;
2183 default :
2184 this.expressionStack[this.expressionPtr] =
2185 new BinaryExpression(
2186 expr1,
2187 expr2,
2188 op);
2189 }
2190 }
consumeBlock()2191 protected void consumeBlock() {
2192 // Block ::= OpenBlock '{' BlockStatementsopt '}'
2193 // LambdaBody ::= NestedType NestedMethod '{' BlockStatementsopt '}'
2194 // simpler action for empty blocks
2195
2196 int statementsLength = this.astLengthStack[this.astLengthPtr--];
2197 Block block;
2198 if (statementsLength == 0) { // empty block
2199 block = new Block(0);
2200 block.sourceStart = this.intStack[this.intPtr--];
2201 block.sourceEnd = this.endStatementPosition;
2202 // check whether this block at least contains some comment in it
2203 if (!containsComment(block.sourceStart, block.sourceEnd)) {
2204 block.bits |= ASTNode.UndocumentedEmptyBlock;
2205 }
2206 this.realBlockPtr--; // still need to pop the block variable counter
2207 } else {
2208 block = new Block(this.realBlockStack[this.realBlockPtr--]);
2209 this.astPtr -= statementsLength;
2210 System.arraycopy(
2211 this.astStack,
2212 this.astPtr + 1,
2213 block.statements = new Statement[statementsLength],
2214 0,
2215 statementsLength);
2216 block.sourceStart = this.intStack[this.intPtr--];
2217 block.sourceEnd = this.endStatementPosition;
2218 }
2219 pushOnAstStack(block);
2220 }
consumeBlockStatement()2221 protected void consumeBlockStatement() {
2222 // for assist parsers.
2223 }
consumeBlockStatements()2224 protected void consumeBlockStatements() {
2225 // BlockStatements ::= BlockStatements BlockStatement
2226 concatNodeLists();
2227 }
consumeCaseLabel()2228 protected void consumeCaseLabel() {
2229 // // SwitchLabel ::= 'case' ConstantExpression ':'
2230 // this.expressionLengthPtr--;
2231 // Expression expression = this.expressionStack[this.expressionPtr--];
2232 // CaseStatement caseStatement = new CaseStatement(expression, expression.sourceEnd, this.intStack[this.intPtr--]);
2233 // // Look for $fall-through$ tag in leading comment for case statement
2234 // if (hasLeadingTagComment(FALL_THROUGH_TAG, caseStatement.sourceStart)) {
2235 // caseStatement.bits |= ASTNode.DocumentedFallthrough;
2236 // }
2237 // pushOnAstStack(caseStatement);
2238 Expression[] constantExpressions = null;
2239 int length = 0;
2240 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
2241 this.expressionPtr -= length;
2242 System.arraycopy(
2243 this.expressionStack,
2244 this.expressionPtr + 1,
2245 constantExpressions = new Expression[length],
2246 0,
2247 length);
2248 } else {
2249 // TODO : ERROR
2250 }
2251 CaseStatement caseStatement = new CaseStatement(constantExpressions[0], constantExpressions[length - 1].sourceEnd, this.intStack[this.intPtr--]);
2252 if (constantExpressions.length > 1) {
2253 if (!this.parsingJava14Plus) {
2254 problemReporter().multiConstantCaseLabelsNotSupported(caseStatement);
2255 }
2256 }
2257 caseStatement.constantExpressions = constantExpressions;
2258 // Look for $fall-through$ tag in leading comment for case statement
2259 if (hasLeadingTagComment(FALL_THROUGH_TAG, caseStatement.sourceStart)) {
2260 caseStatement.bits |= ASTNode.DocumentedFallthrough;
2261 }
2262
2263 pushOnAstStack(caseStatement);
2264 }
consumeCastExpressionLL1()2265 protected void consumeCastExpressionLL1() {
2266 //CastExpression ::= '(' Name ')' InsideCastExpressionLL1 UnaryExpressionNotPlusMinus
2267
2268
2269 //optimize push/pop
2270
2271 Expression cast;
2272 Expression exp;
2273 this.expressionPtr--;
2274 this.expressionStack[this.expressionPtr] =
2275 cast = new CastExpression(
2276 exp=this.expressionStack[this.expressionPtr+1] ,
2277 (TypeReference) this.expressionStack[this.expressionPtr]);
2278 this.expressionLengthPtr -- ;
2279 updateSourcePosition(cast);
2280 cast.sourceEnd=exp.sourceEnd;
2281 }
createIntersectionCastTypeReference(TypeReference[] typeReferences)2282 public IntersectionCastTypeReference createIntersectionCastTypeReference(TypeReference[] typeReferences) {
2283 if (this.options.sourceLevel < ClassFileConstants.JDK1_8) {
2284 problemReporter().intersectionCastNotBelow18(typeReferences);
2285 }
2286 return new IntersectionCastTypeReference(typeReferences);
2287 }
consumeCastExpressionLL1WithBounds()2288 protected void consumeCastExpressionLL1WithBounds() {
2289 //CastExpression ::= '(' Name AdditionalBoundsList ')' UnaryExpressionNotPlusMinus
2290 Expression cast;
2291 Expression exp;
2292 int length;
2293 exp = this.expressionStack[this.expressionPtr--];
2294 this.expressionLengthPtr --;
2295 TypeReference[] bounds = new TypeReference[length = this.expressionLengthStack[this.expressionLengthPtr]];
2296 System.arraycopy(this.expressionStack, this.expressionPtr -= (length - 1), bounds, 0, length);
2297 this.expressionStack[this.expressionPtr] =
2298 cast = new CastExpression(
2299 exp,
2300 createIntersectionCastTypeReference(bounds));
2301 this.expressionLengthStack[this.expressionLengthPtr] = 1;
2302 updateSourcePosition(cast);
2303 cast.sourceEnd=exp.sourceEnd;
2304 }
consumeCastExpressionWithGenericsArray()2305 protected void consumeCastExpressionWithGenericsArray() {
2306 // CastExpression ::= PushLPAREN Name TypeArguments Dimsopt AdditionalBoundsListOpt PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
2307
2308 TypeReference[] bounds = null;
2309 int additionalBoundsLength = this.genericsLengthStack[this.genericsLengthPtr--];
2310 if (additionalBoundsLength > 0) {
2311 bounds = new TypeReference[additionalBoundsLength + 1];
2312 this.genericsPtr -= additionalBoundsLength;
2313 System.arraycopy(this.genericsStack, this.genericsPtr + 1, bounds, 1, additionalBoundsLength);
2314 }
2315 Expression exp;
2316 Expression cast;
2317 TypeReference castType;
2318 int end = this.intStack[this.intPtr--];
2319
2320 int dim = this.intStack[this.intPtr--];
2321 pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
2322 if (additionalBoundsLength > 0) {
2323 bounds[0] = getTypeReference(dim);
2324 castType = createIntersectionCastTypeReference(bounds);
2325 } else {
2326 castType = getTypeReference(dim);
2327 }
2328 this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType);
2329 this.intPtr--; // pop position of '<'
2330 castType.sourceEnd = end - 1;
2331 castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
2332 cast.sourceEnd = exp.sourceEnd;
2333 }
consumeCastExpressionWithNameArray()2334 protected void consumeCastExpressionWithNameArray() {
2335 // CastExpression ::= PushLPAREN Name Dims AdditionalBoundsListOpt PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
2336
2337 Expression exp;
2338 Expression cast;
2339 TypeReference castType;
2340 int end = this.intStack[this.intPtr--];
2341
2342 TypeReference[] bounds = null;
2343 int additionalBoundsLength = this.genericsLengthStack[this.genericsLengthPtr--];
2344 if (additionalBoundsLength > 0) {
2345 bounds = new TypeReference[additionalBoundsLength + 1];
2346 this.genericsPtr -= additionalBoundsLength;
2347 System.arraycopy(this.genericsStack, this.genericsPtr + 1, bounds, 1, additionalBoundsLength);
2348 }
2349 // handle type arguments
2350 pushOnGenericsLengthStack(0);
2351 pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
2352
2353 if (additionalBoundsLength > 0) {
2354 bounds[0] = getTypeReference(this.intStack[this.intPtr--]);
2355 castType = createIntersectionCastTypeReference(bounds);
2356 } else {
2357 castType = getTypeReference(this.intStack[this.intPtr--]);
2358 }
2359 this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType);
2360 castType.sourceEnd = end - 1;
2361 castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
2362 cast.sourceEnd = exp.sourceEnd;
2363 }
consumeCastExpressionWithPrimitiveType()2364 protected void consumeCastExpressionWithPrimitiveType() {
2365 // CastExpression ::= PushLPAREN PrimitiveType Dimsopt AdditionalBoundsListOpt PushRPAREN InsideCastExpression UnaryExpression
2366
2367 //this.intStack : posOfLeftParen dim posOfRightParen
2368
2369 TypeReference[] bounds = null;
2370 int additionalBoundsLength = this.genericsLengthStack[this.genericsLengthPtr--];
2371 if (additionalBoundsLength > 0) {
2372 bounds = new TypeReference[additionalBoundsLength + 1];
2373 this.genericsPtr -= additionalBoundsLength;
2374 System.arraycopy(this.genericsStack, this.genericsPtr + 1, bounds, 1, additionalBoundsLength);
2375 }
2376
2377 //optimize the push/pop
2378 Expression exp;
2379 Expression cast;
2380 TypeReference castType;
2381 int end = this.intStack[this.intPtr--];
2382 if (additionalBoundsLength > 0) {
2383 bounds[0] = getTypeReference(this.intStack[this.intPtr--]);
2384 castType = createIntersectionCastTypeReference(bounds);
2385 } else {
2386 castType = getTypeReference(this.intStack[this.intPtr--]);
2387 }
2388 this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType);
2389 castType.sourceEnd = end - 1;
2390 castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
2391 cast.sourceEnd = exp.sourceEnd;
2392 }
consumeCastExpressionWithQualifiedGenericsArray()2393 protected void consumeCastExpressionWithQualifiedGenericsArray() {
2394 // CastExpression ::= PushLPAREN Name OnlyTypeArguments '.' ClassOrInterfaceType Dimsopt AdditionalBoundsOpt PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
2395
2396 TypeReference[] bounds = null;
2397 int additionalBoundsLength = this.genericsLengthStack[this.genericsLengthPtr--];
2398 if (additionalBoundsLength > 0) {
2399 bounds = new TypeReference[additionalBoundsLength + 1];
2400 this.genericsPtr -= additionalBoundsLength;
2401 System.arraycopy(this.genericsStack, this.genericsPtr + 1, bounds, 1, additionalBoundsLength);
2402 }
2403
2404 Expression exp;
2405 Expression cast;
2406 TypeReference castType;
2407 int end = this.intStack[this.intPtr--];
2408 int dim = this.intStack[this.intPtr--];
2409 Annotation [][] annotationsOnDimensions = dim == 0 ? null : getAnnotationsOnDimensions(dim);
2410 TypeReference rightSide = getTypeReference(0);
2411 castType = computeQualifiedGenericsFromRightSide(rightSide, dim, annotationsOnDimensions);
2412
2413 if (additionalBoundsLength > 0) {
2414 bounds[0] = castType;
2415 castType = createIntersectionCastTypeReference(bounds);
2416 }
2417
2418 this.intPtr--;
2419 this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType);
2420 castType.sourceEnd = end - 1;
2421 castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
2422 cast.sourceEnd = exp.sourceEnd;
2423 }
consumeCatches()2424 protected void consumeCatches() {
2425 // Catches ::= Catches CatchClause
2426 optimizedConcatNodeLists();
2427 }
consumeCatchFormalParameter()2428 protected void consumeCatchFormalParameter() {
2429 // CatchFormalParameter ::= Modifiersopt CatchType VariableDeclaratorId
2430 this.identifierLengthPtr--;
2431 char[] identifierName = this.identifierStack[this.identifierPtr];
2432 long namePositions = this.identifierPositionStack[this.identifierPtr--];
2433 int extendedDimensions = this.intStack[this.intPtr--]; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=348369
2434 TypeReference type = (TypeReference) this.astStack[this.astPtr--];
2435 if (extendedDimensions > 0) {
2436 type = augmentTypeWithAdditionalDimensions(type, extendedDimensions, null, false);
2437 type.sourceEnd = this.endPosition;
2438 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391092
2439 if (type instanceof UnionTypeReference) {
2440 this.problemReporter().illegalArrayOfUnionType(identifierName, type);
2441 }
2442 }
2443 this.astLengthPtr--;
2444 int modifierPositions = this.intStack[this.intPtr--];
2445 this.intPtr--;
2446 Argument arg =
2447 new Argument(
2448 identifierName,
2449 namePositions,
2450 type,
2451 this.intStack[this.intPtr + 1] & ~ClassFileConstants.AccDeprecated); // modifiers
2452 arg.bits &= ~ASTNode.IsArgument;
2453 arg.declarationSourceStart = modifierPositions;
2454 // consume annotations
2455 int length;
2456 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
2457 System.arraycopy(
2458 this.expressionStack,
2459 (this.expressionPtr -= length) + 1,
2460 arg.annotations = new Annotation[length],
2461 0,
2462 length);
2463 }
2464 pushOnAstStack(arg);
2465 /* if incomplete method header, this.listLength counter will not have been reset,
2466 indicating that some arguments are available on the stack */
2467 this.listLength++;
2468 }
consumeCatchHeader()2469 protected void consumeCatchHeader() {
2470 // CatchDeclaration ::= 'catch' '(' FormalParameter ')' '{'
2471
2472 if (this.currentElement == null){
2473 return; // should never occur, this consumeRule is only used in recovery mode
2474 }
2475 // current element should be a block due to the presence of the opening brace
2476 if (!(this.currentElement instanceof RecoveredBlock)){
2477 if(!(this.currentElement instanceof RecoveredMethod)) {
2478 return;
2479 }
2480 RecoveredMethod rMethod = (RecoveredMethod) this.currentElement;
2481 if(!(rMethod.methodBody == null && rMethod.bracketBalance > 0)) {
2482 return;
2483 }
2484 }
2485
2486 Argument arg = (Argument)this.astStack[this.astPtr--];
2487 // convert argument to local variable
2488 LocalDeclaration localDeclaration = new LocalDeclaration(arg.name, arg.sourceStart, arg.sourceEnd);
2489 localDeclaration.type = arg.type;
2490 localDeclaration.declarationSourceStart = arg.declarationSourceStart;
2491 localDeclaration.declarationSourceEnd = arg.declarationSourceEnd;
2492
2493 this.currentElement = this.currentElement.add(localDeclaration, 0);
2494 this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
2495 this.restartRecovery = true; // request to restart from here on
2496 this.lastIgnoredToken = -1;
2497 }
consumeCatchType()2498 protected void consumeCatchType() {
2499 // CatchType ::= UnionType
2500 int length = this.astLengthStack[this.astLengthPtr--];
2501 if (length != 1) {
2502 TypeReference[] typeReferences;
2503 System.arraycopy(
2504 this.astStack,
2505 (this.astPtr -= length) + 1,
2506 (typeReferences = new TypeReference[length]),
2507 0,
2508 length);
2509 UnionTypeReference typeReference = new UnionTypeReference(typeReferences);
2510 pushOnAstStack(typeReference);
2511 if (this.options.sourceLevel < ClassFileConstants.JDK1_7) {
2512 problemReporter().multiCatchNotBelow17(typeReference);
2513 }
2514 } else {
2515 // push back the type reference
2516 pushOnAstLengthStack(1);
2517 }
2518 }
consumeClassBodyDeclaration()2519 protected void consumeClassBodyDeclaration() {
2520 // ClassBodyDeclaration ::= Diet NestedMethod CreateInitializer Block
2521 //push an Initializer
2522 //optimize the push/pop
2523 this.nestedMethod[this.nestedType]--;
2524 Block block = (Block) this.astStack[this.astPtr--];
2525 this.astLengthPtr--;
2526 if (this.diet) block.bits &= ~ASTNode.UndocumentedEmptyBlock; // clear bit since was diet
2527 Initializer initializer = (Initializer) this.astStack[this.astPtr];
2528 initializer.declarationSourceStart = initializer.sourceStart = block.sourceStart;
2529 initializer.block = block;
2530 this.intPtr--; // pop sourcestart left on the stack by consumeNestedMethod.
2531 initializer.bodyStart = this.intStack[this.intPtr--];
2532 this.realBlockPtr--; // pop the block variable counter left on the stack by consumeNestedMethod
2533 int javadocCommentStart = this.intStack[this.intPtr--];
2534 if (javadocCommentStart != -1) {
2535 initializer.declarationSourceStart = javadocCommentStart;
2536 initializer.javadoc = this.javadoc;
2537 this.javadoc = null;
2538 }
2539 initializer.bodyEnd = this.endPosition;
2540 initializer.sourceEnd = this.endStatementPosition;
2541 initializer.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
2542 }
consumeClassBodyDeclarations()2543 protected void consumeClassBodyDeclarations() {
2544 // ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration
2545 concatNodeLists();
2546 }
consumeClassBodyDeclarationsopt()2547 protected void consumeClassBodyDeclarationsopt() {
2548 // ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations
2549 this.nestedType-- ;
2550 }
consumeClassBodyopt()2551 protected void consumeClassBodyopt() {
2552 // ClassBodyopt ::= $empty
2553 pushOnAstStack(null);
2554 this.endPosition = this.rParenPos;
2555 }
consumeClassDeclaration()2556 protected void consumeClassDeclaration() {
2557 // ClassDeclaration ::= ClassHeader ClassBody
2558
2559 int length;
2560 if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
2561 //there are length declarations
2562 //dispatch according to the type of the declarations
2563 dispatchDeclarationInto(length);
2564 }
2565
2566 TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
2567
2568 //convert constructor that do not have the type's name into methods
2569 boolean hasConstructor = typeDecl.checkConstructors(this);
2570
2571 //add the default constructor when needed (interface don't have it)
2572 if (!hasConstructor) {
2573 switch(TypeDeclaration.kind(typeDecl.modifiers)) {
2574 case TypeDeclaration.CLASS_DECL :
2575 case TypeDeclaration.ENUM_DECL :
2576 boolean insideFieldInitializer = false;
2577 if (this.diet) {
2578 for (int i = this.nestedType; i > 0; i--){
2579 if (this.variablesCounter[i] > 0) {
2580 insideFieldInitializer = true;
2581 break;
2582 }
2583 }
2584 }
2585 typeDecl.createDefaultConstructor(!(this.diet && this.dietInt == 0) || insideFieldInitializer, true);
2586 }
2587 }
2588 //always add <clinit> (will be remove at code gen time if empty)
2589 if (this.scanner.containsAssertKeyword) {
2590 typeDecl.bits |= ASTNode.ContainsAssertion;
2591 }
2592 typeDecl.addClinit();
2593 typeDecl.bodyEnd = this.endStatementPosition;
2594 if (length == 0 && !containsComment(typeDecl.bodyStart, typeDecl.bodyEnd)) {
2595 typeDecl.bits |= ASTNode.UndocumentedEmptyBlock;
2596 }
2597
2598 typeDecl.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
2599 }
consumeClassHeader()2600 protected void consumeClassHeader() {
2601 // ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt
2602
2603 TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
2604 if (this.currentToken == TokenNameLBRACE) {
2605 typeDecl.bodyStart = this.scanner.currentPosition;
2606 }
2607 if (this.currentElement != null) {
2608 this.restartRecovery = true; // used to avoid branching back into the regular automaton
2609 }
2610 // flush the comments related to the class header
2611 this.scanner.commentPtr = -1;
2612 }
consumeClassHeaderExtends()2613 protected void consumeClassHeaderExtends() {
2614 // ClassHeaderExtends ::= 'extends' ClassType
2615 //superclass
2616 TypeReference superClass = getTypeReference(0);
2617 // There is a class declaration on the top of stack
2618 TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
2619 typeDecl.bits |= (superClass.bits & ASTNode.HasTypeAnnotations);
2620 typeDecl.superclass = superClass;
2621 superClass.bits |= ASTNode.IsSuperType;
2622 typeDecl.bodyStart = typeDecl.superclass.sourceEnd + 1;
2623 // recovery
2624 if (this.currentElement != null){
2625 this.lastCheckPoint = typeDecl.bodyStart;
2626 }
2627 }
consumeClassHeaderImplements()2628 protected void consumeClassHeaderImplements() {
2629 // ClassHeaderImplements ::= 'implements' InterfaceTypeList
2630 int length = this.astLengthStack[this.astLengthPtr--];
2631 //super interfaces
2632 this.astPtr -= length;
2633 // There is a class declaration on the top of stack
2634 TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
2635 System.arraycopy(
2636 this.astStack,
2637 this.astPtr + 1,
2638 typeDecl.superInterfaces = new TypeReference[length],
2639 0,
2640 length);
2641 TypeReference[] superinterfaces = typeDecl.superInterfaces;
2642 for (int i = 0, max = superinterfaces.length; i < max; i++) {
2643 TypeReference typeReference = superinterfaces[i];
2644 typeDecl.bits |= (typeReference.bits & ASTNode.HasTypeAnnotations);
2645 typeReference.bits |= ASTNode.IsSuperType;
2646 }
2647 typeDecl.bodyStart = typeDecl.superInterfaces[length-1].sourceEnd + 1;
2648 this.listLength = 0; // reset after having read super-interfaces
2649 // recovery
2650 if (this.currentElement != null) { // is recovering
2651 this.lastCheckPoint = typeDecl.bodyStart;
2652 }
2653 }
consumeClassOrRecordHeaderName1(boolean isRecord)2654 private void consumeClassOrRecordHeaderName1(boolean isRecord) {
2655 TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
2656 if (this.nestedMethod[this.nestedType] == 0) {
2657 if (this.nestedType != 0) {
2658 typeDecl.bits |= ASTNode.IsMemberType;
2659 }
2660 } else {
2661 // Record that the block has a declaration for local types
2662 typeDecl.bits |= ASTNode.IsLocalType;
2663 markEnclosingMemberWithLocalType();
2664 blockReal();
2665 }
2666
2667 //highlight the name of the type
2668 long pos = this.identifierPositionStack[this.identifierPtr];
2669 typeDecl.sourceEnd = (int) pos;
2670 typeDecl.sourceStart = (int) (pos >>> 32);
2671 typeDecl.name = this.identifierStack[this.identifierPtr--];
2672 this.identifierLengthPtr--;
2673
2674 //compute the declaration source too
2675 // 'class' and 'interface' push two int positions: the beginning of the class token and its end.
2676 // we want to keep the beginning position but get rid of the end position
2677 // it is only used for the ClassLiteralAccess positions.
2678 typeDecl.declarationSourceStart = this.intStack[this.intPtr--];
2679 typeDecl.restrictedIdentifierStart = typeDecl.declarationSourceStart;
2680 this.intPtr--; // remove the end position of the class token
2681
2682 typeDecl.modifiersSourceStart = this.intStack[this.intPtr--];
2683 typeDecl.modifiers = this.intStack[this.intPtr--];
2684 if (typeDecl.modifiersSourceStart >= 0) {
2685 typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
2686 }
2687
2688 // Store secondary info
2689 if ((typeDecl.bits & ASTNode.IsMemberType) == 0 && (typeDecl.bits & ASTNode.IsLocalType) == 0) {
2690 if (this.compilationUnit != null && !CharOperation.equals(typeDecl.name, this.compilationUnit.getMainTypeName())) {
2691 typeDecl.bits |= ASTNode.IsSecondaryType;
2692 }
2693 }
2694
2695 // consume annotations
2696 int length;
2697 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
2698 System.arraycopy(
2699 this.expressionStack,
2700 (this.expressionPtr -= length) + 1,
2701 typeDecl.annotations = new Annotation[length],
2702 0,
2703 length);
2704 }
2705 typeDecl.bodyStart = typeDecl.sourceEnd + 1;
2706 if (isRecord) {
2707 typeDecl.modifiers |= ExtraCompilerModifiers.AccRecord;
2708 }
2709 pushOnAstStack(typeDecl);
2710
2711 this.listLength = 0; // will be updated when reading super-interfaces
2712 // recovery
2713 if (this.currentElement != null){
2714 this.lastCheckPoint = typeDecl.bodyStart;
2715 this.currentElement = this.currentElement.add(typeDecl, 0);
2716 this.lastIgnoredToken = -1;
2717 }
2718 // javadoc
2719 typeDecl.javadoc = this.javadoc;
2720 this.javadoc = null;
2721 }
consumeClassHeaderName1()2722 protected void consumeClassHeaderName1() {
2723 // ClassHeaderName1 ::= Modifiersopt 'class' 'Identifier'
2724 consumeClassOrRecordHeaderName1(false);
2725 }
consumeClassInstanceCreationExpression()2726 protected void consumeClassInstanceCreationExpression() {
2727 // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
2728 classInstanceCreation(false);
2729 consumeInvocationExpression();
2730 }
consumeClassInstanceCreationExpressionName()2731 protected void consumeClassInstanceCreationExpressionName() {
2732 // ClassInstanceCreationExpressionName ::= Name '.'
2733 pushOnExpressionStack(getUnspecifiedReferenceOptimized());
2734 }
consumeClassInstanceCreationExpressionQualified()2735 protected void consumeClassInstanceCreationExpressionQualified() {
2736 // ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
2737 // ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
2738 classInstanceCreation(true);
2739
2740 QualifiedAllocationExpression qae =
2741 (QualifiedAllocationExpression) this.expressionStack[this.expressionPtr];
2742
2743 if (qae.anonymousType == null) {
2744 this.expressionLengthPtr--;
2745 this.expressionPtr--;
2746 qae.enclosingInstance = this.expressionStack[this.expressionPtr];
2747 this.expressionStack[this.expressionPtr] = qae;
2748 }
2749 qae.sourceStart = qae.enclosingInstance.sourceStart;
2750 consumeInvocationExpression();
2751 }
consumeClassInstanceCreationExpressionQualifiedWithTypeArguments()2752 protected void consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() {
2753 // ClassInstanceCreationExpression ::= Primary '.' 'new' TypeArguments SimpleName '(' ArgumentListopt ')' ClassBodyopt
2754 // ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' TypeArguments SimpleName '(' ArgumentListopt ')' ClassBodyopt
2755
2756 QualifiedAllocationExpression alloc;
2757 int length;
2758 if (((length = this.astLengthStack[this.astLengthPtr--]) == 1) && (this.astStack[this.astPtr] == null)) {
2759 //NO ClassBody
2760 this.astPtr--;
2761 alloc = new QualifiedAllocationExpression();
2762 alloc.sourceEnd = this.endPosition; //the position has been stored explicitly
2763
2764 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
2765 this.expressionPtr -= length;
2766 System.arraycopy(
2767 this.expressionStack,
2768 this.expressionPtr + 1,
2769 alloc.arguments = new Expression[length],
2770 0,
2771 length);
2772 }
2773 alloc.type = getTypeReference(0);
2774 checkForDiamond(alloc.type);
2775 length = this.genericsLengthStack[this.genericsLengthPtr--];
2776 this.genericsPtr -= length;
2777 System.arraycopy(this.genericsStack, this.genericsPtr + 1, alloc.typeArguments = new TypeReference[length], 0, length);
2778 this.intPtr--;
2779
2780 //the default constructor with the correct number of argument
2781 //will be created and added by the TC (see createsInternalConstructorWithBinding)
2782 alloc.sourceStart = this.intStack[this.intPtr--];
2783 pushOnExpressionStack(alloc);
2784 } else {
2785 dispatchDeclarationInto(length);
2786 TypeDeclaration anonymousTypeDeclaration = (TypeDeclaration)this.astStack[this.astPtr];
2787 anonymousTypeDeclaration.declarationSourceEnd = this.endStatementPosition;
2788 anonymousTypeDeclaration.bodyEnd = this.endStatementPosition;
2789 if (length == 0 && !containsComment(anonymousTypeDeclaration.bodyStart, anonymousTypeDeclaration.bodyEnd)) {
2790 anonymousTypeDeclaration.bits |= ASTNode.UndocumentedEmptyBlock;
2791 }
2792 this.astPtr--;
2793 this.astLengthPtr--;
2794
2795 QualifiedAllocationExpression allocationExpression = anonymousTypeDeclaration.allocation;
2796 if (allocationExpression != null) {
2797 allocationExpression.sourceEnd = this.endStatementPosition;
2798 // handle type arguments
2799 length = this.genericsLengthStack[this.genericsLengthPtr--];
2800 this.genericsPtr -= length;
2801 System.arraycopy(this.genericsStack, this.genericsPtr + 1, allocationExpression.typeArguments = new TypeReference[length], 0, length);
2802 allocationExpression.sourceStart = this.intStack[this.intPtr--];
2803 checkForDiamond(allocationExpression.type);
2804 }
2805 }
2806
2807 QualifiedAllocationExpression qae =
2808 (QualifiedAllocationExpression) this.expressionStack[this.expressionPtr];
2809
2810 if (qae.anonymousType == null) {
2811 this.expressionLengthPtr--;
2812 this.expressionPtr--;
2813 qae.enclosingInstance = this.expressionStack[this.expressionPtr];
2814 this.expressionStack[this.expressionPtr] = qae;
2815 }
2816 qae.sourceStart = qae.enclosingInstance.sourceStart;
2817 consumeInvocationExpression();
2818 }
consumeClassInstanceCreationExpressionWithTypeArguments()2819 protected void consumeClassInstanceCreationExpressionWithTypeArguments() {
2820 // ClassInstanceCreationExpression ::= 'new' TypeArguments ClassType '(' ArgumentListopt ')' ClassBodyopt
2821 AllocationExpression alloc;
2822 int length;
2823 if (((length = this.astLengthStack[this.astLengthPtr--]) == 1)
2824 && (this.astStack[this.astPtr] == null)) {
2825 //NO ClassBody
2826 this.astPtr--;
2827 alloc = new AllocationExpression();
2828 alloc.sourceEnd = this.endPosition; //the position has been stored explicitly
2829
2830 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
2831 this.expressionPtr -= length;
2832 System.arraycopy(
2833 this.expressionStack,
2834 this.expressionPtr + 1,
2835 alloc.arguments = new Expression[length],
2836 0,
2837 length);
2838 }
2839 alloc.type = getTypeReference(0);
2840 checkForDiamond(alloc.type);
2841
2842 length = this.genericsLengthStack[this.genericsLengthPtr--];
2843 this.genericsPtr -= length;
2844 System.arraycopy(this.genericsStack, this.genericsPtr + 1, alloc.typeArguments = new TypeReference[length], 0, length);
2845 this.intPtr--;
2846
2847 //the default constructor with the correct number of argument
2848 //will be created and added by the TC (see createsInternalConstructorWithBinding)
2849 alloc.sourceStart = this.intStack[this.intPtr--];
2850 pushOnExpressionStack(alloc);
2851 } else {
2852 dispatchDeclarationInto(length);
2853 TypeDeclaration anonymousTypeDeclaration = (TypeDeclaration)this.astStack[this.astPtr];
2854 anonymousTypeDeclaration.declarationSourceEnd = this.endStatementPosition;
2855 anonymousTypeDeclaration.bodyEnd = this.endStatementPosition;
2856 if (length == 0 && !containsComment(anonymousTypeDeclaration.bodyStart, anonymousTypeDeclaration.bodyEnd)) {
2857 anonymousTypeDeclaration.bits |= ASTNode.UndocumentedEmptyBlock;
2858 }
2859 this.astPtr--;
2860 this.astLengthPtr--;
2861
2862 QualifiedAllocationExpression allocationExpression = anonymousTypeDeclaration.allocation;
2863 if (allocationExpression != null) {
2864 allocationExpression.sourceEnd = this.endStatementPosition;
2865 // handle type arguments
2866 length = this.genericsLengthStack[this.genericsLengthPtr--];
2867 this.genericsPtr -= length;
2868 System.arraycopy(this.genericsStack, this.genericsPtr + 1, allocationExpression.typeArguments = new TypeReference[length], 0, length);
2869 allocationExpression.sourceStart = this.intStack[this.intPtr--];
2870 checkForDiamond(allocationExpression.type);
2871 }
2872 }
2873 consumeInvocationExpression();
2874 }
consumeClassOrInterface()2875 protected void consumeClassOrInterface() {
2876 this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr] += this.identifierLengthStack[this.identifierLengthPtr];
2877 pushOnGenericsLengthStack(0); // handle type arguments
2878 }
consumeClassOrInterfaceName()2879 protected void consumeClassOrInterfaceName() {
2880 pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
2881 pushOnGenericsLengthStack(0); // handle type arguments
2882 }
consumeClassTypeElt()2883 protected void consumeClassTypeElt() {
2884 // ClassTypeElt ::= ClassType
2885 pushOnAstStack(getTypeReference(0));
2886 /* if incomplete thrown exception list, this.listLength counter will not have been reset,
2887 indicating that some items are available on the stack */
2888 this.listLength++;
2889 }
consumeClassTypeList()2890 protected void consumeClassTypeList() {
2891 // ClassTypeList ::= ClassTypeList ',' ClassTypeElt
2892 optimizedConcatNodeLists();
2893 }
consumeCompilationUnit()2894 protected void consumeCompilationUnit() {
2895 // CompilationUnit ::= EnterCompilationUnit InternalCompilationUnit
2896 // do nothing by default
2897 }
consumeConditionalExpression(int op)2898 protected void consumeConditionalExpression(int op) {
2899 // ConditionalExpression ::= ConditionalOrExpression '?' Expression ':' ConditionalExpression
2900 //optimize the push/pop
2901 this.intPtr -= 2;//consume position of the question mark
2902 this.expressionPtr -= 2;
2903 this.expressionLengthPtr -= 2;
2904 this.expressionStack[this.expressionPtr] =
2905 new ConditionalExpression(
2906 this.expressionStack[this.expressionPtr],
2907 this.expressionStack[this.expressionPtr + 1],
2908 this.expressionStack[this.expressionPtr + 2]);
2909 }
2910 /**
2911 * @param op
2912 */
consumeConditionalExpressionWithName(int op)2913 protected void consumeConditionalExpressionWithName(int op) {
2914 // ConditionalExpression ::= Name '?' Expression ':' ConditionalExpression
2915 this.intPtr -= 2;//consume position of the question mark
2916 pushOnExpressionStack(getUnspecifiedReferenceOptimized());
2917 this.expressionPtr -= 2;
2918 this.expressionLengthPtr -= 2;
2919 this.expressionStack[this.expressionPtr] =
2920 new ConditionalExpression(
2921 this.expressionStack[this.expressionPtr + 2],
2922 this.expressionStack[this.expressionPtr],
2923 this.expressionStack[this.expressionPtr + 1]);
2924 }
consumeConstructorBlockStatements()2925 protected void consumeConstructorBlockStatements() {
2926 // ConstructorBody ::= NestedMethod '{' ExplicitConstructorInvocation BlockStatements '}'
2927 concatNodeLists(); // explictly add the first statement into the list of statements
2928 }
consumeConstructorBody()2929 protected void consumeConstructorBody() {
2930 // ConstructorBody ::= NestedMethod '{' BlockStatementsopt '}'
2931 // ConstructorBody ::= NestedMethod '{' ExplicitConstructorInvocation '}'
2932 this.nestedMethod[this.nestedType] --;
2933 }
consumeConstructorDeclaration()2934 protected void consumeConstructorDeclaration() {
2935 // ConstructorDeclaration ::= ConstructorHeader ConstructorBody
2936
2937 /*
2938 this.astStack : MethodDeclaration statements
2939 this.identifierStack : name
2940 ==>
2941 this.astStack : MethodDeclaration
2942 this.identifierStack :
2943 */
2944
2945 //must provide a default constructor call when needed
2946
2947 int length;
2948
2949 // pop the position of the { (body of the method) pushed in block decl
2950 this.intPtr--;
2951 this.intPtr--;
2952
2953 //statements
2954 this.realBlockPtr--;
2955 ExplicitConstructorCall constructorCall = null;
2956 Statement[] statements = null;
2957 if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
2958 this.astPtr -= length;
2959 if (!this.options.ignoreMethodBodies) {
2960 if (this.astStack[this.astPtr + 1] instanceof ExplicitConstructorCall) {
2961 //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
2962 System.arraycopy(
2963 this.astStack,
2964 this.astPtr + 2,
2965 statements = new Statement[length - 1],
2966 0,
2967 length - 1);
2968 constructorCall = (ExplicitConstructorCall) this.astStack[this.astPtr + 1];
2969 } else { //need to add explicitly the super();
2970 System.arraycopy(
2971 this.astStack,
2972 this.astPtr + 1,
2973 statements = new Statement[length],
2974 0,
2975 length);
2976 constructorCall = SuperReference.implicitSuperConstructorCall();
2977 }
2978 }
2979 } else {
2980 boolean insideFieldInitializer = false;
2981 if (this.diet) {
2982 for (int i = this.nestedType; i > 0; i--){
2983 if (this.variablesCounter[i] > 0) {
2984 insideFieldInitializer = true;
2985 break;
2986 }
2987 }
2988 }
2989
2990 if (!this.options.ignoreMethodBodies) {
2991 if (!this.diet || insideFieldInitializer){
2992 // add it only in non-diet mode, if diet_bodies, then constructor call will be added elsewhere.
2993 constructorCall = SuperReference.implicitSuperConstructorCall();
2994 }
2995 }
2996 }
2997
2998 // now we know that the top of stack is a constructorDeclaration
2999 ConstructorDeclaration cd = (ConstructorDeclaration) this.astStack[this.astPtr];
3000 cd.constructorCall = constructorCall;
3001 cd.statements = statements;
3002
3003 //highlight of the implicit call on the method name
3004 if (constructorCall != null && cd.constructorCall.sourceEnd == 0) {
3005 cd.constructorCall.sourceEnd = cd.sourceEnd;
3006 cd.constructorCall.sourceStart = cd.sourceStart;
3007 }
3008
3009 if (!(this.diet && this.dietInt == 0)
3010 && statements == null
3011 && (constructorCall == null || constructorCall.isImplicitSuper())
3012 && !containsComment(cd.bodyStart, this.endPosition)) {
3013 cd.bits |= ASTNode.UndocumentedEmptyBlock;
3014 }
3015
3016 //watch for } that could be given as a unicode ! ( u007D is '}' )
3017 // store the this.endPosition (position just before the '}') in case there is
3018 // a trailing comment behind the end of the method
3019 cd.bodyEnd = this.endPosition;
3020 cd.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
3021 }
consumeConstructorHeader()3022 protected void consumeConstructorHeader() {
3023 // ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
3024
3025 AbstractMethodDeclaration method = (AbstractMethodDeclaration)this.astStack[this.astPtr];
3026
3027 if (this.currentToken == TokenNameLBRACE){
3028 method.bodyStart = this.scanner.currentPosition;
3029 }
3030 // recovery
3031 if (this.currentElement != null){
3032 if (this.currentToken == TokenNameSEMICOLON){ // for invalid constructors
3033 method.modifiers |= ExtraCompilerModifiers.AccSemicolonBody;
3034 method.declarationSourceEnd = this.scanner.currentPosition-1;
3035 method.bodyEnd = this.scanner.currentPosition-1;
3036 if (this.currentElement.parseTree() == method && this.currentElement.parent != null) {
3037 this.currentElement = this.currentElement.parent;
3038 }
3039 }
3040 this.restartRecovery = true; // used to avoid branching back into the regular automaton
3041 }
3042 }
consumeConstructorHeaderName()3043 protected void consumeConstructorHeaderName() {
3044
3045 /* recovering - might be an empty message send */
3046 if (this.currentElement != null){
3047 if (this.lastIgnoredToken == TokenNamenew){ // was an allocation expression
3048 this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
3049 this.restartRecovery = true;
3050 return;
3051 }
3052 }
3053
3054 // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
3055 ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationUnit.compilationResult);
3056
3057 //name -- this is not really revelant but we do .....
3058 cd.selector = this.identifierStack[this.identifierPtr];
3059 long selectorSource = this.identifierPositionStack[this.identifierPtr--];
3060 this.identifierLengthPtr--;
3061
3062 //modifiers
3063 cd.declarationSourceStart = this.intStack[this.intPtr--];
3064 cd.modifiers = this.intStack[this.intPtr--];
3065 // consume annotations
3066 int length;
3067 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
3068 System.arraycopy(
3069 this.expressionStack,
3070 (this.expressionPtr -= length) + 1,
3071 cd.annotations = new Annotation[length],
3072 0,
3073 length);
3074 }
3075 // javadoc
3076 cd.javadoc = this.javadoc;
3077 this.javadoc = null;
3078
3079 //highlight starts at the selector starts
3080 cd.sourceStart = (int) (selectorSource >>> 32);
3081 pushOnAstStack(cd);
3082 cd.sourceEnd = this.lParenPos;
3083 cd.bodyStart = this.lParenPos+1;
3084 this.listLength = 0; // initialize this.listLength before reading parameters/throws
3085
3086 // recovery
3087 if (this.currentElement != null){
3088 this.lastCheckPoint = cd.bodyStart;
3089 if ((this.currentElement instanceof RecoveredType && this.lastIgnoredToken != TokenNameDOT)
3090 || cd.modifiers != 0){
3091 this.currentElement = this.currentElement.add(cd, 0);
3092 this.lastIgnoredToken = -1;
3093 }
3094 }
3095 }
3096 // TODO: Refactor code for constructor and compact one once records are standardized.
populateCompactConstructor(CompactConstructorDeclaration ccd)3097 private void populateCompactConstructor(CompactConstructorDeclaration ccd) {
3098 //name -- this is not really revelant but we do .....
3099 ccd.selector = this.identifierStack[this.identifierPtr];
3100 long selectorSource = this.identifierPositionStack[this.identifierPtr--];
3101 this.identifierLengthPtr--;
3102
3103 //modifiers
3104 ccd.declarationSourceStart = this.intStack[this.intPtr--];
3105 ccd.modifiers = this.intStack[this.intPtr--];
3106 // consume annotations
3107 int length;
3108 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
3109 System.arraycopy(
3110 this.expressionStack,
3111 (this.expressionPtr -= length) + 1,
3112 ccd.annotations = new Annotation[length],
3113 0,
3114 length);
3115 }
3116 // javadoc
3117 ccd.javadoc = this.javadoc;
3118 this.javadoc = null;
3119
3120 //highlight starts at the selector starts
3121 ccd.sourceStart = (int) (selectorSource >>> 32);
3122 pushOnAstStack(ccd);
3123 ccd.sourceEnd = ccd.sourceStart + ccd.selector.length - 1; // no lParen for compact constructor
3124 ccd.bodyStart = ccd.sourceStart + ccd.selector.length;
3125 this.listLength = 0; // initialize this.listLength before reading parameters/throws
3126
3127 // recovery
3128 if (this.currentElement != null){
3129 this.lastCheckPoint = ccd.bodyStart;
3130 if ((this.currentElement instanceof RecoveredType && this.lastIgnoredToken != TokenNameDOT)
3131 || ccd.modifiers != 0){
3132 this.currentElement = this.currentElement.add(ccd, 0);
3133 this.lastIgnoredToken = -1;
3134 }
3135 }
3136 }
consumeConstructorHeaderNameWithTypeParameters()3137 protected void consumeConstructorHeaderNameWithTypeParameters() {
3138
3139 /* recovering - might be an empty message send */
3140 if (this.currentElement != null){
3141 if (this.lastIgnoredToken == TokenNamenew){ // was an allocation expression
3142 this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
3143 this.restartRecovery = true;
3144 return;
3145 }
3146 }
3147
3148 // ConstructorHeaderName ::= Modifiersopt TypeParameters 'Identifier' '('
3149 ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationUnit.compilationResult);
3150
3151 helperConstructorHeaderNameWithTypeParameters(cd);
3152 }
helperConstructorHeaderNameWithTypeParameters(ConstructorDeclaration cd)3153 private void helperConstructorHeaderNameWithTypeParameters(ConstructorDeclaration cd) {
3154 //name -- this is not really revelant but we do .....
3155 cd.selector = this.identifierStack[this.identifierPtr];
3156 long selectorSource = this.identifierPositionStack[this.identifierPtr--];
3157 this.identifierLengthPtr--;
3158
3159 // consume type parameters
3160 int length = this.genericsLengthStack[this.genericsLengthPtr--];
3161 this.genericsPtr -= length;
3162 System.arraycopy(this.genericsStack, this.genericsPtr + 1, cd.typeParameters = new TypeParameter[length], 0, length);
3163
3164 //modifiers
3165 cd.declarationSourceStart = this.intStack[this.intPtr--];
3166 cd.modifiers = this.intStack[this.intPtr--];
3167 // consume annotations
3168 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
3169 System.arraycopy(
3170 this.expressionStack,
3171 (this.expressionPtr -= length) + 1,
3172 cd.annotations = new Annotation[length],
3173 0,
3174 length);
3175 }
3176 // javadoc
3177 cd.javadoc = this.javadoc;
3178 this.javadoc = null;
3179
3180 //highlight starts at the selector starts
3181 cd.sourceStart = (int) (selectorSource >>> 32);
3182 pushOnAstStack(cd);
3183 cd.sourceEnd = this.lParenPos;
3184 cd.bodyStart = this.lParenPos+1;
3185 this.listLength = 0; // initialize this.listLength before reading parameters/throws
3186
3187 // recovery
3188 if (this.currentElement != null){
3189 this.lastCheckPoint = cd.bodyStart;
3190 if ((this.currentElement instanceof RecoveredType && this.lastIgnoredToken != TokenNameDOT)
3191 || cd.modifiers != 0){
3192 this.currentElement = this.currentElement.add(cd, 0);
3193 this.lastIgnoredToken = -1;
3194 }
3195 }
3196 }
consumeCreateInitializer()3197 protected void consumeCreateInitializer() {
3198 pushOnAstStack(new Initializer(null, 0));
3199 }
consumeDefaultLabel()3200 protected void consumeDefaultLabel() {
3201 // SwitchLabel ::= 'default' ':'
3202 CaseStatement defaultStatement = new CaseStatement(null, this.intStack[this.intPtr--], this.intStack[this.intPtr--]);
3203 // Look for $fall-through$ and $CASES-OMITTED$ tags in leading comment for case statement
3204 if (hasLeadingTagComment(FALL_THROUGH_TAG, defaultStatement.sourceStart)) {
3205 defaultStatement.bits |= ASTNode.DocumentedFallthrough;
3206 }
3207 if (hasLeadingTagComment(CASES_OMITTED_TAG, defaultStatement.sourceStart)) {
3208 defaultStatement.bits |= ASTNode.DocumentedCasesOmitted;
3209 }
3210 pushOnAstStack(defaultStatement);
3211 }
consumeDefaultModifiers()3212 protected void consumeDefaultModifiers() {
3213 checkComment(); // might update modifiers with AccDeprecated
3214 pushOnIntStack(this.modifiers); // modifiers
3215 pushOnIntStack(
3216 this.modifiersSourceStart >= 0 ? this.modifiersSourceStart : this.scanner.startPosition);
3217 resetModifiers();
3218 pushOnExpressionStackLengthStack(0); // no annotation
3219 }
consumeDiet()3220 protected void consumeDiet() {
3221 // Diet ::= $empty
3222 checkComment();
3223 pushOnIntStack(this.modifiersSourceStart); // push the start position of a javadoc comment if there is one
3224 resetModifiers();
3225 jumpOverMethodBody();
3226 }
consumeDims()3227 protected void consumeDims() {
3228 // Dims ::= DimsLoop
3229 pushOnIntStack(this.dimensions);
3230 this.dimensions = 0;
3231 }
consumeDimWithOrWithOutExpr()3232 protected void consumeDimWithOrWithOutExpr() {
3233 // DimWithOrWithOutExpr ::= TypeAnnotationsopt '[' ']'
3234 // DimWithOrWithOutExpr ::= TypeAnnotationsopt '[' Expression ']'
3235 pushOnExpressionStack(null);
3236
3237 if(this.currentElement != null && this.currentToken == TokenNameLBRACE) {
3238 this.ignoreNextOpeningBrace = true;
3239 this.currentElement.bracketBalance++;
3240 }
3241 }
consumeDimWithOrWithOutExprs()3242 protected void consumeDimWithOrWithOutExprs() {
3243 // DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr
3244 concatExpressionLists();
3245 }
consumeUnionType()3246 protected void consumeUnionType() {
3247 // UnionType ::= UnionType '|' Type
3248 pushOnAstStack(getTypeReference(this.intStack[this.intPtr--]));
3249 optimizedConcatNodeLists();
3250 }
consumeUnionTypeAsClassType()3251 protected void consumeUnionTypeAsClassType() {
3252 // UnionType ::= Type
3253 pushOnAstStack(getTypeReference(this.intStack[this.intPtr--]));
3254 }
consumeEmptyAnnotationTypeMemberDeclarationsopt()3255 protected void consumeEmptyAnnotationTypeMemberDeclarationsopt() {
3256 // AnnotationTypeMemberDeclarationsopt ::= $empty
3257 pushOnAstLengthStack(0);
3258 }
consumeEmptyArgumentListopt()3259 protected void consumeEmptyArgumentListopt() {
3260 // ArgumentListopt ::= $empty
3261 pushOnExpressionStackLengthStack(0);
3262 }
consumeEmptyArguments()3263 protected void consumeEmptyArguments() {
3264 // Argumentsopt ::= $empty
3265 final FieldDeclaration fieldDeclaration = (FieldDeclaration) this.astStack[this.astPtr];
3266 pushOnIntStack(fieldDeclaration.sourceEnd);
3267 pushOnExpressionStackLengthStack(0);
3268 }
consumeEmptyArrayInitializer()3269 protected void consumeEmptyArrayInitializer() {
3270 // ArrayInitializer ::= '{' ,opt '}'
3271 arrayInitializer(0);
3272 }
consumeEmptyArrayInitializeropt()3273 protected void consumeEmptyArrayInitializeropt() {
3274 // ArrayInitializeropt ::= $empty
3275 pushOnExpressionStackLengthStack(0);
3276 }
consumeEmptyBlockStatementsopt()3277 protected void consumeEmptyBlockStatementsopt() {
3278 // BlockStatementsopt ::= $empty
3279 pushOnAstLengthStack(0);
3280 }
consumeEmptyCatchesopt()3281 protected void consumeEmptyCatchesopt() {
3282 // Catchesopt ::= $empty
3283 pushOnAstLengthStack(0);
3284 }
consumeEmptyClassBodyDeclarationsopt()3285 protected void consumeEmptyClassBodyDeclarationsopt() {
3286 // ClassBodyDeclarationsopt ::= $empty
3287 pushOnAstLengthStack(0);
3288 }
consumeEmptyDimsopt()3289 protected void consumeEmptyDimsopt() {
3290 // Dimsopt ::= $empty
3291 pushOnIntStack(0);
3292 }
consumeEmptyEnumDeclarations()3293 protected void consumeEmptyEnumDeclarations() {
3294 // EnumBodyDeclarationsopt ::= $empty
3295 pushOnAstLengthStack(0);
3296 }
consumeEmptyExpression()3297 protected void consumeEmptyExpression() {
3298 // Expressionopt ::= $empty
3299 pushOnExpressionStackLengthStack(0);
3300 }
consumeEmptyForInitopt()3301 protected void consumeEmptyForInitopt() {
3302 // ForInitopt ::= $empty
3303 pushOnAstLengthStack(0);
3304 this.forStartPosition = 0;
3305 }
consumeEmptyForUpdateopt()3306 protected void consumeEmptyForUpdateopt() {
3307 // ForUpdateopt ::= $empty
3308 pushOnExpressionStackLengthStack(0);
3309 }
consumeEmptyInterfaceMemberDeclarationsopt()3310 protected void consumeEmptyInterfaceMemberDeclarationsopt() {
3311 // InterfaceMemberDeclarationsopt ::= $empty
3312 pushOnAstLengthStack(0);
3313 }
consumeEmptyInternalCompilationUnit()3314 protected void consumeEmptyInternalCompilationUnit() {
3315 // InternalCompilationUnit ::= $empty
3316 // nothing to do by default
3317 if (this.compilationUnit.isPackageInfo()) {
3318 this.compilationUnit.types = new TypeDeclaration[1];
3319 this.compilationUnit.createPackageInfoType();
3320 }
3321 }
consumeEmptyMemberValueArrayInitializer()3322 protected void consumeEmptyMemberValueArrayInitializer() {
3323 // MemberValueArrayInitializer ::= '{' ',' '}'
3324 // MemberValueArrayInitializer ::= '{' '}'
3325 arrayInitializer(0);
3326 }
consumeEmptyMemberValuePairsopt()3327 protected void consumeEmptyMemberValuePairsopt() {
3328 // MemberValuePairsopt ::= $empty
3329 pushOnAstLengthStack(0);
3330 }
consumeEmptyMethodHeaderDefaultValue()3331 protected void consumeEmptyMethodHeaderDefaultValue() {
3332 // DefaultValueopt ::= $empty
3333 AbstractMethodDeclaration method = (AbstractMethodDeclaration)this.astStack[this.astPtr];
3334 if(method.isAnnotationMethod()) { //'method' can be a MethodDeclaration when recovery is started
3335 pushOnExpressionStackLengthStack(0);
3336 }
3337 this.recordStringLiterals = true;
3338 }
consumeEmptyStatement()3339 protected void consumeEmptyStatement() {
3340 // EmptyStatement ::= ';'
3341 char[] source = this.scanner.source;
3342 if (source[this.endStatementPosition] == ';') {
3343 pushOnAstStack(new EmptyStatement(this.endStatementPosition, this.endStatementPosition));
3344 } else {
3345 if(source.length > 5) {
3346 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
3347 int pos = this.endStatementPosition - 4;
3348 while (source[pos] == 'u') {
3349 pos--;
3350 }
3351 if (source[pos] == '\\' &&
3352 !((c1 = ScannerHelper.getHexadecimalValue(source[this.endStatementPosition - 3])) > 15
3353 || c1 < 0
3354 || (c2 = ScannerHelper.getHexadecimalValue(source[this.endStatementPosition - 2])) > 15
3355 || c2 < 0
3356 || (c3 = ScannerHelper.getHexadecimalValue(source[this.endStatementPosition - 1])) > 15
3357 || c3 < 0
3358 || (c4 = ScannerHelper.getHexadecimalValue(source[this.endStatementPosition])) > 15
3359 || c4 < 0) &&
3360 ((char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4)) == ';'){
3361 // we have a Unicode for the ';' (/u003B)
3362 pushOnAstStack(new EmptyStatement(pos, this.endStatementPosition));
3363 return;
3364 }
3365 }
3366 pushOnAstStack(new EmptyStatement(this.endPosition + 1, this.endStatementPosition));
3367 }
3368 }
consumeEmptySwitchBlock()3369 protected void consumeEmptySwitchBlock() {
3370 // SwitchBlock ::= '{' '}'
3371 pushOnAstLengthStack(0);
3372 }
consumeEmptyTypeDeclaration()3373 protected void consumeEmptyTypeDeclaration() {
3374 // ClassMemberDeclaration ::= ';'
3375 // InterfaceMemberDeclaration ::= ';'
3376 // TypeDeclaration ::= ';'
3377 pushOnAstLengthStack(0);
3378 if(!this.statementRecoveryActivated) problemReporter().superfluousSemicolon(this.endPosition+1, this.endStatementPosition);
3379 flushCommentsDefinedPriorTo(this.endStatementPosition);
3380 }
consumeEnhancedForStatement()3381 protected void consumeEnhancedForStatement() {
3382 // EnhancedForStatement ::= EnhancedForStatementHeader Statement
3383 // EnhancedForStatementNoShortIf ::= EnhancedForStatementHeader StatementNoShortIf
3384
3385 //statements
3386 this.astLengthPtr--;
3387 Statement statement = (Statement) this.astStack[this.astPtr--];
3388
3389 // foreach statement is on the ast stack
3390 ForeachStatement foreachStatement = (ForeachStatement) this.astStack[this.astPtr];
3391 foreachStatement.action = statement;
3392 // remember useful empty statement
3393 if (statement instanceof EmptyStatement) statement.bits |= ASTNode.IsUsefulEmptyStatement;
3394
3395 foreachStatement.sourceEnd = this.endStatementPosition;
3396 }
consumeEnhancedForStatementHeader()3397 protected void consumeEnhancedForStatementHeader(){
3398 // EnhancedForStatementHeader ::= EnhancedForStatementHeaderInit ':' Expression ')'
3399 final ForeachStatement statement = (ForeachStatement) this.astStack[this.astPtr];
3400 //updates are on the expression stack
3401 this.expressionLengthPtr--;
3402 final Expression collection = this.expressionStack[this.expressionPtr--];
3403 statement.collection = collection;
3404 // https://bugs.eclipse.org/393719 - [compiler] inconsistent warnings on iteration variables
3405 // let declaration(Source)End include the collection to achieve that @SuppressWarnings affects this part, too:
3406 statement.elementVariable.declarationSourceEnd = collection.sourceEnd;
3407 statement.elementVariable.declarationEnd = collection.sourceEnd;
3408 statement.sourceEnd = this.rParenPos;
3409
3410 if(!this.statementRecoveryActivated &&
3411 this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
3412 this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
3413 problemReporter().invalidUsageOfForeachStatements(statement.elementVariable, collection);
3414 }
3415 }
consumeEnhancedForStatementHeaderInit(boolean hasModifiers)3416 protected void consumeEnhancedForStatementHeaderInit(boolean hasModifiers) {
3417 TypeReference type;
3418
3419 char[] identifierName = this.identifierStack[this.identifierPtr];
3420 long namePosition = this.identifierPositionStack[this.identifierPtr];
3421
3422 LocalDeclaration localDeclaration = createLocalDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition);
3423 localDeclaration.declarationSourceEnd = localDeclaration.declarationEnd;
3424 localDeclaration.bits |= ASTNode.IsForeachElementVariable;
3425
3426 int extraDims = this.intStack[this.intPtr--];
3427 Annotation [][] annotationsOnExtendedDimensions = extraDims == 0 ? null : getAnnotationsOnDimensions(extraDims);
3428 this.identifierPtr--;
3429 this.identifierLengthPtr--;
3430 // remove fake modifiers/modifiers start
3431 int declarationSourceStart = 0;
3432 int modifiersValue = 0;
3433 if (hasModifiers) {
3434 declarationSourceStart = this.intStack[this.intPtr--];
3435 modifiersValue = this.intStack[this.intPtr--];
3436 } else {
3437 this.intPtr-=2;
3438 }
3439
3440 type = getTypeReference(this.intStack[this.intPtr--]); // type dimension
3441
3442 // consume annotations
3443 int length;
3444 if ((length = this.expressionLengthStack[this.expressionLengthPtr--])!= 0) {
3445 System.arraycopy(
3446 this.expressionStack,
3447 (this.expressionPtr -= length) + 1,
3448 localDeclaration.annotations = new Annotation[length],
3449 0,
3450 length);
3451 localDeclaration.bits |= ASTNode.HasTypeAnnotations;
3452 }
3453 if (extraDims != 0) {
3454 type = augmentTypeWithAdditionalDimensions(type, extraDims, annotationsOnExtendedDimensions, false);
3455 }
3456 if (hasModifiers) {
3457 localDeclaration.declarationSourceStart = declarationSourceStart;
3458 localDeclaration.modifiers = modifiersValue;
3459 } else {
3460 localDeclaration.declarationSourceStart = type.sourceStart;
3461 }
3462 localDeclaration.type = type;
3463 localDeclaration.bits |= (type.bits & ASTNode.HasTypeAnnotations);
3464
3465 ForeachStatement iteratorForStatement =
3466 new ForeachStatement(
3467 localDeclaration,
3468 this.intStack[this.intPtr--]);
3469 pushOnAstStack(iteratorForStatement);
3470
3471 iteratorForStatement.sourceEnd = localDeclaration.declarationSourceEnd;
3472 this.forStartPosition = 0;
3473 }
consumeEnterAnonymousClassBody(boolean qualified)3474 protected void consumeEnterAnonymousClassBody(boolean qualified) {
3475 // EnterAnonymousClassBody ::= $empty
3476 TypeReference typeReference = getTypeReference(0);
3477
3478 TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult);
3479 anonymousType.name = CharOperation.NO_CHAR;
3480 anonymousType.bits |= (ASTNode.IsAnonymousType|ASTNode.IsLocalType);
3481 anonymousType.bits |= (typeReference.bits & ASTNode.HasTypeAnnotations);
3482 QualifiedAllocationExpression alloc = new QualifiedAllocationExpression(anonymousType);
3483 markEnclosingMemberWithLocalType();
3484 pushOnAstStack(anonymousType);
3485
3486 alloc.sourceEnd = this.rParenPos; //the position has been stored explicitly
3487 int argumentLength;
3488 if ((argumentLength = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
3489 this.expressionPtr -= argumentLength;
3490 System.arraycopy(
3491 this.expressionStack,
3492 this.expressionPtr + 1,
3493 alloc.arguments = new Expression[argumentLength],
3494 0,
3495 argumentLength);
3496 }
3497
3498 if (qualified) {
3499 this.expressionLengthPtr--;
3500 alloc.enclosingInstance = this.expressionStack[this.expressionPtr--];
3501 }
3502
3503 alloc.type = typeReference;
3504
3505 anonymousType.sourceEnd = alloc.sourceEnd;
3506 //position at the type while it impacts the anonymous declaration
3507 anonymousType.sourceStart = anonymousType.declarationSourceStart = alloc.type.sourceStart;
3508 alloc.sourceStart = this.intStack[this.intPtr--];
3509 pushOnExpressionStack(alloc);
3510
3511 anonymousType.bodyStart = this.scanner.currentPosition;
3512 this.listLength = 0; // will be updated when reading super-interfaces
3513
3514 // flush the comments related to the anonymous
3515 this.scanner.commentPtr = -1;
3516
3517 // recovery
3518 if (this.currentElement != null){
3519 this.lastCheckPoint = anonymousType.bodyStart;
3520 this.currentElement = this.currentElement.add(anonymousType, 0);
3521 if (!(this.currentElement instanceof RecoveredAnnotation)) {
3522 if (isIndirectlyInsideLambdaExpression())
3523 this.ignoreNextOpeningBrace = true;
3524 else
3525 this.currentToken = 0; // opening brace already taken into account
3526 } else {
3527 this.ignoreNextOpeningBrace = true;
3528 this.currentElement.bracketBalance++;
3529 }
3530 this.lastIgnoredToken = -1;
3531 }
3532 }
consumeEnterCompilationUnit()3533 protected void consumeEnterCompilationUnit() {
3534 // EnterCompilationUnit ::= $empty
3535 // do nothing by default
3536 }
consumeEnterMemberValue()3537 protected void consumeEnterMemberValue() {
3538 // EnterMemberValue ::= $empty
3539 if (this.currentElement != null && this.currentElement instanceof RecoveredAnnotation) {
3540 RecoveredAnnotation recoveredAnnotation = (RecoveredAnnotation)this.currentElement;
3541 recoveredAnnotation.hasPendingMemberValueName = true;
3542 }
3543 }
consumeEnterMemberValueArrayInitializer()3544 protected void consumeEnterMemberValueArrayInitializer() {
3545 // EnterMemberValueArrayInitializer ::= $empty
3546 if(this.currentElement != null) {
3547 this.ignoreNextOpeningBrace = true;
3548 this.currentElement.bracketBalance++;
3549 }
3550 }
isAFieldDeclarationInRecord()3551 private boolean isAFieldDeclarationInRecord() {
3552 if (this.options.sourceLevel < ClassFileConstants.JDK14)
3553 return false;
3554 int recordIndex = -1;
3555 Integer[] nestingTypeAndMethod = null;
3556 for (int i = this.astPtr; i >= 0; --i) {
3557 if (this.astStack[i] instanceof TypeDeclaration) {
3558 TypeDeclaration node = (TypeDeclaration) this.astStack[i];
3559 if (!node.isRecord())
3560 continue;
3561 nestingTypeAndMethod = this.recordNestedMethodLevels.get(node);
3562 if (nestingTypeAndMethod != null) { // record declaration is done yet
3563 recordIndex = i;
3564 break;
3565 }
3566 }
3567 }
3568 if (recordIndex < 0)
3569 return false;
3570 for (int i = recordIndex + 1; i <= this.astPtr; ++i) {
3571 ASTNode node = this.astStack[i];
3572 if (node instanceof TypeDeclaration) {
3573 if (node.sourceEnd < 0) {
3574 return false;
3575 }
3576 } else if (node instanceof AbstractMethodDeclaration) {
3577 if (this.nestedType != nestingTypeAndMethod[0] ||
3578 this.nestedMethod[this.nestedType] != nestingTypeAndMethod[1])
3579 return false;
3580 } else if (node instanceof FieldDeclaration) {
3581 continue;
3582 } else {
3583 return false;
3584 }
3585 }
3586 return true;
3587 }
consumeEnterVariable()3588 protected void consumeEnterVariable() {
3589 // EnterVariable ::= $empty
3590 // do nothing by default
3591
3592 char[] identifierName = this.identifierStack[this.identifierPtr];
3593 long namePosition = this.identifierPositionStack[this.identifierPtr];
3594 int extendedDimensions = this.intStack[this.intPtr--];
3595 // pop any annotations on extended dimensions now, so they don't pollute the base dimensions.
3596 Annotation [][] annotationsOnExtendedDimensions = extendedDimensions == 0 ? null : getAnnotationsOnDimensions(extendedDimensions);
3597 AbstractVariableDeclaration declaration;
3598 // create the ast node
3599 boolean isLocalDeclaration = this.nestedMethod[this.nestedType] != 0 &&
3600 !isAFieldDeclarationInRecord();
3601 if (isLocalDeclaration) {
3602 // create the local variable declarations
3603 declaration =
3604 createLocalDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition);
3605 } else {
3606 // create the field declaration
3607 declaration =
3608 createFieldDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition);
3609 }
3610
3611 this.identifierPtr--;
3612 this.identifierLengthPtr--;
3613 TypeReference type;
3614 int variableIndex = this.variablesCounter[this.nestedType];
3615 if (variableIndex == 0) {
3616 // first variable of the declaration (FieldDeclaration or LocalDeclaration)
3617 if (isLocalDeclaration) {
3618 declaration.declarationSourceStart = this.intStack[this.intPtr--];
3619 declaration.modifiers = this.intStack[this.intPtr--];
3620 // consume annotations
3621 int length;
3622 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
3623 System.arraycopy(
3624 this.expressionStack,
3625 (this.expressionPtr -= length) + 1,
3626 declaration.annotations = new Annotation[length],
3627 0,
3628 length);
3629 }
3630 type = getTypeReference(this.intStack[this.intPtr--]); // type dimension
3631 if (declaration.declarationSourceStart == -1) {
3632 // this is true if there is no modifiers for the local variable declaration
3633 declaration.declarationSourceStart = type.sourceStart;
3634 }
3635 pushOnAstStack(type);
3636 } else {
3637 type = getTypeReference(this.intStack[this.intPtr--]); // type dimension
3638 pushOnAstStack(type);
3639 declaration.declarationSourceStart = this.intStack[this.intPtr--];
3640 declaration.modifiers = this.intStack[this.intPtr--];
3641 // consume annotations
3642 int length;
3643 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
3644 System.arraycopy(
3645 this.expressionStack,
3646 (this.expressionPtr -= length) + 1,
3647 declaration.annotations = new Annotation[length],
3648 0,
3649 length);
3650 }
3651 // Store javadoc only on first declaration as it is the same for all ones
3652 FieldDeclaration fieldDeclaration = (FieldDeclaration) declaration;
3653 fieldDeclaration.javadoc = this.javadoc;
3654 }
3655 this.javadoc = null;
3656 } else {
3657 type = (TypeReference) this.astStack[this.astPtr - variableIndex];
3658 AbstractVariableDeclaration previousVariable =
3659 (AbstractVariableDeclaration) this.astStack[this.astPtr];
3660 declaration.declarationSourceStart = previousVariable.declarationSourceStart;
3661 declaration.modifiers = previousVariable.modifiers;
3662 final Annotation[] annotations = previousVariable.annotations;
3663 if (annotations != null) {
3664 final int annotationsLength = annotations.length;
3665 System.arraycopy(annotations, 0, declaration.annotations = new Annotation[annotationsLength], 0, annotationsLength);
3666 }
3667 declaration.bits |= ASTNode.IsAdditionalDeclarator;
3668 }
3669
3670 declaration.type = extendedDimensions == 0 ? type : augmentTypeWithAdditionalDimensions(type, extendedDimensions, annotationsOnExtendedDimensions, false);
3671 declaration.bits |= (type.bits & ASTNode.HasTypeAnnotations);
3672
3673 this.variablesCounter[this.nestedType]++;
3674 pushOnAstStack(declaration);
3675 // recovery
3676 if (this.currentElement != null) {
3677 if (!(this.currentElement instanceof RecoveredType)
3678 && (this.currentToken == TokenNameDOT
3679 //|| declaration.modifiers != 0
3680 || (Util.getLineNumber(declaration.type.sourceStart, this.scanner.lineEnds, 0, this.scanner.linePtr)
3681 != Util.getLineNumber((int) (namePosition >>> 32), this.scanner.lineEnds, 0, this.scanner.linePtr)))){
3682 this.lastCheckPoint = (int) (namePosition >>> 32);
3683 this.restartRecovery = true;
3684 return;
3685 }
3686 if (isLocalDeclaration){
3687 LocalDeclaration localDecl = (LocalDeclaration) this.astStack[this.astPtr];
3688 this.lastCheckPoint = localDecl.sourceEnd + 1;
3689 this.currentElement = this.currentElement.add(localDecl, 0);
3690 } else {
3691 FieldDeclaration fieldDecl = (FieldDeclaration) this.astStack[this.astPtr];
3692 this.lastCheckPoint = fieldDecl.sourceEnd + 1;
3693 this.currentElement = this.currentElement.add(fieldDecl, 0);
3694 }
3695 this.lastIgnoredToken = -1;
3696 }
3697 }
consumeEnumBodyNoConstants()3698 protected void consumeEnumBodyNoConstants() {
3699 // nothing to do
3700 // The 0 on the astLengthStack has been pushed by EnumBodyDeclarationsopt
3701 }
consumeEnumBodyWithConstants()3702 protected void consumeEnumBodyWithConstants() {
3703 // merge the constants values with the class body
3704 concatNodeLists();
3705 }
consumeEnumConstantHeader()3706 protected void consumeEnumConstantHeader() {
3707 FieldDeclaration enumConstant = (FieldDeclaration) this.astStack[this.astPtr];
3708 boolean foundOpeningBrace = this.currentToken == TokenNameLBRACE;
3709 if (foundOpeningBrace){
3710 // qualified allocation expression
3711 TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult);
3712 anonymousType.name = CharOperation.NO_CHAR;
3713 anonymousType.bits |= (ASTNode.IsAnonymousType|ASTNode.IsLocalType);
3714 final int start = this.scanner.startPosition;
3715 anonymousType.declarationSourceStart = start;
3716 anonymousType.sourceStart = start;
3717 anonymousType.sourceEnd = start; // closing parenthesis
3718 anonymousType.modifiers = 0;
3719 anonymousType.bodyStart = this.scanner.currentPosition;
3720 markEnclosingMemberWithLocalType();
3721 consumeNestedType();
3722 this.variablesCounter[this.nestedType]++;
3723 pushOnAstStack(anonymousType);
3724 QualifiedAllocationExpression allocationExpression = new QualifiedAllocationExpression(anonymousType);
3725 allocationExpression.enumConstant = enumConstant;
3726
3727 // fill arguments if needed
3728 int length;
3729 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
3730 this.expressionPtr -= length;
3731 System.arraycopy(
3732 this.expressionStack,
3733 this.expressionPtr + 1,
3734 allocationExpression.arguments = new Expression[length],
3735 0,
3736 length);
3737 }
3738 enumConstant.initialization = allocationExpression;
3739 } else {
3740 AllocationExpression allocationExpression = new AllocationExpression();
3741 allocationExpression.enumConstant = enumConstant;
3742 // fill arguments if needed
3743 int length;
3744 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
3745 this.expressionPtr -= length;
3746 System.arraycopy(
3747 this.expressionStack,
3748 this.expressionPtr + 1,
3749 allocationExpression.arguments = new Expression[length],
3750 0,
3751 length);
3752 }
3753 enumConstant.initialization = allocationExpression;
3754 }
3755 // initialize the starting position of the allocation expression
3756 enumConstant.initialization.sourceStart = enumConstant.declarationSourceStart;
3757
3758 // recovery
3759 if (this.currentElement != null) {
3760 if(foundOpeningBrace) {
3761 TypeDeclaration anonymousType = (TypeDeclaration) this.astStack[this.astPtr];
3762 this.currentElement = this.currentElement.add(anonymousType, 0);
3763 this.lastCheckPoint = anonymousType.bodyStart;
3764 this.lastIgnoredToken = -1;
3765 if (isIndirectlyInsideLambdaExpression())
3766 this.ignoreNextOpeningBrace = true;
3767 else
3768 this.currentToken = 0; // opening brace already taken into account
3769 } else {
3770 if(this.currentToken == TokenNameSEMICOLON) {
3771 RecoveredType currentType = currentRecoveryType();
3772 if(currentType != null) {
3773 currentType.insideEnumConstantPart = false;
3774 }
3775 }
3776 this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
3777 this.lastIgnoredToken = -1;
3778 this.restartRecovery = true;
3779 }
3780 }
3781 }
consumeEnumConstantHeaderName()3782 protected void consumeEnumConstantHeaderName() {
3783 if (this.currentElement != null) {
3784 if (!(this.currentElement instanceof RecoveredType
3785 || (this.currentElement instanceof RecoveredField && ((RecoveredField)this.currentElement).fieldDeclaration.type == null))
3786 || (this.lastIgnoredToken == TokenNameDOT)) {
3787 this.lastCheckPoint = this.scanner.startPosition;
3788 this.restartRecovery = true;
3789 return;
3790 }
3791 }
3792 long namePosition = this.identifierPositionStack[this.identifierPtr];
3793 char[] constantName = this.identifierStack[this.identifierPtr];
3794 final int sourceEnd = (int) namePosition;
3795 FieldDeclaration enumConstant = createFieldDeclaration(constantName, (int) (namePosition >>> 32), sourceEnd);
3796 this.identifierPtr--;
3797 this.identifierLengthPtr--;
3798 enumConstant.modifiersSourceStart = this.intStack[this.intPtr--];
3799 enumConstant.modifiers = this.intStack[this.intPtr--];
3800 enumConstant.declarationSourceStart = enumConstant.modifiersSourceStart;
3801
3802 // consume annotations
3803 int length;
3804 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
3805 System.arraycopy(
3806 this.expressionStack,
3807 (this.expressionPtr -= length) + 1,
3808 enumConstant.annotations = new Annotation[length],
3809 0,
3810 length);
3811 enumConstant.bits |= ASTNode.HasTypeAnnotations;
3812 }
3813 pushOnAstStack(enumConstant);
3814 if (this.currentElement != null){
3815 this.lastCheckPoint = enumConstant.sourceEnd + 1;
3816 this.currentElement = this.currentElement.add(enumConstant, 0);
3817 }
3818 // javadoc
3819 enumConstant.javadoc = this.javadoc;
3820 this.javadoc = null;
3821 }
consumeEnumConstantNoClassBody()3822 protected void consumeEnumConstantNoClassBody() {
3823 // set declarationEnd and declarationSourceEnd
3824 int endOfEnumConstant = this.intStack[this.intPtr--];
3825 final FieldDeclaration fieldDeclaration = (FieldDeclaration) this.astStack[this.astPtr];
3826 fieldDeclaration.declarationEnd = endOfEnumConstant;
3827 fieldDeclaration.declarationSourceEnd = endOfEnumConstant;
3828 // initialize the starting position of the allocation expression
3829 ASTNode initialization = fieldDeclaration.initialization;
3830 if (initialization != null) {
3831 initialization.sourceEnd = endOfEnumConstant;
3832 }
3833 }
consumeEnumConstants()3834 protected void consumeEnumConstants() {
3835 concatNodeLists();
3836 }
consumeEnumConstantWithClassBody()3837 protected void consumeEnumConstantWithClassBody() {
3838 dispatchDeclarationInto(this.astLengthStack[this.astLengthPtr--]);
3839 TypeDeclaration anonymousType = (TypeDeclaration) this.astStack[this.astPtr--]; // pop type
3840 this.astLengthPtr--;
3841 anonymousType.bodyEnd = this.endPosition;
3842 anonymousType.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
3843 final FieldDeclaration fieldDeclaration = ((FieldDeclaration) this.astStack[this.astPtr]);
3844 fieldDeclaration.declarationEnd = this.endStatementPosition;
3845 int declarationSourceEnd = anonymousType.declarationSourceEnd;
3846 fieldDeclaration.declarationSourceEnd = declarationSourceEnd;
3847 this.intPtr --; // remove end position of the arguments
3848 this.variablesCounter[this.nestedType] = 0;
3849 this.nestedType--;
3850 ASTNode initialization = fieldDeclaration.initialization;
3851 if (initialization != null) {
3852 initialization.sourceEnd = declarationSourceEnd;
3853 }
3854 }
consumeEnumDeclaration()3855 protected void consumeEnumDeclaration() {
3856 // EnumDeclaration ::= EnumHeader ClassHeaderImplementsopt EnumBody
3857 int length;
3858 if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
3859 //there are length declarations
3860 //dispatch according to the type of the declarations
3861 dispatchDeclarationIntoEnumDeclaration(length);
3862 }
3863
3864 TypeDeclaration enumDeclaration = (TypeDeclaration) this.astStack[this.astPtr];
3865
3866 //convert constructor that do not have the type's name into methods
3867 boolean hasConstructor = enumDeclaration.checkConstructors(this);
3868
3869 //add the default constructor when needed
3870 if (!hasConstructor) {
3871 boolean insideFieldInitializer = false;
3872 if (this.diet) {
3873 for (int i = this.nestedType; i > 0; i--){
3874 if (this.variablesCounter[i] > 0) {
3875 insideFieldInitializer = true;
3876 break;
3877 }
3878 }
3879 }
3880 enumDeclaration.createDefaultConstructor(!this.diet || insideFieldInitializer, true);
3881 }
3882
3883 //always add <clinit> (will be remove at code gen time if empty)
3884 if (this.scanner.containsAssertKeyword) {
3885 enumDeclaration.bits |= ASTNode.ContainsAssertion;
3886 }
3887 enumDeclaration.addClinit();
3888 enumDeclaration.bodyEnd = this.endStatementPosition;
3889 if (length == 0 && !containsComment(enumDeclaration.bodyStart, enumDeclaration.bodyEnd)) {
3890 enumDeclaration.bits |= ASTNode.UndocumentedEmptyBlock;
3891 }
3892
3893 enumDeclaration.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
3894 }
consumeEnumDeclarations()3895 protected void consumeEnumDeclarations() {
3896 // Do nothing by default
3897 }
consumeEnumHeader()3898 protected void consumeEnumHeader() {
3899 TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
3900 if (this.currentToken == TokenNameLBRACE) {
3901 typeDecl.bodyStart = this.scanner.currentPosition;
3902 }
3903
3904 if (this.currentElement != null) {
3905 this.restartRecovery = true; // used to avoid branching back into the regular automaton
3906 }
3907
3908 // flush the comments related to the enum header
3909 this.scanner.commentPtr = -1;
3910 }
consumeEnumHeaderName()3911 protected void consumeEnumHeaderName() {
3912 // EnumHeaderName ::= Modifiersopt 'enum' Identifier
3913 TypeDeclaration enumDeclaration = new TypeDeclaration(this.compilationUnit.compilationResult);
3914 if (this.nestedMethod[this.nestedType] == 0) {
3915 if (this.nestedType != 0) {
3916 enumDeclaration.bits |= ASTNode.IsMemberType;
3917 }
3918 } else {
3919 // Record that the block has a declaration for local types
3920 // markEnclosingMemberWithLocalType();
3921 blockReal();
3922 }
3923 //highlight the name of the type
3924 long pos = this.identifierPositionStack[this.identifierPtr];
3925 enumDeclaration.sourceEnd = (int) pos;
3926 enumDeclaration.sourceStart = (int) (pos >>> 32);
3927 enumDeclaration.name = this.identifierStack[this.identifierPtr--];
3928 this.identifierLengthPtr--;
3929
3930 //compute the declaration source too
3931 // 'class' and 'interface' push two int positions: the beginning of the class token and its end.
3932 // we want to keep the beginning position but get rid of the end position
3933 // it is only used for the ClassLiteralAccess positions.
3934 enumDeclaration.declarationSourceStart = this.intStack[this.intPtr--];
3935 this.intPtr--; // remove the end position of the class token
3936
3937 enumDeclaration.modifiersSourceStart = this.intStack[this.intPtr--];
3938 enumDeclaration.modifiers = this.intStack[this.intPtr--] | ClassFileConstants.AccEnum;
3939 if (enumDeclaration.modifiersSourceStart >= 0) {
3940 enumDeclaration.declarationSourceStart = enumDeclaration.modifiersSourceStart;
3941 }
3942
3943 // Store secondary info
3944 if ((enumDeclaration.bits & ASTNode.IsMemberType) == 0 && (enumDeclaration.bits & ASTNode.IsLocalType) == 0) {
3945 if (this.compilationUnit != null && !CharOperation.equals(enumDeclaration.name, this.compilationUnit.getMainTypeName())) {
3946 enumDeclaration.bits |= ASTNode.IsSecondaryType;
3947 }
3948 }
3949
3950 // consume annotations
3951 int length;
3952 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
3953 System.arraycopy(
3954 this.expressionStack,
3955 (this.expressionPtr -= length) + 1,
3956 enumDeclaration.annotations = new Annotation[length],
3957 0,
3958 length);
3959 }
3960 // if (this.currentToken == TokenNameLBRACE) {
3961 // enumDeclaration.bodyStart = this.scanner.currentPosition;
3962 // }
3963 enumDeclaration.bodyStart = enumDeclaration.sourceEnd + 1;
3964 pushOnAstStack(enumDeclaration);
3965
3966 this.listLength = 0; // will be updated when reading super-interfaces
3967
3968 if(!this.statementRecoveryActivated &&
3969 this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
3970 this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
3971 //TODO this code will be never run while 'enum' is an identifier in 1.3 scanner
3972 problemReporter().invalidUsageOfEnumDeclarations(enumDeclaration);
3973 }
3974
3975 // recovery
3976 if (this.currentElement != null){
3977 this.lastCheckPoint = enumDeclaration.bodyStart;
3978 this.currentElement = this.currentElement.add(enumDeclaration, 0);
3979 this.lastIgnoredToken = -1;
3980 }
3981 // javadoc
3982 enumDeclaration.javadoc = this.javadoc;
3983 this.javadoc = null;
3984 }
consumeEnumHeaderNameWithTypeParameters()3985 protected void consumeEnumHeaderNameWithTypeParameters() {
3986 // EnumHeaderNameWithTypeParameters ::= Modifiersopt 'enum' Identifier TypeParameters
3987 TypeDeclaration enumDeclaration = new TypeDeclaration(this.compilationUnit.compilationResult);
3988 // consume type parameters
3989 int length = this.genericsLengthStack[this.genericsLengthPtr--];
3990 this.genericsPtr -= length;
3991 System.arraycopy(this.genericsStack, this.genericsPtr + 1, enumDeclaration.typeParameters = new TypeParameter[length], 0, length);
3992
3993 problemReporter().invalidUsageOfTypeParametersForEnumDeclaration(enumDeclaration);
3994
3995 enumDeclaration.bodyStart = enumDeclaration.typeParameters[length-1].declarationSourceEnd + 1;
3996
3997 // enumDeclaration.typeParameters = null;
3998
3999 this.listTypeParameterLength = 0;
4000
4001 if (this.nestedMethod[this.nestedType] == 0) {
4002 if (this.nestedType != 0) {
4003 enumDeclaration.bits |= ASTNode.IsMemberType;
4004 }
4005 } else {
4006 // Record that the block has a declaration for local types
4007 // markEnclosingMemberWithLocalType();
4008 blockReal();
4009 }
4010 //highlight the name of the type
4011 long pos = this.identifierPositionStack[this.identifierPtr];
4012 enumDeclaration.sourceEnd = (int) pos;
4013 enumDeclaration.sourceStart = (int) (pos >>> 32);
4014 enumDeclaration.name = this.identifierStack[this.identifierPtr--];
4015 this.identifierLengthPtr--;
4016
4017 //compute the declaration source too
4018 // 'class' and 'interface' push two int positions: the beginning of the class token and its end.
4019 // we want to keep the beginning position but get rid of the end position
4020 // it is only used for the ClassLiteralAccess positions.
4021 enumDeclaration.declarationSourceStart = this.intStack[this.intPtr--];
4022 this.intPtr--; // remove the end position of the class token
4023
4024 enumDeclaration.modifiersSourceStart = this.intStack[this.intPtr--];
4025 enumDeclaration.modifiers = this.intStack[this.intPtr--] | ClassFileConstants.AccEnum;
4026 if (enumDeclaration.modifiersSourceStart >= 0) {
4027 enumDeclaration.declarationSourceStart = enumDeclaration.modifiersSourceStart;
4028 }
4029
4030 // Store secondary info
4031 if ((enumDeclaration.bits & ASTNode.IsMemberType) == 0 && (enumDeclaration.bits & ASTNode.IsLocalType) == 0) {
4032 if (this.compilationUnit != null && !CharOperation.equals(enumDeclaration.name, this.compilationUnit.getMainTypeName())) {
4033 enumDeclaration.bits |= ASTNode.IsSecondaryType;
4034 }
4035 }
4036
4037 // consume annotations
4038 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
4039 System.arraycopy(
4040 this.expressionStack,
4041 (this.expressionPtr -= length) + 1,
4042 enumDeclaration.annotations = new Annotation[length],
4043 0,
4044 length);
4045 }
4046 // if (this.currentToken == TokenNameLBRACE) {
4047 // enumDeclaration.bodyStart = this.scanner.currentPosition;
4048 // }
4049 enumDeclaration.bodyStart = enumDeclaration.sourceEnd + 1;
4050 pushOnAstStack(enumDeclaration);
4051
4052 this.listLength = 0; // will be updated when reading super-interfaces
4053
4054 if(!this.statementRecoveryActivated &&
4055 this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
4056 this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
4057 //TODO this code will be never run while 'enum' is an identifier in 1.3 scanner
4058 problemReporter().invalidUsageOfEnumDeclarations(enumDeclaration);
4059 }
4060
4061 // recovery
4062 if (this.currentElement != null){
4063 this.lastCheckPoint = enumDeclaration.bodyStart;
4064 this.currentElement = this.currentElement.add(enumDeclaration, 0);
4065 this.lastIgnoredToken = -1;
4066 }
4067 // javadoc
4068 enumDeclaration.javadoc = this.javadoc;
4069 this.javadoc = null;
4070 }
consumeEqualityExpression(int op)4071 protected void consumeEqualityExpression(int op) {
4072 // EqualityExpression ::= EqualityExpression '==' RelationalExpression
4073 // EqualityExpression ::= EqualityExpression '!=' RelationalExpression
4074
4075 //optimize the push/pop
4076
4077 this.expressionPtr--;
4078 this.expressionLengthPtr--;
4079 this.expressionStack[this.expressionPtr] =
4080 new EqualExpression(
4081 this.expressionStack[this.expressionPtr],
4082 this.expressionStack[this.expressionPtr + 1],
4083 op);
4084 }
4085 /*
4086 * @param op
4087 */
consumeEqualityExpressionWithName(int op)4088 protected void consumeEqualityExpressionWithName(int op) {
4089 // EqualityExpression ::= Name '==' RelationalExpression
4090 // EqualityExpression ::= Name '!=' RelationalExpression
4091 pushOnExpressionStack(getUnspecifiedReferenceOptimized());
4092 this.expressionPtr--;
4093 this.expressionLengthPtr--;
4094 this.expressionStack[this.expressionPtr] =
4095 new EqualExpression(
4096 this.expressionStack[this.expressionPtr + 1],
4097 this.expressionStack[this.expressionPtr],
4098 op);
4099 }
consumeExitMemberValue()4100 protected void consumeExitMemberValue() {
4101 // ExitMemberValue ::= $empty
4102 if (this.currentElement != null && this.currentElement instanceof RecoveredAnnotation) {
4103 RecoveredAnnotation recoveredAnnotation = (RecoveredAnnotation)this.currentElement;
4104 recoveredAnnotation.hasPendingMemberValueName = false;
4105 recoveredAnnotation.memberValuPairEqualEnd = -1;
4106 }
4107 }
consumeExitTryBlock()4108 protected void consumeExitTryBlock() {
4109 //ExitTryBlock ::= $empty
4110 if(this.currentElement != null) {
4111 this.restartRecovery = true;
4112 }
4113 }
consumeExitVariableWithInitialization()4114 protected void consumeExitVariableWithInitialization() {
4115 // ExitVariableWithInitialization ::= $empty
4116 // do nothing by default
4117 this.expressionLengthPtr--;
4118 AbstractVariableDeclaration variableDecl = (AbstractVariableDeclaration) this.astStack[this.astPtr];
4119 variableDecl.initialization = this.expressionStack[this.expressionPtr--];
4120 // we need to update the declarationSourceEnd of the local variable declaration to the
4121 // source end position of the initialization expression
4122 variableDecl.declarationSourceEnd = variableDecl.initialization.sourceEnd;
4123 variableDecl.declarationEnd = variableDecl.initialization.sourceEnd;
4124
4125 recoveryExitFromVariable();
4126 }
consumeExitVariableWithoutInitialization()4127 protected void consumeExitVariableWithoutInitialization() {
4128 // ExitVariableWithoutInitialization ::= $empty
4129 // do nothing by default
4130
4131 AbstractVariableDeclaration variableDecl = (AbstractVariableDeclaration) this.astStack[this.astPtr];
4132 variableDecl.declarationSourceEnd = variableDecl.declarationEnd;
4133 if(this.currentElement != null && this.currentElement instanceof RecoveredField) {
4134 if(this.endStatementPosition > variableDecl.sourceEnd) {
4135 this.currentElement.updateSourceEndIfNecessary(this.endStatementPosition);
4136 }
4137 }
4138 recoveryExitFromVariable();
4139 }
consumeExplicitConstructorInvocation(int flag, int recFlag)4140 protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
4141
4142 /* flag allows to distinguish 3 cases :
4143 (0) :
4144 ExplicitConstructorInvocation ::= 'this' '(' ArgumentListopt ')' ';'
4145 ExplicitConstructorInvocation ::= 'super' '(' ArgumentListopt ')' ';'
4146 (1) :
4147 ExplicitConstructorInvocation ::= Primary '.' 'super' '(' ArgumentListopt ')' ';'
4148 ExplicitConstructorInvocation ::= Primary '.' 'this' '(' ArgumentListopt ')' ';'
4149 (2) :
4150 ExplicitConstructorInvocation ::= Name '.' 'super' '(' ArgumentListopt ')' ';'
4151 ExplicitConstructorInvocation ::= Name '.' 'this' '(' ArgumentListopt ')' ';'
4152 */
4153 int startPosition = this.intStack[this.intPtr--];
4154 ExplicitConstructorCall ecc = new ExplicitConstructorCall(recFlag);
4155 int length;
4156 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
4157 this.expressionPtr -= length;
4158 System.arraycopy(this.expressionStack, this.expressionPtr + 1, ecc.arguments = new Expression[length], 0, length);
4159 }
4160 switch (flag) {
4161 case 0 :
4162 ecc.sourceStart = startPosition;
4163 break;
4164 case 1 :
4165 this.expressionLengthPtr--;
4166 ecc.sourceStart = (ecc.qualification = this.expressionStack[this.expressionPtr--]).sourceStart;
4167 break;
4168 case 2 :
4169 ecc.sourceStart = (ecc.qualification = getUnspecifiedReferenceOptimized()).sourceStart;
4170 break;
4171 }
4172 pushOnAstStack(ecc);
4173 ecc.sourceEnd = this.endStatementPosition;
4174 }
consumeExplicitConstructorInvocationWithTypeArguments(int flag, int recFlag)4175 protected void consumeExplicitConstructorInvocationWithTypeArguments(int flag, int recFlag) {
4176
4177 /* flag allows to distinguish 3 cases :
4178 (0) :
4179 ExplicitConstructorInvocation ::= TypeArguments 'this' '(' ArgumentListopt ')' ';'
4180 ExplicitConstructorInvocation ::= TypeArguments 'super' '(' ArgumentListopt ')' ';'
4181 (1) :
4182 ExplicitConstructorInvocation ::= Primary '.' TypeArguments 'super' '(' ArgumentListopt ')' ';'
4183 ExplicitConstructorInvocation ::= Primary '.' TypeArguments 'this' '(' ArgumentListopt ')' ';'
4184 (2) :
4185 ExplicitConstructorInvocation ::= Name '.' TypeArguments 'super' '(' ArgumentListopt ')' ';'
4186 ExplicitConstructorInvocation ::= Name '.' TypeArguments 'this' '(' ArgumentListopt ')' ';'
4187 */
4188 int startPosition = this.intStack[this.intPtr--];
4189 ExplicitConstructorCall ecc = new ExplicitConstructorCall(recFlag);
4190 int length;
4191 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
4192 this.expressionPtr -= length;
4193 System.arraycopy(this.expressionStack, this.expressionPtr + 1, ecc.arguments = new Expression[length], 0, length);
4194 }
4195 length = this.genericsLengthStack[this.genericsLengthPtr--];
4196 this.genericsPtr -= length;
4197 System.arraycopy(this.genericsStack, this.genericsPtr + 1, ecc.typeArguments = new TypeReference[length], 0, length);
4198 ecc.typeArgumentsSourceStart = this.intStack[this.intPtr--];
4199
4200 switch (flag) {
4201 case 0 :
4202 ecc.sourceStart = startPosition;
4203 break;
4204 case 1 :
4205 this.expressionLengthPtr--;
4206 ecc.sourceStart = (ecc.qualification = this.expressionStack[this.expressionPtr--]).sourceStart;
4207 break;
4208 case 2 :
4209 ecc.sourceStart = (ecc.qualification = getUnspecifiedReferenceOptimized()).sourceStart;
4210 break;
4211 }
4212
4213 pushOnAstStack(ecc);
4214 ecc.sourceEnd = this.endStatementPosition;
4215 }
consumeExpressionStatement()4216 protected void consumeExpressionStatement() {
4217 // ExpressionStatement ::= StatementExpression ';'
4218 this.expressionLengthPtr--;
4219 Expression expression = this.expressionStack[this.expressionPtr--];
4220 expression.statementEnd = this.endStatementPosition;
4221 expression.bits |= ASTNode.InsideExpressionStatement;
4222 pushOnAstStack(expression);
4223 }
consumeFieldAccess(boolean isSuperAccess)4224 protected void consumeFieldAccess(boolean isSuperAccess) {
4225 // FieldAccess ::= Primary '.' 'Identifier'
4226 // FieldAccess ::= 'super' '.' 'Identifier'
4227
4228 FieldReference fr =
4229 new FieldReference(
4230 this.identifierStack[this.identifierPtr],
4231 this.identifierPositionStack[this.identifierPtr--]);
4232 this.identifierLengthPtr--;
4233 if (isSuperAccess) {
4234 //considers the fieldReference beginning at the 'super' ....
4235 fr.sourceStart = this.intStack[this.intPtr--];
4236 fr.receiver = new SuperReference(fr.sourceStart, this.endPosition);
4237 pushOnExpressionStack(fr);
4238 } else {
4239 //optimize push/pop
4240 fr.receiver = this.expressionStack[this.expressionPtr];
4241 //field reference begins at the receiver
4242 fr.sourceStart = fr.receiver.sourceStart;
4243 this.expressionStack[this.expressionPtr] = fr;
4244 }
4245 }
consumeFieldDeclaration()4246 protected void consumeFieldDeclaration() {
4247 // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
4248 // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
4249
4250 /*
4251 this.astStack :
4252 this.expressionStack: Expression Expression ...... Expression
4253 this.identifierStack : type identifier identifier ...... identifier
4254 this.intStack : typeDim dim dim dim
4255 ==>
4256 this.astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration
4257 this.expressionStack :
4258 this.identifierStack :
4259 this.intStack :
4260
4261 */
4262 int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr];
4263
4264 for (int i = variableDeclaratorsCounter - 1; i >= 0; i--) {
4265 FieldDeclaration fieldDeclaration = (FieldDeclaration) this.astStack[this.astPtr - i];
4266 fieldDeclaration.declarationSourceEnd = this.endStatementPosition;
4267 fieldDeclaration.declarationEnd = this.endStatementPosition; // semi-colon included
4268 }
4269
4270 updateSourceDeclarationParts(variableDeclaratorsCounter);
4271 int endPos = flushCommentsDefinedPriorTo(this.endStatementPosition);
4272 if (endPos != this.endStatementPosition) {
4273 for (int i = 0; i < variableDeclaratorsCounter; i++) {
4274 FieldDeclaration fieldDeclaration = (FieldDeclaration) this.astStack[this.astPtr - i];
4275 fieldDeclaration.declarationSourceEnd = endPos;
4276 }
4277 }
4278 // update the this.astStack, this.astPtr and this.astLengthStack
4279 int startIndex = this.astPtr - this.variablesCounter[this.nestedType] + 1;
4280 System.arraycopy(
4281 this.astStack,
4282 startIndex,
4283 this.astStack,
4284 startIndex - 1,
4285 variableDeclaratorsCounter);
4286 this.astPtr--; // remove the type reference
4287 this.astLengthStack[--this.astLengthPtr] = variableDeclaratorsCounter;
4288
4289 // recovery
4290 if (this.currentElement != null) {
4291 this.lastCheckPoint = endPos + 1;
4292 if (this.currentElement.parent != null && this.currentElement instanceof RecoveredField){
4293 if (!(this.currentElement instanceof RecoveredInitializer)) {
4294 this.currentElement = this.currentElement.parent;
4295 }
4296 }
4297 this.restartRecovery = true;
4298 }
4299 this.variablesCounter[this.nestedType] = 0;
4300 }
consumeForceNoDiet()4301 protected void consumeForceNoDiet() {
4302 // ForceNoDiet ::= $empty
4303 this.dietInt++;
4304 }
consumeForInit()4305 protected void consumeForInit() {
4306 // ForInit ::= StatementExpressionList
4307 pushOnAstLengthStack(-1);
4308 this.forStartPosition = 0;
4309 }
consumeFormalParameter(boolean isVarArgs)4310 protected void consumeFormalParameter(boolean isVarArgs) {
4311 // FormalParameter ::= Modifiersopt Type VariableDeclaratorIdOrThis
4312 // FormalParameter ::= Modifiersopt Type PushZeroTypeAnnotations '...' VariableDeclaratorIdOrThis
4313 // FormalParameter ::= Modifiersopt Type @308... TypeAnnotations '...' VariableDeclaratorIdOrThis
4314 /*
4315 this.astStack :
4316 this.identifierStack : type identifier
4317 this.intStack : dim dim 1||0 // 1 => normal parameter, 0 => this parameter
4318 ==>
4319 this.astStack : Argument
4320 this.identifierStack :
4321 this.intStack :
4322 */
4323 NameReference qualifyingNameReference = null;
4324 boolean isReceiver = this.intStack[this.intPtr--] == 0; // flag pushed in consumeExplicitThisParameter -> 0, consumeVariableDeclaratorIdParameter -> 1
4325 if (isReceiver) {
4326 qualifyingNameReference = (NameReference) this.expressionStack[this.expressionPtr--];
4327 this.expressionLengthPtr --;
4328 }
4329 this.identifierLengthPtr--;
4330 char[] identifierName = this.identifierStack[this.identifierPtr];
4331 long namePositions = this.identifierPositionStack[this.identifierPtr--];
4332 int extendedDimensions = this.intStack[this.intPtr--];
4333 Annotation [][] annotationsOnExtendedDimensions = extendedDimensions == 0 ? null : getAnnotationsOnDimensions(extendedDimensions);
4334 Annotation [] varArgsAnnotations = null;
4335 int endOfEllipsis = 0;
4336 int length;
4337 if (isVarArgs) {
4338 endOfEllipsis = this.intStack[this.intPtr--];
4339 if ((length = this.typeAnnotationLengthStack[this.typeAnnotationLengthPtr--]) != 0) {
4340 System.arraycopy(
4341 this.typeAnnotationStack,
4342 (this.typeAnnotationPtr -= length) + 1,
4343 varArgsAnnotations = new Annotation[length],
4344 0,
4345 length);
4346 }
4347 }
4348 int firstDimensions = this.intStack[this.intPtr--];
4349 TypeReference type = getTypeReference(firstDimensions);
4350 if (isVarArgs || extendedDimensions != 0) {
4351 if (isVarArgs) {
4352 type = augmentTypeWithAdditionalDimensions(type, 1, varArgsAnnotations != null ? new Annotation[][] { varArgsAnnotations } : null, true);
4353 }
4354 if (extendedDimensions != 0) {
4355 type = augmentTypeWithAdditionalDimensions(type, extendedDimensions, annotationsOnExtendedDimensions, false);
4356 }
4357 type.sourceEnd = type.isParameterizedTypeReference() ? this.endStatementPosition : this.endPosition;
4358 }
4359 if (isVarArgs) {
4360 if (extendedDimensions == 0) {
4361 type.sourceEnd = endOfEllipsis;
4362 }
4363 type.bits |= ASTNode.IsVarArgs; // set isVarArgs
4364 }
4365 int modifierPositions = this.intStack[this.intPtr--];
4366 Argument arg;
4367 if (isReceiver) {
4368 arg = new Receiver(
4369 identifierName,
4370 namePositions,
4371 type,
4372 qualifyingNameReference,
4373 this.intStack[this.intPtr--] & ~ClassFileConstants.AccDeprecated);
4374 } else {
4375 arg = new Argument(
4376 identifierName,
4377 namePositions,
4378 type,
4379 this.intStack[this.intPtr--] & ~ClassFileConstants.AccDeprecated); // modifiers
4380 }
4381 arg.declarationSourceStart = modifierPositions;
4382 arg.bits |= (type.bits & ASTNode.HasTypeAnnotations);
4383 // consume annotations
4384 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
4385 System.arraycopy(
4386 this.expressionStack,
4387 (this.expressionPtr -= length) + 1,
4388 arg.annotations = new Annotation[length],
4389 0,
4390 length);
4391 arg.bits |= ASTNode.HasTypeAnnotations;
4392 RecoveredType currentRecoveryType = this.currentRecoveryType();
4393 if (currentRecoveryType != null)
4394 currentRecoveryType.annotationsConsumed(arg.annotations);
4395 }
4396 pushOnAstStack(arg);
4397
4398 /* if incomplete method header, this.listLength counter will not have been reset,
4399 indicating that some arguments are available on the stack */
4400 this.listLength++;
4401
4402 if(isVarArgs) {
4403 if (!this.statementRecoveryActivated &&
4404 this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
4405 this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
4406 problemReporter().invalidUsageOfVarargs(arg);
4407 } else if (!this.statementRecoveryActivated &&
4408 extendedDimensions > 0) {
4409 problemReporter().illegalExtendedDimensions(arg);
4410 }
4411 }
4412 }
getAnnotationsOnDimensions(int dimensionsCount)4413 protected Annotation[][] getAnnotationsOnDimensions(int dimensionsCount) {
4414 Annotation [][] dimensionsAnnotations = null;
4415 if (dimensionsCount > 0) {
4416 for (int i = 0; i < dimensionsCount; i++) {
4417 Annotation [] annotations = null;
4418 int length;
4419 if ((length = this.typeAnnotationLengthStack[this.typeAnnotationLengthPtr--]) != 0) {
4420 System.arraycopy(
4421 this.typeAnnotationStack,
4422 (this.typeAnnotationPtr -= length) + 1,
4423 annotations = new Annotation[length],
4424 0,
4425 length);
4426 if (dimensionsAnnotations == null) {
4427 dimensionsAnnotations = new Annotation[dimensionsCount][];
4428 }
4429 dimensionsAnnotations[dimensionsCount - i - 1] = annotations;
4430 }
4431 }
4432 }
4433 return dimensionsAnnotations;
4434 }
consumeFormalParameterList()4435 protected void consumeFormalParameterList() {
4436 // FormalParameterList ::= FormalParameterList ',' FormalParameter
4437 // TypeElidedFormalParameterList ::= TypeElidedFormalParameterList ',' TypeElidedFormalParameter
4438 optimizedConcatNodeLists();
4439 }
consumeFormalParameterListopt()4440 protected void consumeFormalParameterListopt() {
4441 // FormalParameterListopt ::= $empty
4442 pushOnAstLengthStack(0);
4443 }
consumeGenericType()4444 protected void consumeGenericType() {
4445 // GenericType ::= ClassOrInterface TypeArguments
4446 // nothing to do
4447 // Will be consume by a getTypeReference call
4448 }
consumeGenericTypeArrayType()4449 protected void consumeGenericTypeArrayType() {
4450 // nothing to do
4451 // Will be consume by a getTypeReference call
4452 }
consumeGenericTypeNameArrayType()4453 protected void consumeGenericTypeNameArrayType() {
4454 // nothing to do
4455 // Will be consume by a getTypeReference call
4456 }
consumeGenericTypeWithDiamond()4457 protected void consumeGenericTypeWithDiamond() {
4458 // GenericType ::= ClassOrInterface '<' '>'
4459 // zero type arguments == <>
4460 pushOnGenericsLengthStack(-1);
4461 concatGenericsLists();
4462 this.intPtr--; // pop the null dimension pushed in by consumeReferenceType, as we have no type between <>, getTypeReference won't kick in
4463 }
consumeImportDeclaration()4464 protected void consumeImportDeclaration() {
4465 // SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName ';'
4466 ImportReference impt = (ImportReference) this.astStack[this.astPtr];
4467 // flush annotations defined prior to import statements
4468 impt.declarationEnd = this.endStatementPosition;
4469 impt.declarationSourceEnd =
4470 flushCommentsDefinedPriorTo(impt.declarationSourceEnd);
4471
4472 // recovery
4473 if (this.currentElement != null) {
4474 this.lastCheckPoint = impt.declarationSourceEnd + 1;
4475 this.currentElement = this.currentElement.add(impt, 0);
4476 this.lastIgnoredToken = -1;
4477 this.restartRecovery = true;
4478 // used to avoid branching back into the regular automaton
4479 }
4480 }
consumeImportDeclarations()4481 protected void consumeImportDeclarations() {
4482 // ImportDeclarations ::= ImportDeclarations ImportDeclaration
4483 optimizedConcatNodeLists();
4484 }
consumeInsideCastExpression()4485 protected void consumeInsideCastExpression() {
4486 // InsideCastExpression ::= $empty
4487 }
consumeInsideCastExpressionLL1()4488 protected void consumeInsideCastExpressionLL1() {
4489 // InsideCastExpressionLL1 ::= $empty
4490 pushOnGenericsLengthStack(0); // handle type arguments
4491 pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
4492 pushOnExpressionStack(getTypeReference(0));
4493 }
consumeInsideCastExpressionLL1WithBounds()4494 protected void consumeInsideCastExpressionLL1WithBounds() {
4495 // InsideCastExpressionLL1WithBounds ::= $empty
4496 int additionalBoundsLength = this.genericsLengthStack[this.genericsLengthPtr--];
4497 TypeReference[] bounds = new TypeReference[additionalBoundsLength + 1];
4498 this.genericsPtr -= additionalBoundsLength;
4499 System.arraycopy(this.genericsStack, this.genericsPtr + 1, bounds, 1, additionalBoundsLength);
4500
4501 pushOnGenericsLengthStack(0); // handle type arguments
4502 pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
4503 bounds[0] = getTypeReference(0);
4504
4505 for (int i = 0; i <= additionalBoundsLength; i++) {
4506 pushOnExpressionStack(bounds[i]);
4507 if (i > 0)
4508 this.expressionLengthStack[--this.expressionLengthPtr]++;
4509 }
4510 }
consumeInsideCastExpressionWithQualifiedGenerics()4511 protected void consumeInsideCastExpressionWithQualifiedGenerics() {
4512 // InsideCastExpressionWithQualifiedGenerics ::= $empty
4513 }
consumeTypeTestPattern()4514 private void consumeTypeTestPattern() {
4515 TypeReference type;
4516 char[] identifierName = this.identifierStack[this.identifierPtr];
4517 long namePosition = this.identifierPositionStack[this.identifierPtr];
4518
4519 LocalDeclaration local = createLocalDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition);
4520 local.declarationSourceEnd = local.declarationEnd;
4521
4522 this.identifierPtr--;
4523 this.identifierLengthPtr--;
4524
4525 type = getTypeReference(this.intStack[this.intPtr--]); //getTypeReference(0); // no type dimension
4526 local.declarationSourceStart = type.sourceStart;
4527 local.type = type;
4528 if (!this.parsingJava14Plus) {
4529 problemReporter().previewFeatureNotSupported(type.sourceStart, local.declarationEnd, "Instanceof Pattern", CompilerOptions.VERSION_13); //$NON-NLS-1$
4530 } else if (!this.options.enablePreviewFeatures){
4531 problemReporter().previewFeatureNotEnabled(type.sourceStart, local.declarationEnd, "Instanceof Pattern"); //$NON-NLS-1$
4532 } else {
4533 if (this.options.isAnyEnabled(IrritantSet.PREVIEW)) {
4534 problemReporter().previewFeatureUsed(type.sourceStart, local.declarationEnd);
4535 }
4536 }
4537 local.modifiers |= ClassFileConstants.AccFinal;
4538 pushOnPatternStack(local);
4539 }
consumeInstanceOfExpression()4540 protected void consumeInstanceOfExpression() {
4541 // RelationalExpression ::= RelationalExpression 'instanceof' ReferenceType
4542 //optimize the push/pop
4543
4544 //by construction, no base type may be used in getTypeReference
4545 int length = this.patternLengthPtr >= 0 ?
4546 this.patternLengthStack[this.patternLengthPtr--] : 0;
4547 Expression exp;
4548 if (length > 0) {
4549 LocalDeclaration typeDecl = (LocalDeclaration) this.patternStack[this.patternPtr--];
4550 this.expressionStack[this.expressionPtr] = exp =
4551 new InstanceOfExpression(
4552 this.expressionStack[this.expressionPtr],
4553 typeDecl);
4554 } else {
4555 this.expressionStack[this.expressionPtr] = exp =
4556 new InstanceOfExpression(
4557 this.expressionStack[this.expressionPtr],
4558 getTypeReference(this.intStack[this.intPtr--]));
4559 }
4560
4561 if (exp.sourceEnd == 0) {
4562 //array on base type....
4563 exp.sourceEnd = this.scanner.startPosition - 1;
4564 }
4565 //the scanner is on the next token already....
4566 }
consumeInstanceOfExpressionWithName()4567 protected void consumeInstanceOfExpressionWithName() {
4568 // RelationalExpression_NotName ::= Name instanceof ReferenceType
4569 //optimize the push/pop
4570
4571 int length = this.patternLengthPtr >= 0 ?
4572 this.patternLengthStack[this.patternLengthPtr--] : 0;
4573 Expression exp;
4574 if (length != 0) {
4575 LocalDeclaration typeDecl = (LocalDeclaration) this.patternStack[this.patternPtr--];
4576 pushOnExpressionStack(getUnspecifiedReferenceOptimized());
4577 this.expressionStack[this.expressionPtr] = exp =
4578 new InstanceOfExpression(
4579 this.expressionStack[this.expressionPtr],
4580 typeDecl);
4581 } else {
4582 //by construction, no base type may be used in getTypeReference
4583 TypeReference reference = getTypeReference(this.intStack[this.intPtr--]);
4584 pushOnExpressionStack(getUnspecifiedReferenceOptimized());
4585 this.expressionStack[this.expressionPtr] = exp =
4586 new InstanceOfExpression(
4587 this.expressionStack[this.expressionPtr],
4588 reference);
4589 }
4590 if (exp.sourceEnd == 0) {
4591 //array on base type....
4592 exp.sourceEnd = this.scanner.startPosition - 1;
4593 }
4594 //the scanner is on the next token already....
4595 }
consumeInterfaceDeclaration()4596 protected void consumeInterfaceDeclaration() {
4597 // see consumeClassDeclaration in case of changes: duplicated code
4598 // InterfaceDeclaration ::= InterfaceHeader InterfaceBody
4599 int length;
4600 if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
4601 //there are length declarations
4602 //dispatch.....according to the type of the declarations
4603 dispatchDeclarationInto(length);
4604 }
4605
4606 TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
4607
4608 //convert constructor that do not have the type's name into methods
4609 typeDecl.checkConstructors(this);
4610
4611 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=212713,
4612 // reject initializers that have been tolerated by the grammar.
4613 FieldDeclaration [] fields = typeDecl.fields;
4614 int fieldCount = fields == null ? 0 : fields.length;
4615 for (int i = 0; i < fieldCount; i++) {
4616 FieldDeclaration field = fields[i];
4617 if (field instanceof Initializer) {
4618 problemReporter().interfaceCannotHaveInitializers(typeDecl.name, field);
4619 }
4620 }
4621
4622 //always add <clinit> (will be remove at code gen time if empty)
4623 if (this.scanner.containsAssertKeyword) {
4624 typeDecl.bits |= ASTNode.ContainsAssertion;
4625 }
4626 typeDecl.addClinit();
4627 typeDecl.bodyEnd = this.endStatementPosition;
4628 if (length == 0 && !containsComment(typeDecl.bodyStart, typeDecl.bodyEnd)) {
4629 typeDecl.bits |= ASTNode.UndocumentedEmptyBlock;
4630 }
4631 typeDecl.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
4632 }
consumeInterfaceHeader()4633 protected void consumeInterfaceHeader() {
4634 // InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt
4635
4636 TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
4637 if (this.currentToken == TokenNameLBRACE){
4638 typeDecl.bodyStart = this.scanner.currentPosition;
4639 }
4640 if (this.currentElement != null){
4641 this.restartRecovery = true; // used to avoid branching back into the regular automaton
4642 }
4643 // flush the comments related to the interface header
4644 this.scanner.commentPtr = -1;
4645 }
consumeInterfaceHeaderExtends()4646 protected void consumeInterfaceHeaderExtends() {
4647 // InterfaceHeaderExtends ::= 'extends' InterfaceTypeList
4648 int length = this.astLengthStack[this.astLengthPtr--];
4649 //super interfaces
4650 this.astPtr -= length;
4651 TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
4652 System.arraycopy(
4653 this.astStack,
4654 this.astPtr + 1,
4655 typeDecl.superInterfaces = new TypeReference[length],
4656 0,
4657 length);
4658 TypeReference[] superinterfaces = typeDecl.superInterfaces;
4659 for (int i = 0, max = superinterfaces.length; i < max; i++) {
4660 TypeReference typeReference = superinterfaces[i];
4661 typeDecl.bits |= (typeReference.bits & ASTNode.HasTypeAnnotations);
4662 typeReference.bits |= ASTNode.IsSuperType;
4663 }
4664 typeDecl.bodyStart = typeDecl.superInterfaces[length-1].sourceEnd + 1;
4665 this.listLength = 0; // reset after having read super-interfaces
4666 // recovery
4667 if (this.currentElement != null) {
4668 this.lastCheckPoint = typeDecl.bodyStart;
4669 }
4670 }
consumeInterfaceHeaderName1()4671 protected void consumeInterfaceHeaderName1() {
4672 // InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
4673 TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
4674
4675 if (this.nestedMethod[this.nestedType] == 0) {
4676 if (this.nestedType != 0) {
4677 typeDecl.bits |= ASTNode.IsMemberType;
4678 }
4679 } else {
4680 // Record that the block has a declaration for local types
4681 typeDecl.bits |= ASTNode.IsLocalType;
4682 markEnclosingMemberWithLocalType();
4683 blockReal();
4684 }
4685
4686 //highlight the name of the type
4687 long pos = this.identifierPositionStack[this.identifierPtr];
4688 typeDecl.sourceEnd = (int) pos;
4689 typeDecl.sourceStart = (int) (pos >>> 32);
4690 typeDecl.name = this.identifierStack[this.identifierPtr--];
4691 this.identifierLengthPtr--;
4692
4693 //compute the declaration source too
4694 // 'class' and 'interface' push two int positions: the beginning of the class token and its end.
4695 // we want to keep the beginning position but get rid of the end position
4696 // it is only used for the ClassLiteralAccess positions.
4697 typeDecl.declarationSourceStart = this.intStack[this.intPtr--];
4698 this.intPtr--; // remove the end position of the class token
4699 typeDecl.modifiersSourceStart = this.intStack[this.intPtr--];
4700 typeDecl.modifiers = this.intStack[this.intPtr--] | ClassFileConstants.AccInterface;
4701 if (typeDecl.modifiersSourceStart >= 0) {
4702 typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
4703 }
4704
4705 // Store secondary info
4706 if ((typeDecl.bits & ASTNode.IsMemberType) == 0 && (typeDecl.bits & ASTNode.IsLocalType) == 0) {
4707 if (this.compilationUnit != null && !CharOperation.equals(typeDecl.name, this.compilationUnit.getMainTypeName())) {
4708 typeDecl.bits |= ASTNode.IsSecondaryType;
4709 }
4710 }
4711
4712 // consume annotations
4713 int length;
4714 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
4715 System.arraycopy(
4716 this.expressionStack,
4717 (this.expressionPtr -= length) + 1,
4718 typeDecl.annotations = new Annotation[length],
4719 0,
4720 length);
4721 }
4722 typeDecl.bodyStart = typeDecl.sourceEnd + 1;
4723 pushOnAstStack(typeDecl);
4724 this.listLength = 0; // will be updated when reading super-interfaces
4725 // recovery
4726 if (this.currentElement != null){ // is recovering
4727 this.lastCheckPoint = typeDecl.bodyStart;
4728 this.currentElement = this.currentElement.add(typeDecl, 0);
4729 this.lastIgnoredToken = -1;
4730 }
4731 // javadoc
4732 typeDecl.javadoc = this.javadoc;
4733 this.javadoc = null;
4734 }
consumeInterfaceMemberDeclarations()4735 protected void consumeInterfaceMemberDeclarations() {
4736 // InterfaceMemberDeclarations ::= InterfaceMemberDeclarations InterfaceMemberDeclaration
4737 concatNodeLists();
4738 }
consumeInterfaceMemberDeclarationsopt()4739 protected void consumeInterfaceMemberDeclarationsopt() {
4740 // InterfaceMemberDeclarationsopt ::= NestedType InterfaceMemberDeclarations
4741 this.nestedType--;
4742 }
consumeInterfaceType()4743 protected void consumeInterfaceType() {
4744 // InterfaceType ::= ClassOrInterfaceType
4745 pushOnAstStack(getTypeReference(0));
4746 /* if incomplete type header, this.listLength counter will not have been reset,
4747 indicating that some interfaces are available on the stack */
4748 this.listLength++;
4749 }
consumeInterfaceTypeList()4750 protected void consumeInterfaceTypeList() {
4751 // InterfaceTypeList ::= InterfaceTypeList ',' InterfaceType
4752 optimizedConcatNodeLists();
4753 }
consumeInternalCompilationUnit()4754 protected void consumeInternalCompilationUnit() {
4755 // InternalCompilationUnit ::= PackageDeclaration
4756 // InternalCompilationUnit ::= PackageDeclaration ImportDeclarations ReduceImports
4757 // InternalCompilationUnit ::= ImportDeclarations ReduceImports
4758 if (this.compilationUnit.isPackageInfo()) {
4759 this.compilationUnit.types = new TypeDeclaration[1];
4760 this.compilationUnit.createPackageInfoType();
4761 }
4762 }
consumeInternalCompilationUnitWithTypes()4763 protected void consumeInternalCompilationUnitWithTypes() {
4764 // InternalCompilationUnit ::= PackageDeclaration ImportDeclarations ReduceImports TypeDeclarations
4765 // InternalCompilationUnit ::= PackageDeclaration TypeDeclarations
4766 // InternalCompilationUnit ::= TypeDeclarations
4767 // InternalCompilationUnit ::= ImportDeclarations ReduceImports TypeDeclarations
4768 // consume type declarations
4769 int length;
4770 if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
4771 if (this.compilationUnit.isPackageInfo()) {
4772 this.compilationUnit.types = new TypeDeclaration[length + 1];
4773 this.astPtr -= length;
4774 System.arraycopy(this.astStack, this.astPtr + 1, this.compilationUnit.types, 1, length);
4775 this.compilationUnit.createPackageInfoType();
4776 } else {
4777 this.compilationUnit.types = new TypeDeclaration[length];
4778 this.astPtr -= length;
4779 System.arraycopy(this.astStack, this.astPtr + 1, this.compilationUnit.types, 0, length);
4780 }
4781 }
4782 }
consumeInvalidAnnotationTypeDeclaration()4783 protected void consumeInvalidAnnotationTypeDeclaration() {
4784 // BlockStatement ::= AnnotationTypeDeclaration
4785 TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
4786 if(!this.statementRecoveryActivated) problemReporter().illegalLocalTypeDeclaration(typeDecl);
4787 // remove the ast node created in interface header
4788 this.astPtr--;
4789 pushOnAstLengthStack(-1);
4790 concatNodeLists();
4791 }
consumeInvalidConstructorDeclaration()4792 protected void consumeInvalidConstructorDeclaration() {
4793 // ConstructorDeclaration ::= ConstructorHeader ';'
4794 // now we know that the top of stack is a constructorDeclaration
4795 ConstructorDeclaration cd = (ConstructorDeclaration) this.astStack[this.astPtr];
4796
4797 cd.bodyEnd = this.endPosition; // position just before the trailing semi-colon
4798 cd.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
4799 // report the problem and continue the parsing - narrowing the problem onto the method
4800
4801 cd.modifiers |= ExtraCompilerModifiers.AccSemicolonBody; // remember semi-colon body
4802 }
consumeInvalidConstructorDeclaration(boolean hasBody)4803 protected void consumeInvalidConstructorDeclaration(boolean hasBody) {
4804 // InvalidConstructorDeclaration ::= ConstructorHeader ConstructorBody ==> true
4805 // InvalidConstructorDeclaration ::= ConstructorHeader ';' ==> false
4806
4807 /*
4808 this.astStack : modifiers arguments throws statements
4809 this.identifierStack : name
4810 ==>
4811 this.astStack : MethodDeclaration
4812 this.identifierStack :
4813 */
4814 if (hasBody) {
4815 // pop the position of the { (body of the method) pushed in block decl
4816 this.intPtr--;
4817 }
4818
4819 //statements
4820 if (hasBody) {
4821 this.realBlockPtr--;
4822 }
4823
4824 int length;
4825 if (hasBody && ((length = this.astLengthStack[this.astLengthPtr--]) != 0)) {
4826 this.astPtr -= length;
4827 }
4828 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) this.astStack[this.astPtr];
4829 constructorDeclaration.bodyEnd = this.endStatementPosition;
4830 constructorDeclaration.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
4831 if (!hasBody) {
4832 constructorDeclaration.modifiers |= ExtraCompilerModifiers.AccSemicolonBody;
4833 }
4834 }
consumeInvalidEnumDeclaration()4835 protected void consumeInvalidEnumDeclaration() {
4836 // BlockStatement ::= EnumDeclaration
4837 TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
4838 if(!this.statementRecoveryActivated) problemReporter().illegalLocalTypeDeclaration(typeDecl);
4839 // remove the ast node created in interface header
4840 this.astPtr--;
4841 pushOnAstLengthStack(-1);
4842 concatNodeLists();
4843 }
consumeInvalidInterfaceDeclaration()4844 protected void consumeInvalidInterfaceDeclaration() {
4845 // BlockStatement ::= InvalidInterfaceDeclaration
4846 //InterfaceDeclaration ::= Modifiersopt 'interface' 'Identifier' ExtendsInterfacesopt InterfaceHeader InterfaceBody
4847 TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
4848 if(!this.statementRecoveryActivated) problemReporter().illegalLocalTypeDeclaration(typeDecl);
4849 // remove the ast node created in interface header
4850 this.astPtr--;
4851 pushOnAstLengthStack(-1);
4852 concatNodeLists();
4853 }
consumeInterfaceMethodDeclaration(boolean hasSemicolonBody)4854 protected void consumeInterfaceMethodDeclaration(boolean hasSemicolonBody) {
4855 // InterfaceMemberDeclaration ::= DefaultMethodHeader MethodBody
4856 // InterfaceMemberDeclaration ::= MethodHeader MethodBody
4857 // -- the next rule is illegal but allows to give a more canonical error message from inside consumeInterfaceMethodDeclaration():
4858 // InterfaceMemberDeclaration ::= DefaultMethodHeader ';'
4859
4860
4861 /*
4862 this.astStack : modifiers arguments throws statements
4863 this.identifierStack : type name
4864 this.intStack : dim dim dim
4865 ==>
4866 this.astStack : MethodDeclaration
4867 this.identifierStack :
4868 this.intStack :
4869 */
4870
4871 int explicitDeclarations = 0;
4872 Statement[] statements = null;
4873 if (!hasSemicolonBody) {
4874 // pop the position of the { (body of the method) pushed in block decl
4875 this.intPtr--;
4876 this.intPtr--;
4877
4878 explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
4879
4880 //statements
4881 int length;
4882 if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
4883 if (this.options.ignoreMethodBodies) {
4884 this.astPtr -= length;
4885 } else {
4886 System.arraycopy(
4887 this.astStack,
4888 (this.astPtr -= length) + 1,
4889 statements = new Statement[length],
4890 0,
4891 length);
4892 }
4893 }
4894 }
4895
4896 //watch for } that could be given as a unicode ! ( u007D is '}' )
4897 MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr];
4898 md.statements = statements;
4899 md.explicitDeclarations = explicitDeclarations;
4900 md.bodyEnd = this.endPosition;
4901 md.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
4902
4903 boolean isDefault = (md.modifiers & ExtraCompilerModifiers.AccDefaultMethod) != 0;
4904 boolean isStatic = (md.modifiers & ClassFileConstants.AccStatic) != 0;
4905 boolean isPrivate = (md.modifiers & ClassFileConstants.AccPrivate) != 0;
4906 boolean bodyAllowed = (this.parsingJava9Plus && isPrivate) || isDefault || isStatic;
4907 if (this.parsingJava8Plus) {
4908 if (bodyAllowed && hasSemicolonBody) {
4909 md.modifiers |= ExtraCompilerModifiers.AccSemicolonBody; // avoid complaints regarding undocumented empty body
4910 }
4911 } else {
4912 if (isDefault) problemReporter().defaultMethodsNotBelow18(md);
4913 if (isStatic) problemReporter().staticInterfaceMethodsNotBelow18(md);
4914 }
4915 if (!bodyAllowed && !this.statementRecoveryActivated && !hasSemicolonBody) {
4916 problemReporter().abstractMethodNeedingNoBody(md);
4917 }
4918 }
consumeLabel()4919 protected void consumeLabel() {
4920 // Do nothing
4921 }
consumeLeftParen()4922 protected void consumeLeftParen() {
4923 // PushLPAREN ::= '('
4924 pushOnIntStack(this.lParenPos);
4925 }
consumeLocalVariableDeclaration()4926 protected void consumeLocalVariableDeclaration() {
4927 // LocalVariableDeclaration ::= Modifiers Type VariableDeclarators ';'
4928
4929 /*
4930 this.astStack :
4931 this.expressionStack: Expression Expression ...... Expression
4932 this.identifierStack : type identifier identifier ...... identifier
4933 this.intStack : typeDim dim dim dim
4934 ==>
4935 this.astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration
4936 this.expressionStack :
4937 this.identifierStack :
4938 this.intStack :
4939
4940 */
4941 int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr];
4942
4943 // update the this.astStack, this.astPtr and this.astLengthStack
4944 int startIndex = this.astPtr - this.variablesCounter[this.nestedType] + 1;
4945 System.arraycopy(
4946 this.astStack,
4947 startIndex,
4948 this.astStack,
4949 startIndex - 1,
4950 variableDeclaratorsCounter);
4951 this.astPtr--; // remove the type reference
4952 this.astLengthStack[--this.astLengthPtr] = variableDeclaratorsCounter;
4953 this.variablesCounter[this.nestedType] = 0;
4954 this.forStartPosition = 0;
4955 }
consumeLocalVariableDeclarationStatement()4956 protected void consumeLocalVariableDeclarationStatement() {
4957
4958 int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr];
4959 if (variableDeclaratorsCounter == 1) {
4960 LocalDeclaration localDeclaration = (LocalDeclaration) this.astStack[this.astPtr];
4961 if (localDeclaration.isRecoveredFromLoneIdentifier()) {
4962 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=430336, [1.8][compiler] Bad syntax error recovery: Lonely identifier should be variable name, not type
4963 // Mutate foo $missing; into foo = $missing$;
4964 Expression left;
4965 if (localDeclaration.type instanceof QualifiedTypeReference) {
4966 QualifiedTypeReference qtr = (QualifiedTypeReference) localDeclaration.type;
4967 left = new QualifiedNameReference(qtr.tokens, qtr.sourcePositions, 0, 0);
4968 } else {
4969 left = new SingleNameReference(localDeclaration.type.getLastToken(), 0L);
4970 }
4971 left.sourceStart = localDeclaration.type.sourceStart;
4972 left.sourceEnd = localDeclaration.type.sourceEnd;
4973
4974 Expression right = new SingleNameReference(localDeclaration.name, 0L);
4975 right.sourceStart = localDeclaration.sourceStart;
4976 right.sourceEnd = localDeclaration.sourceEnd;
4977
4978 Assignment assignment = new Assignment(left, right, 0);
4979 int end = this.endStatementPosition;
4980 assignment.sourceEnd = (end == localDeclaration.sourceEnd) ? ++end : end;
4981 assignment.statementEnd = end;
4982 this.astStack[this.astPtr] = assignment;
4983
4984 // also massage recovery scanner data.
4985 if (this.recoveryScanner != null) {
4986 RecoveryScannerData data = this.recoveryScanner.getData();
4987 int position = data.insertedTokensPtr;
4988 while (position > 0) {
4989 if (data.insertedTokensPosition[position] != data.insertedTokensPosition[position - 1])
4990 break;
4991 position--;
4992 }
4993 if (position >= 0)
4994 this.recoveryScanner.insertTokenAhead(TerminalTokens.TokenNameEQUAL, position);
4995 }
4996
4997 if (this.currentElement != null) {
4998 this.lastCheckPoint = assignment.sourceEnd + 1;
4999 this.currentElement = this.currentElement.add(assignment, 0);
5000 }
5001 return;
5002 }
5003 }
5004 // LocalVariableDeclarationStatement ::= LocalVariableDeclaration ';'
5005 // see blockReal in case of change: duplicated code
5006 // increment the amount of declared variables for this block
5007 this.realBlockStack[this.realBlockPtr]++;
5008
5009 // update source end to include the semi-colon
5010 for (int i = variableDeclaratorsCounter - 1; i >= 0; i--) {
5011 LocalDeclaration localDeclaration = (LocalDeclaration) this.astStack[this.astPtr - i];
5012 localDeclaration.declarationSourceEnd = this.endStatementPosition;
5013 localDeclaration.declarationEnd = this.endStatementPosition; // semi-colon included
5014 }
5015
5016 }
consumeMarkerAnnotation(boolean isTypeAnnotation)5017 protected void consumeMarkerAnnotation(boolean isTypeAnnotation) {
5018 // MarkerAnnotation ::= AnnotationName
5019 // MarkerTypeAnnotation ::= TypeAnnotationName
5020 MarkerAnnotation markerAnnotation = null;
5021
5022 int oldIndex = this.identifierPtr;
5023
5024 TypeReference typeReference = getAnnotationType();
5025 markerAnnotation = new MarkerAnnotation(typeReference, this.intStack[this.intPtr--]);
5026 markerAnnotation.declarationSourceEnd = markerAnnotation.sourceEnd;
5027 if (isTypeAnnotation) {
5028 pushOnTypeAnnotationStack(markerAnnotation);
5029 } else {
5030 pushOnExpressionStack(markerAnnotation);
5031 }
5032 if(!this.statementRecoveryActivated &&
5033 this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
5034 this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
5035 problemReporter().invalidUsageOfAnnotation(markerAnnotation);
5036 }
5037 this.recordStringLiterals = true;
5038
5039 if (this.currentElement != null && this.currentElement instanceof RecoveredAnnotation) {
5040 this.currentElement = ((RecoveredAnnotation)this.currentElement).addAnnotation(markerAnnotation, oldIndex);
5041 }
5042 }
consumeMemberValueArrayInitializer()5043 protected void consumeMemberValueArrayInitializer() {
5044 // MemberValueArrayInitializer ::= '{' MemberValues ',' '}'
5045 // MemberValueArrayInitializer ::= '{' MemberValues '}'
5046 arrayInitializer(this.expressionLengthStack[this.expressionLengthPtr--]);
5047 }
consumeMemberValueAsName()5048 protected void consumeMemberValueAsName() {
5049 pushOnExpressionStack(getUnspecifiedReferenceOptimized());
5050 }
consumeMemberValuePair()5051 protected void consumeMemberValuePair() {
5052 // MemberValuePair ::= SimpleName '=' MemberValue
5053 char[] simpleName = this.identifierStack[this.identifierPtr];
5054 long position = this.identifierPositionStack[this.identifierPtr--];
5055 this.identifierLengthPtr--;
5056 int end = (int) position;
5057 int start = (int) (position >>> 32);
5058 Expression value = this.expressionStack[this.expressionPtr--];
5059 this.expressionLengthPtr--;
5060 MemberValuePair memberValuePair = new MemberValuePair(simpleName, start, end, value);
5061 pushOnAstStack(memberValuePair);
5062
5063 if (this.currentElement != null && this.currentElement instanceof RecoveredAnnotation) {
5064 RecoveredAnnotation recoveredAnnotation = (RecoveredAnnotation) this.currentElement;
5065
5066 recoveredAnnotation.setKind(RecoveredAnnotation.NORMAL);
5067 }
5068 }
consumeMemberValuePairs()5069 protected void consumeMemberValuePairs() {
5070 // MemberValuePairs ::= MemberValuePairs ',' MemberValuePair
5071 concatNodeLists();
5072 }
consumeMemberValues()5073 protected void consumeMemberValues() {
5074 // MemberValues ::= MemberValues ',' MemberValue
5075 concatExpressionLists();
5076 }
consumeMethodBody()5077 protected void consumeMethodBody() {
5078 // MethodBody ::= NestedMethod '{' BlockStatementsopt '}'
5079 this.nestedMethod[this.nestedType] --;
5080 }
consumeMethodDeclaration(boolean isNotAbstract, boolean isDefaultMethod)5081 protected void consumeMethodDeclaration(boolean isNotAbstract, boolean isDefaultMethod) {
5082 // MethodDeclaration ::= MethodHeader MethodBody
5083 // AbstractMethodDeclaration ::= MethodHeader ';'
5084
5085 /*
5086 this.astStack : modifiers arguments throws statements
5087 this.identifierStack : type name
5088 this.intStack : dim dim dim
5089 ==>
5090 this.astStack : MethodDeclaration
5091 this.identifierStack :
5092 this.intStack :
5093 */
5094
5095 int length;
5096 if (isNotAbstract) {
5097 // pop the position of the { (body of the method) pushed in block decl
5098 this.intPtr--;
5099 this.intPtr--;
5100 }
5101
5102 int explicitDeclarations = 0;
5103 Statement[] statements = null;
5104 if (isNotAbstract) {
5105 //statements
5106 explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
5107 if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
5108 if (this.options.ignoreMethodBodies) {
5109 this.astPtr -= length;
5110 } else {
5111 System.arraycopy(
5112 this.astStack,
5113 (this.astPtr -= length) + 1,
5114 statements = new Statement[length],
5115 0,
5116 length);
5117 }
5118 }
5119 }
5120
5121 // now we know that we have a method declaration at the top of the ast stack
5122 MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr];
5123 md.statements = statements;
5124 md.explicitDeclarations = explicitDeclarations;
5125
5126 // cannot be done in consumeMethodHeader because we have no idea whether or not there
5127 // is a body when we reduce the method header
5128 if (!isNotAbstract) { //remember the fact that the method has a semicolon body
5129 md.modifiers |= ExtraCompilerModifiers.AccSemicolonBody;
5130 } else if (!(this.diet && this.dietInt == 0) && statements == null && !containsComment(md.bodyStart, this.endPosition)) {
5131 md.bits |= ASTNode.UndocumentedEmptyBlock;
5132 }
5133 // store the this.endPosition (position just before the '}') in case there is
5134 // a trailing comment behind the end of the method
5135 md.bodyEnd = this.endPosition;
5136 md.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
5137 if (isDefaultMethod && !this.tolerateDefaultClassMethods) {
5138 if (this.options.sourceLevel >= ClassFileConstants.JDK1_8) {
5139 problemReporter().defaultModifierIllegallySpecified(md.sourceStart, md.sourceEnd);
5140 } else {
5141 problemReporter().illegalModifierForMethod(md);
5142 }
5143 }
5144 }
consumeMethodHeader()5145 protected void consumeMethodHeader() {
5146 // MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
5147 // AnnotationMethodHeader ::= AnnotationMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims AnnotationMethodHeaderDefaultValueopt
5148 // RecoveryMethodHeader ::= RecoveryMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims AnnotationMethodHeaderDefaultValueopt
5149 // RecoveryMethodHeader ::= RecoveryMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims MethodHeaderThrowsClause
5150
5151 // retrieve end position of method declarator
5152 AbstractMethodDeclaration method = (AbstractMethodDeclaration)this.astStack[this.astPtr];
5153
5154 if (this.currentToken == TokenNameLBRACE){
5155 method.bodyStart = this.scanner.currentPosition;
5156 }
5157 // recovery
5158 if (this.currentElement != null){
5159 // if(method.isAnnotationMethod()) {
5160 // method.modifiers |= AccSemicolonBody;
5161 // method.declarationSourceEnd = this.scanner.currentPosition-1;
5162 // method.bodyEnd = this.scanner.currentPosition-1;
5163 // this.currentElement = this.currentElement.parent;
5164 // } else
5165 if (this.currentToken == TokenNameSEMICOLON /*&& !method.isAnnotationMethod()*/){
5166 method.modifiers |= ExtraCompilerModifiers.AccSemicolonBody;
5167 method.declarationSourceEnd = this.scanner.currentPosition-1;
5168 method.bodyEnd = this.scanner.currentPosition-1;
5169 if (this.currentElement.parseTree() == method && this.currentElement.parent != null) {
5170 this.currentElement = this.currentElement.parent;
5171 }
5172 } else if(this.currentToken == TokenNameLBRACE) {
5173 if (this.currentElement instanceof RecoveredMethod &&
5174 ((RecoveredMethod)this.currentElement).methodDeclaration != method) {
5175 this.ignoreNextOpeningBrace = true;
5176 this.currentElement.bracketBalance++;
5177 }
5178 }
5179 this.restartRecovery = true; // used to avoid branching back into the regular automaton
5180 }
5181 }
consumeMethodHeaderDefaultValue()5182 protected void consumeMethodHeaderDefaultValue() {
5183 // MethodHeaderDefaultValue ::= DefaultValue
5184 MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr];
5185
5186
5187 int length = this.expressionLengthStack[this.expressionLengthPtr--];
5188 if (length == 1) {
5189 this.intPtr--; // we get rid of the position of the default keyword
5190 this.intPtr--; // we get rid of the position of the default keyword
5191 if(md.isAnnotationMethod()) {
5192 ((AnnotationMethodDeclaration)md).defaultValue = this.expressionStack[this.expressionPtr];
5193 md.modifiers |= ClassFileConstants.AccAnnotationDefault;
5194 }
5195 this.expressionPtr--;
5196 this.recordStringLiterals = true;
5197 }
5198
5199 if(this.currentElement != null) {
5200 if(md.isAnnotationMethod()) {
5201 this.currentElement.updateSourceEndIfNecessary(((AnnotationMethodDeclaration)md).defaultValue.sourceEnd);
5202 }
5203 }
5204 }
consumeMethodHeaderExtendedDims()5205 protected void consumeMethodHeaderExtendedDims() {
5206 // MethodHeaderExtendedDims ::= Dimsopt
5207 // now we update the returnType of the method
5208 MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr];
5209 int extendedDimensions = this.intStack[this.intPtr--];
5210 if(md.isAnnotationMethod()) {
5211 ((AnnotationMethodDeclaration)md).extendedDimensions = extendedDimensions;
5212 }
5213 if (extendedDimensions != 0) {
5214 md.sourceEnd = this.endPosition;
5215 md.returnType = augmentTypeWithAdditionalDimensions(md.returnType, extendedDimensions, getAnnotationsOnDimensions(extendedDimensions), false);
5216 md.bits |= (md.returnType.bits & ASTNode.HasTypeAnnotations);
5217 if (this.currentToken == TokenNameLBRACE){
5218 md.bodyStart = this.endPosition + 1;
5219 }
5220 // recovery
5221 if (this.currentElement != null){
5222 this.lastCheckPoint = md.bodyStart;
5223 }
5224 }
5225 }
consumeMethodHeaderName(boolean isAnnotationMethod)5226 protected void consumeMethodHeaderName(boolean isAnnotationMethod) {
5227 // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
5228 // AnnotationMethodHeaderName ::= Modifiersopt Type 'Identifier' '('
5229 // RecoveryMethodHeaderName ::= Modifiersopt Type 'Identifier' '('
5230 MethodDeclaration md = null;
5231 if(isAnnotationMethod) {
5232 md = new AnnotationMethodDeclaration(this.compilationUnit.compilationResult);
5233 this.recordStringLiterals = false;
5234 } else {
5235 md = new MethodDeclaration(this.compilationUnit.compilationResult);
5236 }
5237
5238 //name
5239 md.selector = this.identifierStack[this.identifierPtr];
5240 long selectorSource = this.identifierPositionStack[this.identifierPtr--];
5241 this.identifierLengthPtr--;
5242 //type
5243 md.returnType = getTypeReference(this.intStack[this.intPtr--]);
5244 md.bits |= (md.returnType.bits & ASTNode.HasTypeAnnotations);
5245 //modifiers
5246 md.declarationSourceStart = this.intStack[this.intPtr--];
5247 md.modifiers = this.intStack[this.intPtr--];
5248 // consume annotations
5249 int length;
5250 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
5251 System.arraycopy(
5252 this.expressionStack,
5253 (this.expressionPtr -= length) + 1,
5254 md.annotations = new Annotation[length],
5255 0,
5256 length);
5257 }
5258 // javadoc
5259 md.javadoc = this.javadoc;
5260 this.javadoc = null;
5261
5262 //highlight starts at selector start
5263 md.sourceStart = (int) (selectorSource >>> 32);
5264 pushOnAstStack(md);
5265 md.sourceEnd = this.lParenPos;
5266 md.bodyStart = this.lParenPos+1;
5267 this.listLength = 0; // initialize this.listLength before reading parameters/throws
5268
5269 // recovery
5270 if (this.currentElement != null){
5271 if (this.currentElement instanceof RecoveredType
5272 //|| md.modifiers != 0
5273 || (Util.getLineNumber(md.returnType.sourceStart, this.scanner.lineEnds, 0, this.scanner.linePtr)
5274 == Util.getLineNumber(md.sourceStart, this.scanner.lineEnds, 0, this.scanner.linePtr))){
5275 this.lastCheckPoint = md.bodyStart;
5276 this.currentElement = this.currentElement.add(md, 0);
5277 this.lastIgnoredToken = -1;
5278 } else {
5279 this.lastCheckPoint = md.sourceStart;
5280 this.restartRecovery = true;
5281 }
5282 }
5283 }
consumeMethodHeaderNameWithTypeParameters(boolean isAnnotationMethod)5284 protected void consumeMethodHeaderNameWithTypeParameters(boolean isAnnotationMethod) {
5285 // MethodHeaderName ::= Modifiersopt TypeParameters Type 'Identifier' '('
5286 // AnnotationMethodHeaderName ::= Modifiersopt TypeParameters Type 'Identifier' '('
5287 // RecoveryMethodHeaderName ::= Modifiersopt TypeParameters Type 'Identifier' '('
5288 MethodDeclaration md = null;
5289 if(isAnnotationMethod) {
5290 md = new AnnotationMethodDeclaration(this.compilationUnit.compilationResult);
5291 this.recordStringLiterals = false;
5292 } else {
5293 md = new MethodDeclaration(this.compilationUnit.compilationResult);
5294 }
5295
5296 //name
5297 md.selector = this.identifierStack[this.identifierPtr];
5298 long selectorSource = this.identifierPositionStack[this.identifierPtr--];
5299 this.identifierLengthPtr--;
5300 //type
5301 TypeReference returnType = getTypeReference(this.intStack[this.intPtr--]);
5302 if (isAnnotationMethod)
5303 rejectIllegalLeadingTypeAnnotations(returnType);
5304 md.returnType = returnType;
5305 md.bits |= (returnType.bits & ASTNode.HasTypeAnnotations);
5306
5307 // consume type parameters
5308 int length = this.genericsLengthStack[this.genericsLengthPtr--];
5309 this.genericsPtr -= length;
5310 System.arraycopy(this.genericsStack, this.genericsPtr + 1, md.typeParameters = new TypeParameter[length], 0, length);
5311
5312 //modifiers
5313 md.declarationSourceStart = this.intStack[this.intPtr--];
5314 md.modifiers = this.intStack[this.intPtr--];
5315 // consume annotations
5316 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
5317 System.arraycopy(
5318 this.expressionStack,
5319 (this.expressionPtr -= length) + 1,
5320 md.annotations = new Annotation[length],
5321 0,
5322 length);
5323 }
5324 // javadoc
5325 md.javadoc = this.javadoc;
5326 this.javadoc = null;
5327
5328 //highlight starts at selector start
5329 md.sourceStart = (int) (selectorSource >>> 32);
5330 pushOnAstStack(md);
5331 md.sourceEnd = this.lParenPos;
5332 md.bodyStart = this.lParenPos+1;
5333 this.listLength = 0; // initialize this.listLength before reading parameters/throws
5334
5335 // recovery
5336 if (this.currentElement != null){
5337 boolean isType;
5338 if ((isType = this.currentElement instanceof RecoveredType)
5339 //|| md.modifiers != 0
5340 || (Util.getLineNumber(md.returnType.sourceStart, this.scanner.lineEnds, 0, this.scanner.linePtr)
5341 == Util.getLineNumber(md.sourceStart, this.scanner.lineEnds, 0, this.scanner.linePtr))){
5342 if(isType) {
5343 ((RecoveredType) this.currentElement).pendingTypeParameters = null;
5344 }
5345 this.lastCheckPoint = md.bodyStart;
5346 this.currentElement = this.currentElement.add(md, 0);
5347 this.lastIgnoredToken = -1;
5348 } else {
5349 this.lastCheckPoint = md.sourceStart;
5350 this.restartRecovery = true;
5351 }
5352 }
5353 }
consumeMethodHeaderRightParen()5354 protected void consumeMethodHeaderRightParen() {
5355 // MethodHeaderParameters ::= FormalParameterListopt ')'
5356 int length = this.astLengthStack[this.astLengthPtr--];
5357 this.astPtr -= length;
5358 AbstractMethodDeclaration md = (AbstractMethodDeclaration) this.astStack[this.astPtr];
5359 md.sourceEnd = this.rParenPos;
5360 //arguments
5361 if (length != 0) {
5362 Argument arg = (Argument) this.astStack[this.astPtr + 1];
5363 if (arg.isReceiver()) {
5364 md.receiver = (Receiver) arg;
5365 if (length > 1) {
5366 System.arraycopy(
5367 this.astStack,
5368 this.astPtr + 2,
5369 md.arguments = new Argument[length - 1],
5370 0,
5371 length - 1);
5372 }
5373 // Receiver annotations can only be type annotations; move to the type
5374 Annotation[] annotations = arg.annotations;
5375 if (annotations != null && annotations.length > 0) {
5376 // The code assumes that receiver.type.annotations[0] will be null/empty
5377 TypeReference type = arg.type;
5378 if (type.annotations == null) {
5379 type.bits |= ASTNode.HasTypeAnnotations;
5380 type.annotations = new Annotation[type.getAnnotatableLevels()][];
5381 md.bits |= ASTNode.HasTypeAnnotations;
5382 }
5383 type.annotations[0] = annotations;
5384 int annotationSourceStart = annotations[0].sourceStart;
5385 if (type.sourceStart > annotationSourceStart)
5386 type.sourceStart = annotationSourceStart;
5387 arg.annotations = null;
5388 }
5389 md.bits |= (arg.type.bits & ASTNode.HasTypeAnnotations);
5390 } else {
5391 System.arraycopy(
5392 this.astStack,
5393 this.astPtr + 1,
5394 md.arguments = new Argument[length],
5395 0,
5396 length);
5397 for (int i = 0, max = md.arguments.length; i < max; i++) {
5398 if ((md.arguments[i].bits & ASTNode.HasTypeAnnotations) != 0) {
5399 md.bits |= ASTNode.HasTypeAnnotations;
5400 break;
5401 }
5402 }
5403 }
5404 }
5405 md.bodyStart = this.rParenPos+1;
5406 this.listLength = 0; // reset this.listLength after having read all parameters
5407 // recovery
5408 if (this.currentElement != null){
5409 this.lastCheckPoint = md.bodyStart;
5410 if (this.currentElement.parseTree() == md) return;
5411
5412 // might not have been attached yet - in some constructor scenarii
5413 if (md.isConstructor()){
5414 if ((length != 0)
5415 || (this.currentToken == TokenNameLBRACE)
5416 || (this.currentToken == TokenNamethrows)){
5417 this.currentElement = this.currentElement.add(md, 0);
5418 this.lastIgnoredToken = -1;
5419 }
5420 }
5421 }
5422 }
consumeMethodHeaderThrowsClause()5423 protected void consumeMethodHeaderThrowsClause() {
5424 // MethodHeaderThrowsClause ::= 'throws' ClassTypeList
5425 int length = this.astLengthStack[this.astLengthPtr--];
5426 this.astPtr -= length;
5427 AbstractMethodDeclaration md = (AbstractMethodDeclaration) this.astStack[this.astPtr];
5428 System.arraycopy(
5429 this.astStack,
5430 this.astPtr + 1,
5431 md.thrownExceptions = new TypeReference[length],
5432 0,
5433 length);
5434 md.sourceEnd = md.thrownExceptions[length-1].sourceEnd;
5435 md.bodyStart = md.thrownExceptions[length-1].sourceEnd + 1;
5436 this.listLength = 0; // reset this.listLength after having read all thrown exceptions
5437 // recovery
5438 if (this.currentElement != null){
5439 this.lastCheckPoint = md.bodyStart;
5440 }
5441 }
consumeInvocationExpression()5442 protected void consumeInvocationExpression() {
5443 // Trap all forms of invocation expressions. Note: Explicit constructor calls are not expressions. Top of expression stack has the MessageSend or AllocationExpression.
5444 }
consumeMethodInvocationName()5445 protected void consumeMethodInvocationName() {
5446 // MethodInvocation ::= Name '(' ArgumentListopt ')'
5447
5448 // when the name is only an identifier...we have a message send to "this" (implicit)
5449
5450 MessageSend m = newMessageSend();
5451 m.sourceEnd = this.rParenPos;
5452 m.sourceStart =
5453 (int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32);
5454 m.selector = this.identifierStack[this.identifierPtr--];
5455 if (this.identifierLengthStack[this.identifierLengthPtr] == 1) {
5456 m.receiver = ThisReference.implicitThis();
5457 this.identifierLengthPtr--;
5458 } else {
5459 this.identifierLengthStack[this.identifierLengthPtr]--;
5460 m.receiver = getUnspecifiedReference();
5461 m.sourceStart = m.receiver.sourceStart;
5462 }
5463 int length = this.typeAnnotationLengthStack[this.typeAnnotationLengthPtr--];
5464 Annotation [] typeAnnotations;
5465 if (length != 0) {
5466 System.arraycopy(
5467 this.typeAnnotationStack,
5468 (this.typeAnnotationPtr -= length) + 1,
5469 typeAnnotations = new Annotation[length],
5470 0,
5471 length);
5472 problemReporter().misplacedTypeAnnotations(typeAnnotations[0], typeAnnotations[typeAnnotations.length - 1]);
5473 }
5474 pushOnExpressionStack(m);
5475 consumeInvocationExpression();
5476 }
consumeMethodInvocationNameWithTypeArguments()5477 protected void consumeMethodInvocationNameWithTypeArguments() {
5478 // MethodInvocation ::= Name '.' TypeArguments 'Identifier' '(' ArgumentListopt ')'
5479
5480 // when the name is only an identifier...we have a message send to "this" (implicit)
5481
5482 MessageSend m = newMessageSendWithTypeArguments();
5483 m.sourceEnd = this.rParenPos;
5484 m.sourceStart =
5485 (int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32);
5486 m.selector = this.identifierStack[this.identifierPtr--];
5487 this.identifierLengthPtr--;
5488
5489 // handle type arguments
5490 int length = this.genericsLengthStack[this.genericsLengthPtr--];
5491 this.genericsPtr -= length;
5492 System.arraycopy(this.genericsStack, this.genericsPtr + 1, m.typeArguments = new TypeReference[length], 0, length);
5493 this.intPtr--; // consume position of '<'
5494
5495 m.receiver = getUnspecifiedReference();
5496 m.sourceStart = m.receiver.sourceStart;
5497 pushOnExpressionStack(m);
5498 consumeInvocationExpression();
5499 }
consumeMethodInvocationPrimary()5500 protected void consumeMethodInvocationPrimary() {
5501 //optimize the push/pop
5502 //MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
5503
5504 MessageSend m = newMessageSend();
5505 m.sourceStart =
5506 (int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32);
5507 m.selector = this.identifierStack[this.identifierPtr--];
5508 this.identifierLengthPtr--;
5509 m.receiver = this.expressionStack[this.expressionPtr];
5510 m.sourceStart = m.receiver.sourceStart;
5511 m.sourceEnd = this.rParenPos;
5512 this.expressionStack[this.expressionPtr] = m;
5513 consumeInvocationExpression();
5514 }
consumeMethodInvocationPrimaryWithTypeArguments()5515 protected void consumeMethodInvocationPrimaryWithTypeArguments() {
5516 //optimize the push/pop
5517 //MethodInvocation ::= Primary '.' TypeArguments 'Identifier' '(' ArgumentListopt ')'
5518
5519 MessageSend m = newMessageSendWithTypeArguments();
5520 m.sourceStart =
5521 (int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32);
5522 m.selector = this.identifierStack[this.identifierPtr--];
5523 this.identifierLengthPtr--;
5524
5525 // handle type arguments
5526 int length = this.genericsLengthStack[this.genericsLengthPtr--];
5527 this.genericsPtr -= length;
5528 System.arraycopy(this.genericsStack, this.genericsPtr + 1, m.typeArguments = new TypeReference[length], 0, length);
5529 this.intPtr--; // consume position of '<'
5530
5531 m.receiver = this.expressionStack[this.expressionPtr];
5532 m.sourceStart = m.receiver.sourceStart;
5533 m.sourceEnd = this.rParenPos;
5534 this.expressionStack[this.expressionPtr] = m;
5535 consumeInvocationExpression();
5536 }
consumeMethodInvocationSuper()5537 protected void consumeMethodInvocationSuper() {
5538 // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
5539
5540 MessageSend m = newMessageSend();
5541 m.sourceStart = this.intStack[this.intPtr--]; // start position of the super keyword
5542 m.sourceEnd = this.rParenPos;
5543 m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr];
5544 m.selector = this.identifierStack[this.identifierPtr--];
5545 this.identifierLengthPtr--;
5546 m.receiver = new SuperReference(m.sourceStart, this.endPosition);
5547 pushOnExpressionStack(m);
5548 consumeInvocationExpression();
5549 }
consumeMethodInvocationSuperWithTypeArguments()5550 protected void consumeMethodInvocationSuperWithTypeArguments() {
5551 // MethodInvocation ::= 'super' '.' TypeArguments 'Identifier' '(' ArgumentListopt ')'
5552
5553 MessageSend m = newMessageSendWithTypeArguments();
5554 this.intPtr--; // start position of the typeArguments
5555 m.sourceEnd = this.rParenPos;
5556 m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr];
5557 m.selector = this.identifierStack[this.identifierPtr--];
5558 this.identifierLengthPtr--;
5559
5560 // handle type arguments
5561 int length = this.genericsLengthStack[this.genericsLengthPtr--];
5562 this.genericsPtr -= length;
5563 System.arraycopy(this.genericsStack, this.genericsPtr + 1, m.typeArguments = new TypeReference[length], 0, length);
5564 m.sourceStart = this.intStack[this.intPtr--]; // start position of the super keyword
5565
5566 m.receiver = new SuperReference(m.sourceStart, this.endPosition);
5567 pushOnExpressionStack(m);
5568 consumeInvocationExpression();
5569 }
consumeModifiers()5570 protected void consumeModifiers() {
5571 int savedModifiersSourceStart = this.modifiersSourceStart;
5572 checkComment(); // might update modifiers with AccDeprecated
5573 pushOnIntStack(this.modifiers); // modifiers
5574 if (this.modifiersSourceStart >= savedModifiersSourceStart) {
5575 this.modifiersSourceStart = savedModifiersSourceStart;
5576 }
5577 pushOnIntStack(this.modifiersSourceStart);
5578 resetModifiers();
5579 }
consumeModifiers2()5580 protected void consumeModifiers2() {
5581 this.expressionLengthStack[this.expressionLengthPtr - 1] += this.expressionLengthStack[this.expressionLengthPtr--];
5582 }
consumeMultipleResources()5583 protected void consumeMultipleResources() {
5584 // Resources ::= Resources ';' Resource
5585 concatNodeLists();
5586 }
consumeTypeAnnotation()5587 protected void consumeTypeAnnotation() {
5588 // TypeAnnotation ::= NormalTypeAnnotation
5589 // TypeAnnotation ::= MarkerTypeAnnotation
5590 // TypeAnnotation ::= SingleMemberTypeAnnotation
5591
5592 if (!this.statementRecoveryActivated &&
5593 this.options.sourceLevel < ClassFileConstants.JDK1_8 &&
5594 this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
5595 Annotation annotation = this.typeAnnotationStack[this.typeAnnotationPtr];
5596 problemReporter().invalidUsageOfTypeAnnotations(annotation);
5597 }
5598 this.dimensions = this.intStack[this.intPtr--]; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=417660
5599 }
consumeOneMoreTypeAnnotation()5600 protected void consumeOneMoreTypeAnnotation() {
5601 // TypeAnnotations ::= TypeAnnotations TypeAnnotation
5602 this.typeAnnotationLengthStack[--this.typeAnnotationLengthPtr]++;
5603 }
consumeNameArrayType()5604 protected void consumeNameArrayType() {
5605 pushOnGenericsLengthStack(0); // handle type arguments
5606 pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
5607 }
consumeNestedMethod()5608 protected void consumeNestedMethod() {
5609 // NestedMethod ::= $empty
5610 jumpOverMethodBody();
5611 this.nestedMethod[this.nestedType] ++;
5612 pushOnIntStack(this.scanner.currentPosition);
5613 consumeOpenBlock();
5614 }
consumeNestedType()5615 protected void consumeNestedType() {
5616 // NestedType ::= $empty
5617 int length = this.nestedMethod.length;
5618 if (++this.nestedType >= length) {
5619 System.arraycopy(
5620 this.nestedMethod, 0,
5621 this.nestedMethod = new int[length + 30], 0,
5622 length);
5623 // increase the size of the variablesCounter as well. It has to be consistent with the size of the nestedMethod collection
5624 System.arraycopy(
5625 this.variablesCounter, 0,
5626 this.variablesCounter = new int[length + 30], 0,
5627 length);
5628 }
5629 this.nestedMethod[this.nestedType] = 0;
5630 this.variablesCounter[this.nestedType] = 0;
5631 }
consumeNormalAnnotation(boolean isTypeAnnotation)5632 protected void consumeNormalAnnotation(boolean isTypeAnnotation) {
5633 // NormalTypeAnnotation ::= TypeAnnotationName '(' MemberValuePairsopt ')'
5634 // NormalAnnotation ::= AnnotationName '(' MemberValuePairsopt ')'
5635 NormalAnnotation normalAnnotation = null;
5636
5637 int oldIndex = this.identifierPtr;
5638
5639 TypeReference typeReference = getAnnotationType();
5640 normalAnnotation = new NormalAnnotation(typeReference, this.intStack[this.intPtr--]);
5641 int length;
5642 if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
5643 System.arraycopy(
5644 this.astStack,
5645 (this.astPtr -= length) + 1,
5646 normalAnnotation.memberValuePairs = new MemberValuePair[length],
5647 0,
5648 length);
5649 }
5650 normalAnnotation.declarationSourceEnd = this.rParenPos;
5651
5652 if (isTypeAnnotation) {
5653 pushOnTypeAnnotationStack(normalAnnotation);
5654 } else {
5655 pushOnExpressionStack(normalAnnotation);
5656 }
5657
5658 if(this.currentElement != null) {
5659 annotationRecoveryCheckPoint(normalAnnotation.sourceStart, normalAnnotation.declarationSourceEnd);
5660
5661 if (this.currentElement instanceof RecoveredAnnotation) {
5662 this.currentElement = ((RecoveredAnnotation)this.currentElement).addAnnotation(normalAnnotation, oldIndex);
5663 }
5664 }
5665
5666 if(!this.statementRecoveryActivated &&
5667 this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
5668 this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
5669 problemReporter().invalidUsageOfAnnotation(normalAnnotation);
5670 }
5671 this.recordStringLiterals = true;
5672 }
consumeOneDimLoop(boolean isAnnotated)5673 protected void consumeOneDimLoop(boolean isAnnotated) {
5674 // OneDimLoop ::= '[' ']'
5675 // OneDimLoop ::= TypeAnnotations '[' ']'
5676 this.dimensions++;
5677 if (!isAnnotated) {
5678 pushOnTypeAnnotationLengthStack(0); // signal no annotations for the current dimension.
5679 }
5680 }
consumeOnlySynchronized()5681 protected void consumeOnlySynchronized() {
5682 // OnlySynchronized ::= 'synchronized'
5683 pushOnIntStack(this.synchronizedBlockSourceStart);
5684 resetModifiers();
5685 this.expressionLengthPtr--;
5686 }
consumeOnlyTypeArguments()5687 protected void consumeOnlyTypeArguments() {
5688 if(!this.statementRecoveryActivated &&
5689 this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
5690 this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
5691 int length = this.genericsLengthStack[this.genericsLengthPtr];
5692 problemReporter().invalidUsageOfTypeArguments(
5693 (TypeReference)this.genericsStack[this.genericsPtr - length + 1],
5694 (TypeReference)this.genericsStack[this.genericsPtr]);
5695 }
5696 }
consumeOnlyTypeArgumentsForCastExpression()5697 protected void consumeOnlyTypeArgumentsForCastExpression() {
5698 // OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments
5699 }
consumeOpenBlock()5700 protected void consumeOpenBlock() {
5701 // OpenBlock ::= $empty
5702
5703 pushOnIntStack(this.scanner.startPosition);
5704 int stackLength = this.realBlockStack.length;
5705 if (++this.realBlockPtr >= stackLength) {
5706 System.arraycopy(
5707 this.realBlockStack, 0,
5708 this.realBlockStack = new int[stackLength + StackIncrement], 0,
5709 stackLength);
5710 }
5711 this.realBlockStack[this.realBlockPtr] = 0;
5712 }
consumePackageComment()5713 protected void consumePackageComment() {
5714 // get possible comment for syntax since 1.5
5715 if(this.options.sourceLevel >= ClassFileConstants.JDK1_5) {
5716 checkComment();
5717 resetModifiers();
5718 }
5719 }
consumeInternalCompilationUnitWithModuleDeclaration()5720 protected void consumeInternalCompilationUnitWithModuleDeclaration() {
5721 this.compilationUnit.moduleDeclaration = (ModuleDeclaration)this.astStack[this.astPtr--];
5722 this.astLengthStack[this.astLengthPtr--] = 0;
5723 }
consumeRequiresStatement()5724 protected void consumeRequiresStatement() {
5725 RequiresStatement req = (RequiresStatement) this.astStack[this.astPtr];
5726 req.declarationEnd = req.declarationSourceEnd = this.endStatementPosition;
5727 // recovery
5728 if (this.currentElement instanceof RecoveredModule) {
5729 this.lastCheckPoint = req.declarationSourceEnd + 1;
5730 this.currentElement = this.currentElement.add(req, 0);
5731 this.lastIgnoredToken = -1;
5732 this.restartRecovery = true; // used to avoid branching back into the regular automaton
5733 }
5734 }
consumeSingleRequiresModuleName()5735 protected void consumeSingleRequiresModuleName() {
5736 ModuleReference impt;
5737 int length;
5738 char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
5739 this.identifierPtr -= length;
5740 long[] positions = new long[length];
5741 System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
5742 System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
5743 RequiresStatement req = new RequiresStatement(impt = new ModuleReference(tokens, positions));
5744 if (this.currentToken == TokenNameSEMICOLON){
5745 req.declarationSourceEnd = impt.sourceEnd + 1;
5746 } else {
5747 req.declarationSourceEnd = impt.sourceEnd;
5748 }
5749 req.declarationEnd = req.declarationSourceEnd;
5750 req.modifiersSourceStart = this.intStack[this.intPtr--];
5751 req.modifiers |= this.intStack[this.intPtr--];
5752 req.sourceStart = req.declarationSourceStart = this.intStack[this.intPtr--];
5753 req.sourceEnd = impt.sourceEnd;
5754 pushOnAstStack(req);
5755 // recovery
5756 if (this.currentElement instanceof RecoveredModule){
5757 this.lastCheckPoint = req.declarationSourceEnd;
5758 }
5759 }
consumeExportsStatement()5760 protected void consumeExportsStatement() {
5761 ExportsStatement expt = (ExportsStatement) this.astStack[this.astPtr];
5762 expt.declarationSourceEnd = this.endStatementPosition;
5763 expt.declarationEnd = expt.declarationSourceEnd;
5764 // recovery
5765 if (this.currentElement instanceof RecoveredPackageVisibilityStatement) {
5766 this.lastCheckPoint = expt.declarationSourceEnd + 1;
5767 this.currentElement = this.currentElement.parent;
5768 this.lastIgnoredToken = -1;
5769 this.restartRecovery = true;
5770 // used to avoid branching back into the regular automaton
5771 }
5772 }
consumeExportsHeader()5773 protected void consumeExportsHeader() {
5774 ImportReference impt = (ImportReference) this.astStack[this.astPtr];
5775 impt.bits |= ASTNode.inModule;
5776 ExportsStatement expt = new ExportsStatement(impt);
5777 expt.declarationSourceStart = this.intStack[this.intPtr--];
5778 expt.sourceStart = expt.declarationSourceStart;
5779 expt.sourceEnd = impt.sourceEnd;
5780 if (this.currentToken == TokenNameSEMICOLON){
5781 expt.declarationSourceEnd = this.scanner.currentPosition - 1;
5782 } else {
5783 expt.declarationSourceEnd = expt.sourceEnd;
5784 }
5785 expt.declarationEnd = expt.declarationSourceEnd;
5786 this.astStack[this.astPtr] = expt; // replace with ExportsStatement
5787 // recovery
5788 if (this.currentElement instanceof RecoveredModule) {
5789 this.lastCheckPoint = expt.declarationSourceEnd + 1;
5790 this.currentElement = this.currentElement.add(expt, 0);
5791 }
5792 }
consumeOpensHeader()5793 protected void consumeOpensHeader() {
5794 ImportReference impt = (ImportReference) this.astStack[this.astPtr];
5795 impt.bits |= ASTNode.inModule;
5796 OpensStatement stmt = new OpensStatement(impt);
5797 stmt.declarationSourceStart = this.intStack[this.intPtr--];
5798 stmt.sourceStart = stmt.declarationSourceStart;
5799 stmt.sourceEnd = impt.sourceEnd;
5800 if (this.currentToken == TokenNameSEMICOLON){
5801 stmt.declarationSourceEnd = this.scanner.currentPosition - 1;
5802 } else {
5803 stmt.declarationSourceEnd = stmt.sourceEnd;
5804 }
5805 stmt.declarationEnd = stmt.declarationSourceEnd;
5806 this.astStack[this.astPtr] = stmt; // replace with OpensStatement
5807 // recovery
5808 if (this.currentElement instanceof RecoveredModule) {
5809 this.lastCheckPoint = stmt.declarationSourceEnd + 1;
5810 this.lastCheckPoint = stmt.declarationSourceEnd + 1;
5811 this.currentElement = this.currentElement.add(stmt, 0);
5812 }
5813 }
consumeOpensStatement()5814 protected void consumeOpensStatement() {
5815 OpensStatement expt = (OpensStatement) this.astStack[this.astPtr];
5816 expt.declarationSourceEnd = this.endStatementPosition;
5817 expt.declarationEnd = expt.declarationSourceEnd;
5818 // recovery
5819 if (this.currentElement instanceof RecoveredPackageVisibilityStatement) {
5820 this.lastCheckPoint = expt.declarationSourceEnd + 1;
5821 this.currentElement = this.currentElement.parent;
5822 this.lastIgnoredToken = -1;
5823 this.restartRecovery = true;
5824 // used to avoid branching back into the regular automaton
5825 }
5826 }
consumeSingleTargetModuleName()5827 protected void consumeSingleTargetModuleName() {
5828 ModuleReference reference;
5829 int length;
5830 char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
5831 this.identifierPtr -= length;
5832 long[] positions = new long[length];
5833 System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
5834 System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
5835 pushOnAstStack(reference = new ModuleReference(tokens, positions));
5836
5837 // recovery
5838 if (this.currentElement != null) {
5839 this.lastCheckPoint = reference.sourceEnd + 1;
5840 }
5841
5842 }
consumeTargetModuleList()5843 protected void consumeTargetModuleList() {
5844 int length = this.astLengthStack[this.astLengthPtr--];
5845 this.astPtr -= length;
5846 PackageVisibilityStatement node = (PackageVisibilityStatement) this.astStack[this.astPtr];
5847 if (length > 0) {
5848 System.arraycopy(
5849 this.astStack,
5850 this.astPtr + 1,
5851 node.targets = new ModuleReference[length],
5852 0,
5853 length);
5854 node.sourceEnd = node.targets[length - 1].sourceEnd;
5855 if (this.currentToken == TokenNameSEMICOLON){
5856 node.declarationSourceEnd = node.sourceEnd + 1;
5857 } else {
5858 node.declarationSourceEnd = node.sourceEnd;
5859 }
5860 }
5861
5862 this.listLength = 0; // reset after having read target modules list
5863 // recovery TBD
5864 if (this.currentElement != null) { // is recovering
5865 this.lastCheckPoint = node.sourceEnd;
5866 }
5867 }
consumeTargetModuleNameList()5868 protected void consumeTargetModuleNameList() {
5869 this.listLength++;
5870 optimizedConcatNodeLists();
5871 }
consumeSinglePkgName()5872 protected void consumeSinglePkgName() {
5873 ImportReference impt;
5874 int length;
5875 char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
5876 this.identifierPtr -= length;
5877 long[] positions = new long[length];
5878 System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
5879 System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
5880 pushOnAstStack(impt = new ImportReference(tokens, positions, false, ClassFileConstants.AccDefault));
5881
5882 // recovery
5883 if (this.currentElement instanceof RecoveredModule){
5884 this.lastCheckPoint = impt.sourceEnd + 1;
5885 }
5886 }
consumeUsesStatement()5887 protected void consumeUsesStatement() {
5888 UsesStatement stmt = (UsesStatement) this.astStack[this.astPtr];
5889 stmt.declarationEnd = stmt.declarationSourceEnd = this.endStatementPosition;
5890 // recovery
5891 if (this.currentElement instanceof RecoveredModule){
5892 this.lastCheckPoint = stmt.declarationSourceEnd;
5893 this.lastIgnoredToken = -1;
5894 this.restartRecovery = true;
5895 }
5896 }
consumeUsesHeader()5897 protected void consumeUsesHeader() {
5898 pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
5899 pushOnGenericsLengthStack(0);
5900 TypeReference siName = getTypeReference(0);
5901 if (siName.annotations != null) {
5902 for (int j = 0; j < siName.annotations.length; j++) {
5903 Annotation[] qualifierAnnot = siName.annotations[j];
5904 if (qualifierAnnot != null && qualifierAnnot.length > 0) {
5905 problemReporter().misplacedTypeAnnotations(qualifierAnnot[0], qualifierAnnot[qualifierAnnot.length - 1]);
5906 siName.annotations[j] = null;
5907 }
5908 }
5909 }
5910 UsesStatement stmt = new UsesStatement(siName);
5911 if (this.currentToken == TokenNameSEMICOLON){
5912 stmt.declarationSourceEnd = siName.sourceEnd + 1;
5913 } else {
5914 stmt.declarationSourceEnd = siName.sourceEnd;
5915 }
5916 stmt.declarationEnd = stmt.declarationSourceEnd;
5917 stmt.sourceStart = stmt.declarationSourceStart = this.intStack[this.intPtr--];
5918 stmt.sourceEnd = siName.sourceEnd;
5919 pushOnAstStack(stmt);
5920 // recovery
5921 if (this.currentElement instanceof RecoveredModule){
5922 this.lastCheckPoint = stmt.sourceEnd + 1;
5923 this.currentElement = this.currentElement.add(stmt, 0);
5924 }
5925 }
consumeProvidesInterface()5926 protected void consumeProvidesInterface() {
5927 pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
5928 pushOnGenericsLengthStack(0);
5929 TypeReference siName = getTypeReference(0);
5930 if (siName.annotations != null) {
5931 for (int j = 0; j < siName.annotations.length; j++) {
5932 Annotation[] qualifierAnnot = siName.annotations[j];
5933 if (qualifierAnnot != null && qualifierAnnot.length > 0) {
5934 problemReporter().misplacedTypeAnnotations(qualifierAnnot[0], qualifierAnnot[qualifierAnnot.length - 1]);
5935 siName.annotations[j] = null;
5936 }
5937 }
5938 }
5939 ProvidesStatement ref = new ProvidesStatement();
5940 ref.serviceInterface = siName;
5941 pushOnAstStack(ref);
5942 ref.declarationSourceStart = this.intStack[this.intPtr--];
5943 ref.sourceStart = ref.declarationSourceStart;
5944 ref.sourceEnd = siName.sourceEnd;
5945 ref.declarationSourceEnd = ref.sourceEnd;
5946 // recovery
5947 if (this.currentElement instanceof RecoveredModule) {
5948 this.lastCheckPoint = siName.sourceEnd + 1;
5949 this.currentElement = this.currentElement.add(ref, 0);
5950 this.lastIgnoredToken = -1;
5951 }
5952 }
consumeSingleServiceImplName()5953 protected void consumeSingleServiceImplName() {
5954 pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
5955 pushOnGenericsLengthStack(0);
5956 TypeReference siName = getTypeReference(0);
5957 if (siName.annotations != null) {
5958 for (int j = 0; j < siName.annotations.length; j++) {
5959 Annotation[] qualifierAnnot = siName.annotations[j];
5960 if (qualifierAnnot != null && qualifierAnnot.length > 0) {
5961 problemReporter().misplacedTypeAnnotations(qualifierAnnot[0], qualifierAnnot[qualifierAnnot.length - 1]);
5962 siName.annotations[j] = null;
5963 }
5964 }
5965 }
5966 pushOnAstStack(siName);
5967 // recovery
5968 if (this.currentElement instanceof RecoveredModule) {
5969 this.lastCheckPoint = siName.sourceEnd + 1;
5970 }
5971
5972 }
consumeServiceImplNameList()5973 protected void consumeServiceImplNameList() {
5974 this.listLength++;
5975 optimizedConcatNodeLists();
5976 }
consumeProvidesStatement()5977 protected void consumeProvidesStatement() {
5978 ProvidesStatement ref = (ProvidesStatement) this.astStack[this.astPtr];
5979 ref.declarationEnd = ref.declarationSourceEnd = this.endStatementPosition;
5980 //recovery
5981 if (this.currentElement instanceof RecoveredProvidesStatement) {
5982 this.lastIgnoredToken = -1;
5983 this.currentElement = this.currentElement.parent;
5984 this.restartRecovery = true; // used to avoid branching back into the regular automaton
5985 }
5986 }
consumeWithClause()5987 protected void consumeWithClause() {
5988 int length = this.astLengthStack[this.astLengthPtr--];
5989 this.astPtr -= length;
5990
5991 ProvidesStatement service = (ProvidesStatement) this.astStack[this.astPtr];
5992 System.arraycopy(
5993 this.astStack,
5994 this.astPtr + 1,
5995 service.implementations = new TypeReference[length],
5996 0,
5997 length);
5998
5999 service.sourceEnd = service.implementations[length - 1].sourceEnd;
6000
6001 if (this.currentToken == TokenNameSEMICOLON){
6002 service.declarationSourceEnd = service.sourceEnd + 1;
6003 } else {
6004 service.declarationSourceEnd = service.sourceEnd;
6005 }
6006 this.listLength = 0; // reset after having read super-interfaces
6007 // recovery
6008 if (this.currentElement instanceof RecoveredProvidesStatement) { // is recovering
6009 this.lastCheckPoint = service.declarationSourceEnd;
6010 }
6011 }
consumeEmptyModuleStatementsOpt()6012 protected void consumeEmptyModuleStatementsOpt() {
6013 pushOnAstLengthStack(0);
6014 }
consumeModuleStatements()6015 protected void consumeModuleStatements() {
6016 concatNodeLists();
6017 }
consumeModuleModifiers()6018 protected void consumeModuleModifiers() {
6019 checkComment(); // might update modifiers with AccDeprecated
6020 // Merge with other modifiers
6021 this.intStack[this.intPtr -1] |= this.modifiers;
6022 resetModifiers();
6023 // Account for the possible presence of annotations as well
6024 this.expressionLengthStack[this.expressionLengthPtr - 1] += this.expressionLengthStack[this.expressionLengthPtr--];
6025 }
consumeModuleHeader()6026 protected void consumeModuleHeader() {
6027 // ModuleHeader ::= 'module' Name
6028
6029 int length;
6030 char[][] tokens =
6031 new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
6032 this.identifierPtr -= length;
6033 long[] positions = new long[length];
6034 System.arraycopy(this.identifierStack, ++this.identifierPtr, tokens, 0, length);
6035 System.arraycopy(
6036 this.identifierPositionStack,
6037 this.identifierPtr--,
6038 positions,
6039 0,
6040 length);
6041
6042 ModuleDeclaration typeDecl = new ModuleDeclaration(this.compilationUnit.compilationResult, tokens, positions);
6043 //compute the declaration source too
6044 typeDecl.declarationSourceStart = this.intStack[this.intPtr--];
6045 typeDecl.bodyStart = typeDecl.sourceEnd + 1;
6046 typeDecl.modifiersSourceStart = this.intStack[this.intPtr--];
6047 typeDecl.modifiers = this.intStack[this.intPtr--];
6048 if (typeDecl.modifiersSourceStart >= 0) {
6049 typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
6050 }
6051 // int otherModifiersStart = this.intStack[this.intPtr--];
6052 // int otherModifiers = this.intStack[this.intPtr--];
6053 // if (otherModifiersStart >= 0) {
6054 // typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart = otherModifiersStart;
6055 // }
6056 // Merge with other modifiers
6057 // typeDecl.modifiers |= otherModifiers;
6058 if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
6059 System.arraycopy(
6060 this.expressionStack,
6061 (this.expressionPtr -= length) + 1,
6062 typeDecl.annotations = new Annotation[length],
6063 0,
6064 length);
6065 }
6066 pushOnAstStack(typeDecl);
6067
6068 this.listLength = 0;
6069 // recovery
6070 if (this.currentElement != null){
6071 this.lastCheckPoint = typeDecl.bodyStart;
6072 this.currentElement = this.currentElement.add(typeDecl, 0);
6073 this.lastIgnoredToken = -1;
6074 }
6075 // javadoc
6076 // typeDecl.javadoc = this.javadoc;
6077 // this.javadoc = null;
6078 }
consumeModuleDeclaration()6079 protected void consumeModuleDeclaration() {
6080 // ModuleDeclaration ::= ModuleHeader ModuleBody
6081 this.compilationUnit.javadoc = this.javadoc;
6082 this.javadoc = null;
6083
6084 int length = this.astLengthStack[this.astLengthPtr--];
6085 int[] flag = new int[length + 1]; //plus one -- see <HERE>
6086 int size1 = 0, size2 = 0, size3 = 0, size4 = 0, size5 = 0;
6087 if (length != 0) {
6088 //there are length declarations
6089 //dispatch according to the type of the declarations
6090 for (int i = length - 1; i >= 0; i--) {
6091 ASTNode astNode = this.astStack[this.astPtr--];
6092 if (astNode instanceof RequiresStatement) {
6093 flag[i] = 1;
6094 size1++;
6095 } else if (astNode instanceof ExportsStatement) {
6096 flag[i] = 2;
6097 size2++;
6098 } else if (astNode instanceof UsesStatement) {
6099 //field
6100 flag[i] = 3;
6101 size3++;
6102 } else if (astNode instanceof ProvidesStatement){
6103 flag[i] = 4;
6104 size4++;
6105 } else if (astNode instanceof OpensStatement) {
6106 flag[i] = 5;
6107 size5++;
6108 }
6109 }
6110 }
6111 ModuleDeclaration modul = (ModuleDeclaration) this.astStack[this.astPtr];
6112 modul.requiresCount = size1;
6113 modul.exportsCount = size2;
6114 modul.usesCount = size3;
6115 modul.servicesCount = size4;
6116 modul.opensCount = size5;
6117 modul.requires = new RequiresStatement[size1];
6118 modul.exports = new ExportsStatement[size2];
6119 modul.uses = new UsesStatement[size3];
6120 modul.services = new ProvidesStatement[size4];
6121 modul.opens = new OpensStatement[size5];
6122 //arrays fill up
6123 size1 = size2 = size3 = size4 = size5 = 0;
6124 int flagI = flag[0], start = 0;
6125 int length2;
6126 for (int end = 0; end <= length; end++) //<HERE> the plus one allows to
6127 {
6128 if (flagI != flag[end]) //treat the last element as a ended flag.....
6129 { //array copy
6130 switch (flagI) {
6131 case 1 :
6132 size1 += (length2 = end - start);
6133 System.arraycopy(
6134 this.astStack,
6135 this.astPtr + start + 1,
6136 modul.requires,
6137 size1 - length2,
6138 length2);
6139 break;
6140 case 2 :
6141 size2 += (length2 = end - start);
6142 System.arraycopy(
6143 this.astStack,
6144 this.astPtr + start + 1,
6145 modul.exports,
6146 size2 - length2,
6147 length2);
6148 break;
6149 case 3 :
6150 size3 += (length2 = end - start);
6151 System.arraycopy(
6152 this.astStack,
6153 this.astPtr + start + 1,
6154 modul.uses,
6155 size3 - length2,
6156 length2);
6157 break;
6158 case 4 :
6159 size4 += (length2 = end - start);
6160 System.arraycopy(
6161 this.astStack,
6162 this.astPtr + start + 1,
6163 modul.services,
6164 size4 - length2,
6165 length2);
6166 break;
6167 case 5 :
6168 size5 += (length2 = end - start);
6169 System.arraycopy(
6170 this.astStack,
6171 this.astPtr + start + 1,
6172 modul.opens,
6173 size5 - length2,
6174 length2);
6175 break;
6176 }
6177 flagI = flag[start = end];
6178 }
6179 }
6180 modul.bodyEnd = this.endStatementPosition;
6181 modul.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
6182 }
consumePackageDeclaration()6183 protected void consumePackageDeclaration() {
6184 // PackageDeclaration ::= 'package' Name ';'
6185 /* build an ImportRef build from the last name
6186 stored in the identifier stack. */
6187
6188 ImportReference impt = this.compilationUnit.currentPackage;
6189 this.compilationUnit.javadoc = this.javadoc;
6190 this.javadoc = null;
6191 // flush comments defined prior to import statements
6192 impt.declarationEnd = this.endStatementPosition;
6193 impt.declarationSourceEnd = flushCommentsDefinedPriorTo(impt.declarationSourceEnd);
6194 if (this.firstToken == TokenNameQUESTION)
6195 this.unstackedAct = ACCEPT_ACTION; // force termination at goal
6196 }
consumePackageDeclarationName()6197 protected void consumePackageDeclarationName() {
6198 // PackageDeclarationName ::= PackageComment 'package' Name RejectTypeAnnotations
6199 /* build an ImportRef build from the last name
6200 stored in the identifier stack. */
6201
6202 ImportReference impt;
6203 int length;
6204 char[][] tokens =
6205 new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
6206 this.identifierPtr -= length;
6207 long[] positions = new long[length];
6208 System.arraycopy(this.identifierStack, ++this.identifierPtr, tokens, 0, length);
6209 System.arraycopy(
6210 this.identifierPositionStack,
6211 this.identifierPtr--,
6212 positions,
6213 0,
6214 length);
6215
6216 impt = new ImportReference(tokens, positions, false, ClassFileConstants.AccDefault);
6217 this.compilationUnit.currentPackage = impt;
6218
6219 if (this.currentToken == TokenNameSEMICOLON){
6220 impt.declarationSourceEnd = this.scanner.currentPosition - 1;
6221 } else {
6222 impt.declarationSourceEnd = impt.sourceEnd;
6223 }
6224 impt.declarationEnd = impt.declarationSourceEnd;
6225 //this.endPosition is just before the ;
6226 impt.declarationSourceStart = this.intStack[this.intPtr--];
6227
6228 // get possible comment source start
6229 if(this.javadoc != null) {
6230 impt.declarationSourceStart = this.javadoc.sourceStart;
6231 }
6232
6233 // recovery
6234 if (this.currentElement != null){
6235 this.lastCheckPoint = impt.declarationSourceEnd+1;
6236 this.restartRecovery = true; // used to avoid branching back into the regular automaton
6237 }
6238 }
consumePackageDeclarationNameWithModifiers()6239