1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core.util;
13 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
14 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
15 import net.sourceforge.phpdt.internal.compiler.parser.UnitParser;
16 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
17 import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
20 * Internal parser used for parsing source to create DOM AST nodes.
24 public class CommentRecorderParser extends UnitParser {
26 // support for comments
27 int[] commentStops = new int[10];
29 int[] commentStarts = new int[10];
31 int commentPtr = -1; // no comment test with commentPtr value -1
33 protected final static int CommentIncrement = 100;
36 * @param problemReporter
37 * @param optimizeStringLiterals
39 public CommentRecorderParser(ProblemReporter problemReporter) { // , boolean
40 // optimizeStringLiterals)
42 super(problemReporter); // , optimizeStringLiterals);
45 // old javadoc style check which doesn't include all leading comments into
47 // for backward compatibility with 2.1 DOM
48 // public void checkComment() {
50 // if (this.currentElement != null && this.scanner.commentPtr >= 0) {
51 // flushCommentsDefinedPriorTo(this.endStatementPosition); // discard
54 // boolean deprecated = false;
55 // boolean checkDeprecated = false;
56 // int lastCommentIndex = -1;
60 // //since jdk1.2 look only in the last java doc comment...
61 // nextComment : for (lastCommentIndex = this.scanner.commentPtr;
62 // lastCommentIndex >= 0; lastCommentIndex--){
63 // //look for @deprecated into the first javadoc comment preceeding the
65 // int commentSourceStart = this.scanner.commentStarts[lastCommentIndex];
66 // // javadoc only (non javadoc comment have negative end positions.)
67 // if ((commentSourceStart < 0) ||
68 // (this.modifiersSourceStart != -1 && this.modifiersSourceStart <
69 // commentSourceStart) ||
70 // (this.scanner.commentStops[lastCommentIndex] < 0))
72 // continue nextComment;
74 // checkDeprecated = true;
75 // int commentSourceEnd = this.scanner.commentStops[lastCommentIndex] - 1;
78 // deprecated = this.javadocParser.checkDeprecation(commentSourceStart,
80 // this.javadoc = this.javadocParser.docComment;
84 // checkAndSetModifiers(AccDeprecated);
86 // // modify the modifier source start to point at the first comment
87 // if (lastCommentIndex >= 0 && checkDeprecated) {
88 // this.modifiersSourceStart = this.scanner.commentStarts[lastCommentIndex];
89 // if (this.modifiersSourceStart < 0) {
90 // this.modifiersSourceStart = -this.modifiersSourceStart;
98 // net.sourceforge.phpdt.internal.compiler.parser.Parser#consumeClassHeader()
100 // protected void consumeClassHeader() {
101 // pushOnCommentsStack(0, this.scanner.commentPtr);
102 // super.consumeClassHeader();
106 // net.sourceforge.phpdt.internal.compiler.parser.Parser#consumeEmptyClassMemberDeclaration()
108 // protected void consumeEmptyClassMemberDeclaration() {
109 // pushOnCommentsStack(0, this.scanner.commentPtr);
110 // super.consumeEmptyClassMemberDeclaration();
114 // net.sourceforge.phpdt.internal.compiler.parser.Parser#consumeEmptyTypeDeclaration()
116 // protected void consumeEmptyTypeDeclaration() {
117 // pushOnCommentsStack(0, this.scanner.commentPtr);
118 // super.consumeEmptyTypeDeclaration();
122 // net.sourceforge.phpdt.internal.compiler.parser.Parser#consumeInterfaceHeader()
124 // protected void consumeInterfaceHeader() {
125 // pushOnCommentsStack(0, this.scanner.commentPtr);
126 // super.consumeInterfaceHeader();
130 * Insure that start position is always positive.
132 * @see net.sourceforge.phpdt.internal.compiler.parser.Parser#containsComment(int,
135 public boolean containsComment(int sourceStart, int sourceEnd) {
136 int iComment = this.scanner.commentPtr;
137 for (; iComment >= 0; iComment--) {
138 int commentStart = this.scanner.commentStarts[iComment];
139 if (commentStart < 0) {
140 commentStart = -commentStart;
142 // ignore comments before start
143 if (commentStart < sourceStart)
145 // ignore comments after end
146 if (commentStart > sourceEnd)
156 * @see net.sourceforge.phpdt.internal.compiler.parser.Parser#endParse(int)
158 protected CompilationUnitDeclaration endParse(int act) {
159 CompilationUnitDeclaration unit = super.endParse(act);
160 if (unit.comments == null) {
161 pushOnCommentsStack(0, this.scanner.commentPtr);
162 unit.comments = getCommentsPositions();
168 * (non-Javadoc) Save all source comments currently stored before flushing
171 * @see net.sourceforge.phpdt.internal.compiler.parser.Parser#flushCommentsDefinedPriorTo(int)
173 public int flushCommentsDefinedPriorTo(int position) {
175 int lastCommentIndex = this.scanner.commentPtr;
176 if (lastCommentIndex < 0)
177 return position; // no comment
179 // compute the index of the first obsolete comment
180 int index = lastCommentIndex;
183 int commentEnd = this.scanner.commentStops[index];
185 commentEnd = -commentEnd; // negative end position for
186 // non-javadoc comments
187 if (commentEnd <= position) {
193 // if the source at <position> is immediately followed by a line
195 // flush this comment and shift <position> to the comment end.
196 if (validCount > 0) {
197 int immediateCommentEnd = 0;
198 while (index < lastCommentIndex
199 && (immediateCommentEnd = -this.scanner.commentStops[index + 1]) > 0) { // only
209 // is there any line break until the end of the immediate
210 // comment ? (thus only tolerating line comment)
211 immediateCommentEnd--; // comment end in one char too far
212 if (this.scanner.getLineNumber(position) != this.scanner
213 .getLineNumber(immediateCommentEnd))
215 position = immediateCommentEnd;
216 validCount--; // flush this comment
222 return position; // no obsolete comment
223 pushOnCommentsStack(0, index); // store comment before flushing them
225 if (validCount > 0) { // move valid comment infos, overriding obsolete
227 System.arraycopy(this.scanner.commentStarts, index + 1,
228 this.scanner.commentStarts, 0, validCount);
229 System.arraycopy(this.scanner.commentStops, index + 1,
230 this.scanner.commentStops, 0, validCount);
232 this.scanner.commentPtr = validCount - 1;
237 * Build a n*2 matrix of comments positions. For each position, 0 is for
238 * start position and 1 for end position of the comment.
240 public int[][] getCommentsPositions() {
241 int[][] positions = new int[this.commentPtr + 1][2];
242 for (int i = 0, max = this.commentPtr; i <= max; i++) {
243 positions[i][0] = this.commentStarts[i];
244 positions[i][1] = this.commentStops[i];
252 * @see net.sourceforge.phpdt.internal.compiler.parser.Parser#initialize()
254 public void initialize(boolean phpMode) {
255 super.initialize(phpMode);
256 this.commentPtr = -1;
260 * (non-Javadoc) Create and store a specific comment recorder scanner.
262 * @see net.sourceforge.phpdt.internal.compiler.parser.Parser#initializeScanner()
264 public void initializeScanner() {
265 this.scanner = new CommentRecorderScanner(
267 false /* whitespace */,
268 this.options.getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /* nls */,
269 // this.options.sourceLevel /*sourceLevel*/,
270 this.options.taskTags/* taskTags */, this.options.taskPriorites);/* taskPriorities */
271 // this.options.isTaskCaseSensitive/*taskCaseSensitive*/);
275 * Push all stored comments in stack.
277 private void pushOnCommentsStack(int start, int end) {
279 for (int i = start; i <= end; i++) {
280 // First see if comment hasn't been already stored
281 int scannerStart = this.scanner.commentStarts[i] < 0 ? -this.scanner.commentStarts[i]
282 : this.scanner.commentStarts[i];
283 int commentStart = this.commentPtr == -1 ? -1
284 : (this.commentStarts[this.commentPtr] < 0 ? -this.commentStarts[this.commentPtr]
285 : this.commentStarts[this.commentPtr]);
286 if (commentStart == -1 || scannerStart > commentStart) {
289 this.commentStarts[this.commentPtr] = this.scanner.commentStarts[i];
290 this.commentStops[this.commentPtr] = this.scanner.commentStops[i];
291 } catch (IndexOutOfBoundsException e) {
292 // this.commentPtr is still correct
293 int oldStackLength = this.commentStarts.length;
294 int oldCommentStarts[] = this.commentStarts;
295 this.commentStarts = new int[oldStackLength
297 System.arraycopy(oldCommentStarts, 0, this.commentStarts,
299 this.commentStarts[this.commentPtr] = this.scanner.commentStarts[i];
300 int oldCommentStops[] = this.commentStops;
301 this.commentStops = new int[oldStackLength
303 System.arraycopy(oldCommentStops, 0, this.commentStops, 0,
305 this.commentStops[this.commentPtr] = this.scanner.commentStops[i];
312 * (non-Javadoc) Save all source comments currently stored before flushing
315 * @see net.sourceforge.phpdt.internal.compiler.parser.Parser#resetModifiers()
317 protected void resetModifiers() {
318 pushOnCommentsStack(0, this.scanner.commentPtr);
319 super.resetModifiers();