KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > util > CommentRecorderParser


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.core.util;
12
13 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
14 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
15 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
16 import org.eclipse.jdt.internal.compiler.parser.Parser;
17 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
18 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
19
20 /**
21  * Internal parser used for parsing source to create DOM AST nodes.
22  *
23  * @since 3.0
24  */

25 public class CommentRecorderParser extends Parser {
26     
27     // support for comments
28
int[] commentStops = new int[10];
29     int[] commentStarts = new int[10];
30     int commentPtr = -1; // no comment test with commentPtr value -1
31
protected final static int CommentIncrement = 100;
32
33     /**
34      * @param problemReporter
35      * @param optimizeStringLiterals
36      */

37     public CommentRecorderParser(ProblemReporter problemReporter, boolean optimizeStringLiterals) {
38         super(problemReporter, optimizeStringLiterals);
39     }
40
41     // old javadoc style check which doesn't include all leading comments into declaration
42
// for backward compatibility with 2.1 DOM
43
public void checkComment() {
44
45         // discard obsolete comments while inside methods or fields initializer (see bug 74369)
46
if (!(this.diet && this.dietInt==0) && this.scanner.commentPtr >= 0) {
47             flushCommentsDefinedPriorTo(this.endStatementPosition);
48         }
49         boolean deprecated = false;
50         boolean checkDeprecated = false;
51         int lastCommentIndex = -1;
52         
53         //since jdk1.2 look only in the last java doc comment...
54
nextComment : for (lastCommentIndex = this.scanner.commentPtr; lastCommentIndex >= 0; lastCommentIndex--){
55             //look for @deprecated into the first javadoc comment preceeding the declaration
56
int commentSourceStart = this.scanner.commentStarts[lastCommentIndex];
57             // javadoc only (non javadoc comment have negative end positions.)
58
if ((commentSourceStart < 0) ||
59                 (this.modifiersSourceStart != -1 && this.modifiersSourceStart < commentSourceStart) ||
60                 (this.scanner.commentStops[lastCommentIndex] < 0))
61             {
62                 continue nextComment;
63             }
64             checkDeprecated = true;
65             int commentSourceEnd = this.scanner.commentStops[lastCommentIndex] - 1; //stop is one over
66

67             // do not report problem before last parsed comment while recovering code...
68
this.javadocParser.reportProblems = this.currentElement == null || commentSourceEnd > this.lastJavadocEnd;
69             deprecated = this.javadocParser.checkDeprecation(lastCommentIndex);
70             this.javadoc = this.javadocParser.docComment;
71             break nextComment;
72         }
73         if (deprecated) {
74             checkAndSetModifiers(ClassFileConstants.AccDeprecated);
75         }
76         // modify the modifier source start to point at the first comment
77
if (lastCommentIndex >= 0 && checkDeprecated) {
78             this.modifiersSourceStart = this.scanner.commentStarts[lastCommentIndex];
79             if (this.modifiersSourceStart < 0) {
80                 this.modifiersSourceStart = -this.modifiersSourceStart;
81             }
82         }
83     }
84
85     /* (non-Javadoc)
86      * @see org.eclipse.jdt.internal.compiler.parser.Parser#consumeClassHeader()
87      */

88     protected void consumeClassHeader() {
89         pushOnCommentsStack(0, this.scanner.commentPtr);
90         super.consumeClassHeader();
91     }
92     /* (non-Javadoc)
93      * @see org.eclipse.jdt.internal.compiler.parser.Parser#consumeEmptyTypeDeclaration()
94      */

95     protected void consumeEmptyTypeDeclaration() {
96         pushOnCommentsStack(0, this.scanner.commentPtr);
97         super.consumeEmptyTypeDeclaration();
98     }
99     /* (non-Javadoc)
100      * @see org.eclipse.jdt.internal.compiler.parser.Parser#consumeInterfaceHeader()
101      */

102     protected void consumeInterfaceHeader() {
103         pushOnCommentsStack(0, this.scanner.commentPtr);
104         super.consumeInterfaceHeader();
105     }
106
107     /**
108      * Insure that start position is always positive.
109      * @see org.eclipse.jdt.internal.compiler.parser.Parser#containsComment(int, int)
110      */

111     public boolean containsComment(int sourceStart, int sourceEnd) {
112         int iComment = this.scanner.commentPtr;
113         for (; iComment >= 0; iComment--) {
114             int commentStart = this.scanner.commentStarts[iComment];
115             if (commentStart < 0) {
116                 commentStart = -commentStart;
117             }
118             // ignore comments before start
119
if (commentStart < sourceStart) continue;
120             // ignore comments after end
121
if (commentStart > sourceEnd) continue;
122             return true;
123         }
124         return false;
125     }
126
127     /* (non-Javadoc)
128      * @see org.eclipse.jdt.internal.compiler.parser.Parser#endParse(int)
129      */

130     protected CompilationUnitDeclaration endParse(int act) {
131         CompilationUnitDeclaration unit = super.endParse(act);
132         if (unit.comments == null) {
133             pushOnCommentsStack(0, this.scanner.commentPtr);
134             unit.comments = getCommentsPositions();
135         }
136         return unit;
137     }
138
139     /* (non-Javadoc)
140      * Save all source comments currently stored before flushing them.
141      * @see org.eclipse.jdt.internal.compiler.parser.Parser#flushCommentsDefinedPriorTo(int)
142      */

143     public int flushCommentsDefinedPriorTo(int position) {
144
145         int lastCommentIndex = this.scanner.commentPtr;
146         if (lastCommentIndex < 0) return position; // no comment
147

148         // compute the index of the first obsolete comment
149
int index = lastCommentIndex;
150         int validCount = 0;
151         while (index >= 0){
152             int commentEnd = this.scanner.commentStops[index];
153             if (commentEnd < 0) commentEnd = -commentEnd; // negative end position for non-javadoc comments
154
if (commentEnd <= position){
155                 break;
156             }
157             index--;
158             validCount++;
159         }
160         // if the source at <position> is immediately followed by a line comment, then
161
// flush this comment and shift <position> to the comment end.
162
if (validCount > 0){
163             int immediateCommentEnd = 0;
164             while (index<lastCommentIndex && (immediateCommentEnd = -this.scanner.commentStops[index+1]) > 0){ // only tolerating non-javadoc comments (non-javadoc comment end positions are negative)
165
// is there any line break until the end of the immediate comment ? (thus only tolerating line comment)
166
immediateCommentEnd--; // comment end in one char too far
167
if (org.eclipse.jdt.internal.compiler.util.Util.getLineNumber(position, this.scanner.lineEnds, 0, this.scanner.linePtr)
168                         != org.eclipse.jdt.internal.compiler.util.Util.getLineNumber(immediateCommentEnd, this.scanner.lineEnds, 0, this.scanner.linePtr)) break;
169                 position = immediateCommentEnd;
170                 validCount--; // flush this comment
171
index++;
172             }
173         }
174     
175         if (index < 0) return position; // no obsolete comment
176
pushOnCommentsStack(0, index); // store comment before flushing them
177

178         switch (validCount) {
179             case 0:
180                 // do nothing
181
break;
182             // move valid comment infos, overriding obsolete comment infos
183
case 2:
184                 this.scanner.commentStarts[0] = this.scanner.commentStarts[index+1];
185                 this.scanner.commentStops[0] = this.scanner.commentStops[index+1];
186                 this.scanner.commentTagStarts[0] = this.scanner.commentTagStarts[index+1];
187                 this.scanner.commentStarts[1] = this.scanner.commentStarts[index+2];
188                 this.scanner.commentStops[1] = this.scanner.commentStops[index+2];
189                 this.scanner.commentTagStarts[1] = this.scanner.commentTagStarts[index+2];
190                 break;
191             case 1:
192                 this.scanner.commentStarts[0] = this.scanner.commentStarts[index+1];
193                 this.scanner.commentStops[0] = this.scanner.commentStops[index+1];
194                 this.scanner.commentTagStarts[0] = this.scanner.commentTagStarts[index+1];
195                 break;
196             default:
197                 System.arraycopy(this.scanner.commentStarts, index + 1, this.scanner.commentStarts, 0, validCount);
198                 System.arraycopy(this.scanner.commentStops, index + 1, this.scanner.commentStops, 0, validCount);
199                 System.arraycopy(this.scanner.commentTagStarts, index + 1, this.scanner.commentTagStarts, 0, validCount);
200         }
201         this.scanner.commentPtr = validCount - 1;
202         return position;
203     }
204
205     /*
206      * Build a n*2 matrix of comments positions.
207      * For each position, 0 is for start position and 1 for end position of the comment.
208      */

209     public int[][] getCommentsPositions() {
210         int[][] positions = new int[this.commentPtr+1][2];
211         for (int i = 0, max = this.commentPtr; i <= max; i++){
212             positions[i][0] = this.commentStarts[i];
213             positions[i][1] = this.commentStops[i];
214         }
215         return positions;
216     }
217
218     /* (non-Javadoc)
219      * @see org.eclipse.jdt.internal.compiler.parser.Parser#initialize()
220      */

221     public void initialize(boolean initializeNLS) {
222         super.initialize(initializeNLS);
223         this.commentPtr = -1;
224     }
225     /* (non-Javadoc)
226      * @see org.eclipse.jdt.internal.compiler.parser.Parser#initialize()
227      */

228     public void initialize() {
229         super.initialize();
230         this.commentPtr = -1;
231     }
232     
233     /* (non-Javadoc)
234      * Create and store a specific comment recorder scanner.
235      * @see org.eclipse.jdt.internal.compiler.parser.Parser#initializeScanner()
236      */

237     public void initializeScanner() {
238         this.scanner = new CommentRecorderScanner(
239                 false /*comment*/,
240                 false /*whitespace*/,
241                 this.options.getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /*nls*/,
242                 this.options.sourceLevel /*sourceLevel*/,
243                 this.options.taskTags/*taskTags*/,
244                 this.options.taskPriorites/*taskPriorities*/,
245                 this.options.isTaskCaseSensitive/*taskCaseSensitive*/);
246     }
247
248     /*
249      * Push all stored comments in stack.
250      */

251     private void pushOnCommentsStack(int start, int end) {
252     
253         for (int i=start; i<=end; i++) {
254             // First see if comment hasn't been already stored
255
int scannerStart = this.scanner.commentStarts[i]<0 ? -this.scanner.commentStarts[i] : this.scanner.commentStarts[i];
256             int commentStart = this.commentPtr == -1 ? -1 : (this.commentStarts[this.commentPtr]<0 ? -this.commentStarts[this.commentPtr] : this.commentStarts[this.commentPtr]);
257             if (commentStart == -1 || scannerStart > commentStart) {
258                 int stackLength = this.commentStarts.length;
259                 if (++this.commentPtr >= stackLength) {
260                     System.arraycopy(
261                         this.commentStarts, 0,
262                         this.commentStarts = new int[stackLength + CommentIncrement], 0,
263                         stackLength);
264                     System.arraycopy(
265                         this.commentStops, 0,
266                         this.commentStops = new int[stackLength + CommentIncrement], 0,
267                         stackLength);
268                 }
269                 this.commentStarts[this.commentPtr] = this.scanner.commentStarts[i];
270                 this.commentStops[this.commentPtr] = this.scanner.commentStops[i];
271             }
272         }
273     }
274     /* (non-Javadoc)
275      * Save all source comments currently stored before flushing them.
276      * @see org.eclipse.jdt.internal.compiler.parser.Parser#resetModifiers()
277      */

278     protected void resetModifiers() {
279         pushOnCommentsStack(0, this.scanner.commentPtr);
280         super.resetModifiers();
281     }
282 }
283
Popular Tags