Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/puppycrawl/tools/checkstyle/checks/usage/transmogrify/SymTabAST.java


1   
2   // Transmogrify License
3   // 
4   // Copyright (c) 2001, ThoughtWorks, Inc.
5   // All rights reserved.
6   // Redistribution and use in source and binary forms, with or without
7   // modification, are permitted provided that the following conditions
8   // are met:
9   // - Redistributions of source code must retain the above copyright notice,
10  //   this list of conditions and the following disclaimer.
11  // - Redistributions in binary form must reproduce the above copyright
12  // notice, this list of conditions and the following disclaimer in the
13  // documentation and/or other materials provided with the distribution.
14  // Neither the name of the ThoughtWorks, Inc. nor the names of its
15  // contributors may be used to endorse or promote products derived from this
16  // software without specific prior written permission.
17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21  // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24  // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27  // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  
29  package com.puppycrawl.tools.checkstyle.checks.usage.transmogrify;
30  
31  import java.io.File;
32  
33  import antlr.collections.AST;
34  
35  import com.puppycrawl.tools.checkstyle.api.DetailAST;
36  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
37  
38  
39  
40  /**
41   * an extension of <code>antlr.CommonAST</code> that includes
42   * extra information about the AST's location.  This information
43   * is the file and line number where the AST was created.
44   *
45   * To use this AST node in your tree structure, assuming your
46   * antlr.TreeParser is called parser, use
47   *
48   * parser.setASTNOdeCLass(SymTabAST.class.getName());
49   *
50   * make sure you also call setTokenObjectClass for the lexer as well
51   *
52   *
53   * @see SymTabToken
54   */
55  //TODO: Should be an adapter of DetailAST
56  
57  public class SymTabAST
58      extends antlr.CommonASTWithHiddenTokens
59  {
60      private Scope _scope;
61      private IDefinition _definition = null;
62      private boolean _isMeaningful = true;
63  
64      private File _file;
65      private int _line;
66      private int _column;
67  
68  //  parent is not used by Checkstyle
69  //    private SymTabAST parent;
70  
71      private Span _span;
72  
73      /** original syntax tree node */
74      private DetailAST detailNode;
75      
76  //    /**
77  //     * gets parent of this node
78  //     * @return <code>SymTabAST</code>
79  //     */
80  //    public SymTabAST getParent() {
81  //        return parent;
82  //    }
83  
84  //    /**
85  //     * gets previous sibling of this node
86  //     * @return <code>SymTabAST</code>
87  //     */
88  //    public SymTabAST getPreviousSibling() {
89  //        return prevSibling;
90  //    }
91  
92      /**
93       * sets parent of this node
94       * @param parent
95       * @return <code>void</code>
96       */
97      public void setParent(SymTabAST parent) {
98  //parent is not used by Checkstyle
99  //        this.parent = parent;
100     }
101 
102     /**
103      * gets the scope of this node
104      * @return <code>Scope</code>
105      */
106     public Scope getScope() {
107         return _scope;
108     }
109 
110     /**
111      * sets the scope of this node
112      * @param scope
113      * @return <code>void</code>
114      */
115     public void setScope(Scope scope) {
116         _scope = scope;
117     }
118 
119     /**
120      * sets <code>Definition</code> for this node
121      * @param definition
122      * @param scope
123      * @return <code>void</code>
124      * @see #setDefinition(IDefinition, Scope, boolean)
125      */
126     public void setDefinition(IDefinition definition, Scope scope) {
127         setDefinition(definition, scope, true);
128     }
129 
130     /**
131      * sets <code>Definition</code> for this node and adds <code>Reference</code>
132      * to the <code>_definition</code> and <code>scope</code>
133      * @param definition
134      * @param scope
135      * @param createReference
136      * @return <code>void</code>
137      * @see net.sourceforge.transmogrify.symtab.Reference
138      */
139     public void setDefinition(
140         IDefinition definition,
141         Scope scope,
142         boolean createReference) {
143         _definition = definition;
144         Reference reference = new Reference(this);
145         if (scope != null) {
146             scope.addReferenceInScope(reference);
147         }
148 
149         if (definition.isSourced() && createReference) {
150             _definition.addReference(reference);
151         }
152     }
153 
154     /**
155      * gets <code>_definitin</code>
156      * @return <code>IDefinition</code>
157      */
158     public IDefinition getDefinition() {
159         return _definition;
160     }
161 
162     /**
163      * tests if this node is meaningful or should be ignored
164      * @return <code>boolean</code>
165      */
166     public boolean isMeaningful() {
167         return _isMeaningful;
168     }
169 
170     /**
171      * sets <code>_isMeaningful</code> member
172      * @param isMeaningful
173      * @return <code>void</code>
174      */
175     public void setMeaningfulness(boolean isMeaningful) {
176         _isMeaningful = isMeaningful;
177     }
178 
179     /**
180      * sets meaningfulness for this node and its children
181      * @return <code>void</code>
182      * @see #setMeaningfulness(boolean)
183      */
184     public void ignoreChildren() {
185         if (getType() == TokenTypes.IDENT) {
186             setMeaningfulness(false);
187         }
188         SymTabAST child = (SymTabAST) getFirstChild();
189         while (child != null) {
190             child.ignoreChildren();
191             child = (SymTabAST) child.getNextSibling();
192         }
193     }
194 
195     /**
196      * sets file where this node belong to
197      * @param file
198      * @return <code>void</code>
199      */
200     public void setFile(File file) {
201         _file = file;
202     }
203 
204     /**
205      * finishes process for adding node to its parent
206      * @param file file where this node belongs to
207      * @param parent parent of this node
208      * @param previousSibling previous sibling of this node
209      * @return <code>Span</code> the span of this node
210      * @see #setFile(File)
211      * @see #setParent(SymTabAST)
212      * @see #setPreviousSibling(SymTabAST)
213      * @see #finishChildren(File)
214      * @see #setSpan(Span)
215      */
216     public Span finishDefinition(
217         File file,
218         SymTabAST parent) {
219         setFile(file);
220         setParent(parent);
221 
222         Span result = finishChildren(file);
223 
224         if (getLineNo() != 0) {
225             result.compose(
226                 new Span(
227                     getLineNo(),
228                     getColumnNo(),
229                     getLineNo(),
230                     getColumnNo()
231                         + ((getText() == null) ? 0 : getText().length() - 1)));
232         }
233 
234         setSpan(result);
235         return result;
236     }
237 
238     /**
239      * finishes children of this node definition process
240      * @param file file where this node belongs to
241      * @return <code>Span</code>
242      * @see #finishDefinition(File, SymTabAST, SymTabAST)
243      */
244     public Span finishChildren(File file) {
245         Span result = null;
246         SymTabAST previousSibling = null;
247         SymTabAST current = (SymTabAST) getFirstChild();
248 
249         if (current == null) {
250             result = getSpan();
251         }
252         else {
253             while (current != null) {
254                 Span childSpan =
255                     current.finishDefinition(file, this);
256 
257                 if (childSpan != null) {
258                     if (result == null) {
259                         result = new Span(childSpan);
260                     }
261                     else {
262                         result.compose(childSpan);
263                     }
264                 }
265 
266                 SymTabAST temp = current;
267                 current = (SymTabAST) current.getNextSibling();
268                 previousSibling = temp;
269             }
270         }
271 
272         return result;
273     }
274 
275     /**
276      * gets file where this node belongs to
277      * @return <code>File</code>
278      */
279     public File getFile() {
280         return _file;
281     }
282 
283     /**
284      * sets the line where this node reside
285      * @return <code>void</code>
286      */
287     public void setLine(int line) {
288         _line = line;
289     }
290 
291     /**
292      * gets the line where this node reside
293      * @return <code>int</code>
294      */
295     public int getLineNo() {
296         return _line;
297     }
298 
299     /**
300      * sets the column where this node reside
301      * @param column
302      */
303     public void setColumn(int column) {
304         _column = column;
305     }
306 
307     /**
308      * gets the column where this node reside
309      * @return <code>int</code>
310      */
311     public int getColumnNo() {
312         return _column;
313     }
314 
315     /**
316      * gets the definition name of this node
317      * @return <code>String</code>
318      * @see net.sourceforge.transmogrify.symtab.IDefinition
319      */
320     public String getName() {
321         String result = null;
322         if (_definition != null) {
323             result = _definition.getName();
324         }
325 
326         return result;
327     }
328 
329     /**
330      * makes a new copy of the current <code>SymTabAST</code>.  Uses the
331      * initialize(AST t) method to copy properties for each cloned node.
332      *
333      * @return <code>SymTabAST</code> a full tree copy of the current tree
334      */
335     private SymTabAST treeCopy()
336     {
337         SymTabAST copyOfThis = SymTabASTFactory.create(getType(), getText());
338         copyOfThis.initialize(this);
339 
340         if (getFirstChild() != null) {
341             copyOfThis.setFirstChild(((SymTabAST) getFirstChild()).treeCopy());
342         }
343 
344         if (getNextSibling() != null) {
345             copyOfThis.setNextSibling(
346                 ((SymTabAST) getNextSibling()).treeCopy());
347         }
348 
349         return copyOfThis;
350     }
351 
352     /**
353      * prints the line, column and file for this node for debugging purpose
354      * @return <code>String</code>
355      */
356     public String toString() {
357         //StringBuffer resultBuffer = new StringBuffer(super.toString());
358         StringBuffer resultBuffer = new StringBuffer(prefixString(true));
359         resultBuffer.append("[" + getLineNo() + "," + getColumnNo() + "]");
360         //if ( getSpan() != null ) {
361         //  resultBuffer.append( " spans " + getSpan() );
362         //}
363         resultBuffer.append(" in " + getFile());
364         //resultBuffer.append(" type: " + getType());
365         return resultBuffer.toString();
366     }
367 
368     public String prefixString(boolean verboseStringConversion) {
369         StringBuffer b = new StringBuffer();
370 
371         try {
372             final String name = TokenTypes.getTokenName(getType());
373             // if verbose and type name not same as text (keyword probably)
374             if (verboseStringConversion && !getText().equalsIgnoreCase(name)) {
375                 b.append('[');
376                 b.append(getText());
377                 b.append(",<");
378                 b.append(name);
379                 b.append(">]");
380                 return b.toString();
381             }
382         }
383         catch (Exception ex) {
384             ;
385         }
386         return getText();
387     }
388 
389     /**
390      * gets <code>Span</code> of this node
391      * @return <code>Span</code>
392      */
393     public Span getSpan() {
394         if ((_span == null)) {
395             int endColumn = getColumnNo() + 1;
396             final String text = getText();
397             if (text != null) {
398                 endColumn += text.length() - 1;
399             }
400             _span = new Span(getLineNo(), getColumnNo() + 1, getLineNo(), endColumn);
401         }
402         return _span;
403     }
404 
405     /**
406      * sets <code>Span</code> for this node
407      * @param span
408      * @return <code>void</code>
409      */
410     public void setSpan(Span span) {
411         _span = span;
412     }
413 
414 // not used by Checkstyle
415 //    /**
416 //     * tests if this node is inside the span
417 //     * @param line
418 //     * @param column
419 //     * @return <code>boolean</code> <code>true</code> if this node is within the span
420 //     *                              <code>false</code> otherwise
421 //     */
422 //    public boolean contains(int line, int column) {
423 //        return getSpan().contains(line, column);
424 //    }
425 
426     /**
427      * gets enclosing node for this node based on line and column
428      * @param line
429      * @param column
430      * @return <code>SymTabAST</code>
431      * @see #getSpan()
432      */
433     public SymTabAST getEnclosingNode(int line, int column) {
434         SymTabAST result = null;
435 
436         if ((getSpan() != null) && (getSpan().contains(line, column))) {
437             SymTabAST child = (SymTabAST) getFirstChild();
438             while (child != null && result == null) {
439                 result = child.getEnclosingNode(line, column);
440                 child = (SymTabAST) child.getNextSibling();
441             }
442 
443             // if none of the children contain it, I'm the best node
444             if (result == null) {
445                 result = this;
446             }
447 
448         }
449         return result;
450     }
451 
452     public AST getFirstChild()
453     {
454         if (super.getFirstChild() == null) {
455             DetailAST childDetailAST = null;
456             final DetailAST detailAST = getDetailNode();
457             if (detailAST != null) {
458                 childDetailAST = (DetailAST) detailAST.getFirstChild();
459                 if (childDetailAST != null) {
460                     final SymTabAST child =
461                         SymTabASTFactory.create(childDetailAST);
462                     setFirstChild(child);
463                     child.setParent(this);
464                     child.setFile(getFile());
465                 }
466             }
467         }
468         return super.getFirstChild(); 
469     }
470     
471     public AST getNextSibling()
472     {
473         if (super.getNextSibling() == null) {
474             DetailAST siblingDetailAST = null;
475             final DetailAST detailAST = getDetailNode();           
476             if (detailAST != null) {
477                 siblingDetailAST = (DetailAST) detailAST.getNextSibling();
478                 if (siblingDetailAST != null) {
479                     final SymTabAST sibling =
480                     SymTabASTFactory.create(siblingDetailAST);
481                     setNextSibling(sibling);
482 //                    sibling.setParent(this.getParent());
483                     sibling.setFile(getFile());
484                 }
485             }
486         }
487         return super.getNextSibling(); 
488     }
489 
490     
491     /**
492      * initialized this node with input node
493      * @param aAST the node to initialize from. Must be a
494      * <code>DetailAST</code> object.
495      */
496     public void initialize(AST aAST)
497     {
498         if (aAST != null) {
499             super.initialize(aAST);
500             final DetailAST detailAST = (DetailAST) aAST;
501             setDetailNode(detailAST);
502             _column = detailAST.getColumnNo() + 1;
503             _line = detailAST.getLineNo();
504         } 
505     }
506         
507     /**
508      * Gets first occurence of the child node with a certain type
509      * @param type
510      * @return <code>SymTabAST</code>
511      * @see #getType()
512      */
513     public SymTabAST findFirstToken(int type) {
514         SymTabAST result = null;
515 
516         AST sibling = getFirstChild();
517         while (sibling != null) {
518             if (sibling.getType() == type) {
519                 result = (SymTabAST) sibling;
520                 break;
521             }
522             sibling = sibling.getNextSibling();
523         }
524 
525         return result;
526     }
527 
528 //  not used by Checkstyle
529 //    /**
530 //     * adds a node to the last position of this node children
531 //     * @param child
532 //     * @return <code>void</code>
533 //     */
534 //    public void addChild(SymTabAST child)
535 //    {
536 //        SymTabAST lastChild = (SymTabAST) getFirstChild();
537 //        if (lastChild == null) {
538 //            setFirstChild(child);
539 //            child.setParent(this);
540 //            child.setNextSibling(null);
541 //        }
542 //        else {
543 //            while (lastChild.getNextSibling() != null) {
544 //                lastChild = (SymTabAST) lastChild.getNextSibling();
545 //            }
546 //            lastChild.setNextSibling(child);
547 //            child.setNextSibling(null);
548 //            child.setParent(this);
549 //        }
550 //    }
551 
552     /**
553      * Gets Iterator for this node
554      * @return <code>SymTabASTIterator</code>
555      */
556     public SymTabASTIterator getChildren()
557     {
558         return new SymTabASTIterator(this);
559     }
560 
561     /**
562      * Returns the DetailAST associated with this node.
563      * @return the DetailAST associated with this node.
564      */
565     public DetailAST getDetailNode()
566     {
567         return detailNode;
568     }
569 
570     /**
571      * Sets the DetailAST associated with this node.
572      * @param aDetailAST the DetailAST associated with this node.
573      */
574     public void setDetailNode(DetailAST aDetailAST)
575     {
576         detailNode = aDetailAST;
577         ASTManager.getInstance().put(aDetailAST, this);
578     }
579 
580 }