KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > puppycrawl > tools > checkstyle > checks > usage > transmogrify > Resolver


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
32
33 import java.util.Vector JavaDoc;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogConfigurationException;
37 import org.apache.commons.logging.LogFactory;
38
39 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
40
41 /**
42  * The resolver is responsible for traversing all the various
43  * definitions in a symbol table and resolving references in them.
44  *
45  * @see SymbolTable
46  */

47
48 public class Resolver extends DefinitionTraverser {
49
50     /** true if the log factory has been initialized */
51     private boolean mInitialized = false;
52
53     /** Factory for creating org.apache.commons.logging.Log instances */
54     private LogFactory mLogFactory;
55
56     /**
57      * constructor with <code>SymbolTable</code> to be resolved
58      */

59     public Resolver(SymbolTable symbolTable) {
60         super(symbolTable);
61
62         try {
63             mLogFactory = LogFactory.getFactory();
64         }
65         catch (LogConfigurationException e) {
66             System.out.println("log configuration exception" + e);
67         }
68         mInitialized = true;
69
70     }
71
72     /**
73      * resolves the symbol table
74      * @return <code>void</code>
75      * @see #traverse()
76      */

77     public void resolve() {
78         traverse();
79     }
80
81     protected void handleSList(SymTabAST node, Scope scope) {
82         SymTabASTIterator iterator = node.getChildren();
83         while (iterator.hasNext()) {
84             SymTabAST current = iterator.nextChild();
85             resolveExpression(current, scope, null, true);
86         }
87     }
88
89     protected void handleAnonymousInnerClass(AnonymousInnerClass innerClass) {
90         SymTabAST objblock = innerClass.getTreeNode();
91         SymTabAST expression = (SymTabAST) objblock.getFirstChild();
92         while (expression != null) {
93             resolveExpression(expression, innerClass, null, true);
94             expression = (SymTabAST) expression.getNextSibling();
95         }
96     }
97
98     /**
99      * processes a <code>ClassDef</code> and resolves references in it
100      *
101      * @param classDef the <code>ClassDef</code> to process
102      */

103     protected void handleClass(ClassDef classDef) {
104         SymTabAST node = classDef.getTreeNode();
105
106         if (node != null) {
107             SymTabAST nameNode = node.findFirstToken(TokenTypes.IDENT);
108             nameNode.setDefinition(classDef, classDef, true);
109
110             SymTabAST extendsClause =
111                 node.findFirstToken(TokenTypes.EXTENDS_CLAUSE);
112             SymTabAST extendedClassNode =
113                 (SymTabAST) extendsClause.getFirstChild();
114
115             while (extendedClassNode != null) {
116                 IClass superClass =
117                     resolveClass(extendedClassNode, classDef, null, true);
118                 extendedClassNode.setDefinition(superClass, classDef, true);
119                 extendedClassNode =
120                     (SymTabAST) extendedClassNode.getNextSibling();
121             }
122
123             SymTabAST implementsNode =
124                 node.findFirstToken(TokenTypes.IMPLEMENTS_CLAUSE);
125
126             if (implementsNode != null) {
127                 SymTabAST interfaceNode =
128                     (SymTabAST) (implementsNode.getFirstChild());
129                 while (interfaceNode != null) {
130                     resolveClass(interfaceNode, classDef, null, true);
131                     interfaceNode =
132                         (SymTabAST) (interfaceNode.getNextSibling());
133                 }
134             }
135         }
136     }
137
138     /**
139      * processes a <code>MethodDef</code> and resolves references in it
140      *
141      * @param method the <code>MethodDef</code> to process
142      */

143     protected void handleMethod(MethodDef method) {
144         SymTabAST node = method.getTreeNode();
145
146         SymTabAST nameNode = node.findFirstToken(TokenTypes.IDENT);
147         nameNode.setDefinition(method, method, true);
148
149         // references to classes in return type
150
SymTabAST returnTypeNode = node.findFirstToken(TokenTypes.TYPE);
151
152         if (returnTypeNode != null) {
153             // this is not a constructor
154
resolveExpression(returnTypeNode, method, null, true);
155         }
156
157         SymTabAST throwsNode =
158             node.findFirstToken(TokenTypes.LITERAL_THROWS);
159         if (throwsNode != null) {
160             SymTabAST exception = (SymTabAST) throwsNode.getFirstChild();
161             while (exception != null) {
162                 // handle Checkstyle grammar
163
if (exception.getType() != TokenTypes.COMMA) {
164                     resolveClass(exception, method, null, true);
165                 }
166                 exception = (SymTabAST) exception.getNextSibling();
167             }
168         }
169
170         // references to classes in parameters
171

172         // the body -- this would be better its own function
173
SymTabAST slist = node.findFirstToken(TokenTypes.SLIST);
174
175         if (slist != null) {
176             handleSList(slist, method);
177         }
178     }
179
180     /**
181      * processes a <code>BlockDef</code> and resolves references in it
182      *
183      * @param block the <code>BlockDef</code> to process
184      */

185     protected void handleBlock(BlockDef block) {
186         SymTabAST node = block.getTreeNode();
187
188         switch (node.getType()) {
189
190             case TokenTypes.LITERAL_FOR :
191                 handleFor(block);
192                 break;
193
194             case TokenTypes.LITERAL_IF :
195                 handleIf(block);
196                 break;
197
198             case TokenTypes.LITERAL_WHILE :
199                 handleWhileAndSynchronized(block);
200                 break;
201
202             case TokenTypes.LITERAL_DO :
203                 handleDoWhile(block);
204                 break;
205
206             case TokenTypes.LITERAL_TRY :
207             case TokenTypes.LITERAL_FINALLY :
208                 SymTabAST slist = node.findFirstToken(TokenTypes.SLIST);
209
210                 handleSList(slist, block);
211                 break;
212
213             case TokenTypes.LITERAL_CATCH :
214                 handleCatch(block);
215                 break;
216
217             case TokenTypes.LITERAL_SWITCH :
218                 handleSwitch(block);
219                 break;
220
221             case TokenTypes.SLIST :
222                 handleSList(node, block);
223                 break;
224
225             case TokenTypes.EXPR :
226                 resolveExpression(node, block, null, true);
227                 break;
228
229             case TokenTypes.INSTANCE_INIT :
230             case TokenTypes.STATIC_INIT :
231                 handleSList((SymTabAST) node.getFirstChild(), block);
232                 break;
233
234             case TokenTypes.LITERAL_SYNCHRONIZED :
235                 handleWhileAndSynchronized(block);
236                 break;
237
238             case TokenTypes.LITERAL_ASSERT :
239                 handleAssert(block);
240                 break;
241
242             default :
243                 if (mInitialized) {
244                     final Log log = mLogFactory.getInstance(this.getClass());
245                     log.error(
246                         "Unhandled block "
247                             + block
248                             + " of type "
249                             + node.getType());
250                 }
251         }
252     }
253
254     /**
255      * @param block
256      */

257     private void handleAssert(BlockDef block) {
258         SymTabAST node = block.getTreeNode();
259
260         SymTabAST conditional =
261             (node.findFirstToken(TokenTypes.EXPR));
262         resolveExpression(conditional, block, null, true);
263
264         SymTabAST message = (SymTabAST) conditional.getNextSibling();
265         while ((message != null) && (message.getType() != TokenTypes.EXPR)) {
266             message = (SymTabAST) message.getNextSibling();
267         }
268         if (message != null) {
269             resolveExpression(message, block, null, true);
270         }
271     }
272
273     /**
274      * processes a switch statement and resolves references in it
275      *
276      * @param block the <code>BlockDef</code> to process
277      */

278     private void handleSwitch(BlockDef block) {
279         SymTabAST node = block.getTreeNode();
280
281         SymTabAST expr = node.findFirstToken(TokenTypes.EXPR);
282         resolveExpression(expr, block, null, true);
283
284         SymTabAST caseGroup = (SymTabAST) (expr.getNextSibling());
285         while (caseGroup != null
286             && (caseGroup.getType() != TokenTypes.CASE_GROUP)) {
287             caseGroup = (SymTabAST) caseGroup.getNextSibling();
288         }
289         if (caseGroup != null) {
290             while (caseGroup.getType() == TokenTypes.CASE_GROUP) {
291                 SymTabAST caseNode =
292                     caseGroup.findFirstToken(TokenTypes.LITERAL_CASE);
293                 while (caseNode != null
294                     && caseNode.getType() == TokenTypes.LITERAL_CASE) {
295                     resolveExpression(
296                         (SymTabAST) caseNode.getFirstChild(),
297                         block,
298                         null,
299                         true);
300                     caseNode = (SymTabAST) caseNode.getNextSibling();
301                 }
302
303                 SymTabAST caseSlist =
304                     caseGroup.findFirstToken(TokenTypes.SLIST);
305                 handleSList(caseSlist, block);
306
307                 caseGroup = (SymTabAST) (caseGroup.getNextSibling());
308             }
309         }
310     }
311
312     /**
313      * processes a catch block and resolves references in it
314      *
315      * @param block the <code>BlockDef</code> to process
316      */

317     private void handleCatch(BlockDef block) {
318         SymTabAST node = block.getTreeNode();
319
320         SymTabAST slist = node.findFirstToken(TokenTypes.SLIST);
321         handleSList(slist, block);
322     }
323
324     /**
325      * processes a for loop and resolves references in it
326      *
327      * @param block the <code>BlockDef</code> to process
328      */

329     private void handleFor(BlockDef block) {
330         SymTabAST node = block.getTreeNode();
331
332         SymTabAST body;
333         SymTabAST forEach = node.findFirstToken(TokenTypes.FOR_EACH_CLAUSE);
334         if (forEach == null) {
335             SymTabAST init = node.findFirstToken(TokenTypes.FOR_INIT);
336             // only need to handle the elist case. if the init node is a variable
337
// definition, the variable def will be handled later on in the resolution
338
if (init.getFirstChild() != null) {
339                 if (init.getFirstChild().getType() == TokenTypes.ELIST) {
340                     resolveExpression(
341                         (SymTabAST) (init.getFirstChild()),
342                         block,
343                         null,
344                         true);
345                 }
346             }
347
348             SymTabAST cond = node.findFirstToken(TokenTypes.FOR_CONDITION);
349             if (cond.getFirstChild() != null) {
350                 resolveExpression(
351                     (SymTabAST) (cond.getFirstChild()),
352                     block,
353                     null,
354                     true);
355             }
356
357             SymTabAST iterator = node.findFirstToken(TokenTypes.FOR_ITERATOR);
358             if (iterator.getFirstChild() != null) {
359                 resolveExpression(
360                     (SymTabAST) (iterator.getFirstChild()),
361                     block,
362                     null,
363                     true);
364             }
365             body = (SymTabAST) (iterator.getNextSibling());
366         }
367         else {
368             resolveExpression(
369                 (forEach.findFirstToken(TokenTypes.EXPR)),
370                 block,
371                 null,
372                 true);
373             body = (SymTabAST) (forEach.getNextSibling());
374         }
375         //could be an SLIST, EXPR or an EMPTY_STAT
376
if (body.getType() == TokenTypes.RPAREN) {
377             body = (SymTabAST) body.getNextSibling();
378         }
379         if (body.getType() == TokenTypes.SLIST) {
380             handleSList(body, block);
381         }
382         else {
383             resolveExpression(body, block, null, true);
384         }
385
386     }
387
388     /**
389      * processes an if statement and resolves references in it
390      *
391      * @param block the <code>BlockDef</code> to process
392      */

393     private void handleIf(BlockDef block) {
394         SymTabAST node = block.getTreeNode();
395
396         SymTabAST conditional =
397             (node.findFirstToken(TokenTypes.EXPR));
398         resolveExpression(conditional, block, null, true);
399
400         SymTabAST body = (SymTabAST) conditional.getNextSibling();
401         // Handle Checkstyle grammar
402
if (body.getType() == TokenTypes.RPAREN) {
403             body = (SymTabAST) body.getNextSibling();
404         }
405         if (body != null) {
406             if (body.getType() == TokenTypes.SLIST) {
407                 handleSList(body, block);
408             }
409             else {
410                 resolveExpression(body, block, null, true);
411             }
412
413             SymTabAST elseBody = (SymTabAST) body.getNextSibling();
414             //handle Checkstyle grammar
415
while ((elseBody != null)
416                 && (elseBody.getType() != TokenTypes.LITERAL_ELSE)) {
417                 elseBody = (SymTabAST) elseBody.getNextSibling();
418             }
419             /*
420              if (elseBody != null && elseBody.getType() == TokenTypes.SLIST) {
421                  handleSList(elseBody, block);
422              }else{
423                  resolveExpression(elseBody, block, null, true);
424              }
425              */

426             if (elseBody != null) {
427                 elseBody = (SymTabAST) elseBody.getFirstChild();
428             }
429             if (elseBody != null) {
430                 resolveExpression(elseBody, block.getParentScope(), null, true);
431             }
432         }
433     }
434
435     /**
436      * processes a while loop and resolves references in it
437      *
438      * @param block the <code>BlockDef</code> to process
439      */

440     private void handleWhileAndSynchronized(BlockDef block) {
441         SymTabAST node = block.getTreeNode();
442
443         SymTabAST condition =
444             (node.findFirstToken(TokenTypes.EXPR));
445         SymTabAST slist = (SymTabAST) (condition.getNextSibling());
446         // handle Checkstyle grammar
447
if (slist.getType() == TokenTypes.RPAREN) {
448             slist = (SymTabAST) slist.getNextSibling();
449         }
450
451         resolveExpression(condition, block, null, true);
452         handleSList(slist, block);
453     }
454
455     private void handleDoWhile(BlockDef block) {
456         SymTabAST node = block.getTreeNode();
457
458         SymTabAST slist = (SymTabAST) node.getFirstChild();
459         SymTabAST condition =
460             node.findFirstToken(TokenTypes.EXPR);
461
462         handleSList(slist, block);
463         resolveExpression(condition, block, null, true);
464     }
465
466     /**
467      * processes a variable definition and resolves references in it
468      *
469      * @param variable the <code>VariableDef</code> to process
470      */

471     protected void handleVariable(VariableDef variable) {
472         SymTabAST node = variable.getTreeNode();
473         Scope location = variable.getParentScope();
474
475         SymTabAST nameNode = node.findFirstToken(TokenTypes.IDENT);
476         nameNode.setDefinition(variable, location, true);
477
478         SymTabAST typeNode = node.findFirstToken(TokenTypes.TYPE);
479         resolveType(typeNode, location, null, true);
480
481         SymTabAST assignmentNode = node.findFirstToken(TokenTypes.ASSIGN);
482         if (assignmentNode != null) {
483             resolveExpression(
484                 (SymTabAST) (assignmentNode.getFirstChild()),
485                 variable.getParentScope(),
486                 null,
487                 true);
488         }
489     }
490
491     /**
492      * processes a label and resolves references in it
493      *
494      * @param label the <code>LabelDef</code> to process
495      */

496     protected void handleLabel(LabelDef label) {
497         SymTabAST node = label.getTreeNode();
498         ((SymTabAST) node.getFirstChild()).setDefinition(
499             label,
500             label.getParentScope(),
501             true);
502     }
503
504     /**
505      * Resolves Java expressions, returning the type to which the expression
506      * evalutes. If this is the reference creation phase, any references found during resolution are created and
507      * resolved.
508      *
509      * @param expression the <code>SymTabAST</code> representing the expression
510      * @param location the <code>Scope</code> in which the expression occours.
511      * @param context the <code>Scope</code> in which the search for the
512      * definition will start
513      * @param referencePhase whether or not this is the reference phase of
514      * table construction
515      *
516      * @return the <code>ClassDef</code> representing the type to which the
517      * expression evalutes.
518      */

519     public IClass resolveExpression(
520         SymTabAST expression,
521         Scope location,
522         IClass context,
523         boolean referencePhase) {
524         IClass result = null;
525
526         try {
527
528             switch (expression.getType()) {
529
530                 case TokenTypes.TYPECAST :
531                     result =
532                         resolveTypecast(
533                             expression,
534                             location,
535                             context,
536                             referencePhase);
537                     break;
538                 case TokenTypes.EXPR :
539                 case TokenTypes.LITERAL_RETURN :
540                     if (expression.getFirstChild() != null) {
541                         result =
542                             resolveExpression(
543                                 (SymTabAST) expression.getFirstChild(),
544                                 location,
545                                 context,
546                                 referencePhase);
547                     }
548                     else {
549                         // YOU WRITE BAD CODE!
550
}
551                     break;
552
553                 case TokenTypes.ELIST :
554
555                     SymTabAST child = (SymTabAST) (expression.getFirstChild());
556                     while (child != null) {
557                         if (child.getType() != TokenTypes.COMMA) {
558                             resolveExpression(
559                                 child,
560                                 location,
561                                 context,
562                                 referencePhase);
563                         }
564                         child = (SymTabAST) (child.getNextSibling());
565                     }
566                     break;
567
568                 case TokenTypes.IDENT :
569                     result =
570                         resolveIdent(
571                             expression,
572                             location,
573                             context,
574                             referencePhase);
575                     break;
576
577                 case TokenTypes.TYPE :
578                     result =
579                         resolveType(
580                             expression,
581                             location,
582                             context,
583                             referencePhase);
584                     break;
585
586                 case TokenTypes.METHOD_CALL :
587                 //case TokenTypes.SUPER_CTOR_CALL :
588
result =
589                         resolveMethod(
590                             expression,
591                             location,
592                             context,
593                             referencePhase);
594                     break;
595
596                 case TokenTypes.LITERAL_THIS :
597                     result = resolveLiteralThis(expression, location, context);
598                     break;
599
600                 case TokenTypes.LITERAL_SUPER :
601                     result = resolveLiteralSuper(expression, location, context);
602                     break;
603
604                 case TokenTypes.DOT :
605                     result =
606                         resolveDottedName(
607                             expression,
608                             location,
609                             context,
610                             referencePhase);
611                     break;
612
613                 case TokenTypes.LITERAL_NEW :
614                 case TokenTypes.CTOR_CALL :
615                 case TokenTypes.SUPER_CTOR_CALL :
616                     result =
617                         resolveNew(
618                             expression,
619                             location,
620                             context,
621                             referencePhase);
622                     break;
623
624                 case TokenTypes.LITERAL_BOOLEAN :
625                 case TokenTypes.LITERAL_DOUBLE :
626                 case TokenTypes.LITERAL_FLOAT :
627                 case TokenTypes.LITERAL_LONG :
628                 case TokenTypes.LITERAL_INT :
629                 case TokenTypes.LITERAL_SHORT :
630                 case TokenTypes.LITERAL_BYTE :
631                 case TokenTypes.LITERAL_CHAR :
632                     result =
633                         resolvePrimitiveType(
634                             expression,
635                             location,
636                             context,
637                             referencePhase);
638                     break;
639
640                 case TokenTypes.NUM_INT :
641                 case TokenTypes.NUM_LONG :
642                     result = resolveNumInt(expression, location, context);
643                     break;
644
645                 case TokenTypes.NUM_FLOAT :
646                 case TokenTypes.NUM_DOUBLE :
647                     result = resolveNumFloat(expression, location, context);
648                     break;
649
650                 case TokenTypes.STRING_LITERAL :
651                     result =
652                         resolveStringLiteral(expression, location, context);
653                     break;
654
655                 case TokenTypes.CHAR_LITERAL :
656                     result = resolveCharLiteral(expression, location, context);
657                     break;
658
659                 case TokenTypes.ASSIGN :
660                 case TokenTypes.PLUS_ASSIGN :
661                 case TokenTypes.MINUS_ASSIGN :
662                 case TokenTypes.STAR_ASSIGN :
663                 case TokenTypes.DIV_ASSIGN :
664                 case TokenTypes.MOD_ASSIGN :
665                 case TokenTypes.SR_ASSIGN :
666                 case TokenTypes.BSR_ASSIGN :
667                 case TokenTypes.SL_ASSIGN :
668                 case TokenTypes.BAND_ASSIGN :
669                 case TokenTypes.BXOR_ASSIGN :
670                 case TokenTypes.BOR_ASSIGN :
671                     resolveAssignment(
672                         expression,
673                         location,
674                         context,
675                         referencePhase);
676                     break;
677
678                 case TokenTypes.LOR :
679                 case TokenTypes.LAND :
680                 case TokenTypes.NOT_EQUAL :
681                 case TokenTypes.EQUAL :
682                 case TokenTypes.LT :
683                 case TokenTypes.GT :
684                 case TokenTypes.LE :
685                 case TokenTypes.GE :
686                     result =
687                         resolveBooleanExpression(
688                             expression,
689                             location,
690                             context,
691                             referencePhase);
692                     break;
693
694                 case TokenTypes.LITERAL_INSTANCEOF :
695                     result =
696                         resolveInstanceOf(
697                             expression,
698                             location,
699                             context,
700                             referencePhase);
701                     break;
702
703                 case TokenTypes.LITERAL_TRUE :
704                 case TokenTypes.LITERAL_FALSE :
705                     result =
706                         resolveBooleanLiteral(expression, location, context);
707                     break;
708
709                 case TokenTypes.LNOT :
710                     result =
711                         resolveBooleanUnary(
712                             expression,
713                             location,
714                             context,
715                             referencePhase);
716                     break;
717
718                 case TokenTypes.INC :
719                 case TokenTypes.POST_INC :
720                 case TokenTypes.DEC :
721                 case TokenTypes.POST_DEC :
722                 case TokenTypes.UNARY_PLUS :
723                 case TokenTypes.UNARY_MINUS :
724                     result =
725                         resolveUnaryExpression(
726                             expression,
727                             location,
728                             context,
729                             referencePhase);
730                     break;
731
732                 case TokenTypes.PLUS :
733                 case TokenTypes.MINUS :
734                 case TokenTypes.DIV :
735                 case TokenTypes.STAR :
736                 case TokenTypes.BAND :
737                 case TokenTypes.BOR :
738                 case TokenTypes.BXOR :
739                 case TokenTypes.MOD :
740                     result =
741                         resolveArithmeticExpression(
742                             expression,
743                             location,
744                             context,
745                             referencePhase);
746                     break;
747
748                 case TokenTypes.LITERAL_BREAK :
749                 case TokenTypes.LITERAL_CONTINUE :
750                     resolveGoto(expression, location, context, referencePhase);
751                     break;
752
753                 case TokenTypes.LPAREN :
754                     result = resolveExpression(
755                         //TODO: child || sibling?
756
(SymTabAST) (expression.getNextSibling()),
757                         //(SymTabAST) (expression.getFirstChild()),
758
location, context, referencePhase);
759                     break;
760
761                 case TokenTypes.INDEX_OP :
762                     result =
763                         resolveArrayAccess(
764                             expression,
765                             location,
766                             context,
767                             referencePhase);
768                     break;
769
770                 case TokenTypes.LITERAL_NULL :
771                     result = new NullClass();
772                     break;
773
774                 case TokenTypes.QUESTION :
775                     result =
776                         resolveQuestion(
777                             expression,
778                             location,
779                             context,
780                             referencePhase);
781                     break;
782
783                 case TokenTypes.LITERAL_CLASS :
784                     result = resolveLiteralClass();
785                     break;
786
787                 case TokenTypes.ARRAY_INIT :
788                     resolveArrayInitializer(
789                         expression,
790                         location,
791                         context,
792                         referencePhase);
793                     break;
794
795                 case TokenTypes.LITERAL_THROW :
796                     resolveThrowExpression(
797                         expression,
798                         location,
799                         context,
800                         referencePhase);
801                     break;
802
803                 case TokenTypes.SL :
804                 case TokenTypes.SR :
805                 case TokenTypes.BSR :
806                     result =
807                         resolveShiftOperator(
808                             expression,
809                             location,
810                             context,
811                             referencePhase);
812                     break;
813
814                 case TokenTypes.BNOT :
815                     resolveBitwiseNot(
816                         expression,
817                         location,
818                         context,
819                         referencePhase);
820                     break;
821
822                 case TokenTypes.LITERAL_ASSERT :
823 // resolveAssert(
824
// expression,
825
// location,
826
// context,
827
// referencePhase);
828
break;
829
830                 case TokenTypes.RPAREN :
831                 case TokenTypes.EMPTY_STAT :
832                     // case TokenTypes.ML_COMMENT:
833
// case TokenTypes.SL_COMMENT:
834
case TokenTypes.VARIABLE_DEF :
835                 case TokenTypes.METHOD_DEF :
836                 case TokenTypes.CLASS_DEF :
837                 case TokenTypes.LITERAL_FOR :
838                 case TokenTypes.LITERAL_WHILE :
839                 case TokenTypes.LITERAL_IF :
840                 case TokenTypes.LITERAL_VOID :
841                     // case TokenTypes.LITERAL_INTERFACE:
842
case TokenTypes.LITERAL_DO :
843                 case TokenTypes.LITERAL_SWITCH :
844                 case TokenTypes.LITERAL_STATIC :
845                 case TokenTypes.LITERAL_TRANSIENT :
846                 case TokenTypes.LITERAL_NATIVE :
847                     // case TokenTypes.LITERAL_threadsafe:
848
case TokenTypes.LITERAL_SYNCHRONIZED :
849                 case TokenTypes.LITERAL_VOLATILE :
850                 case TokenTypes.LITERAL_TRY :
851                 case TokenTypes.LITERAL_CATCH :
852                 case TokenTypes.LITERAL_FINALLY :
853                 case TokenTypes.LABELED_STAT :
854                 case TokenTypes.LCURLY :
855                 case TokenTypes.RCURLY :
856                 case TokenTypes.SLIST :
857                 case TokenTypes.SEMI :
858                 case TokenTypes.COMMA :
859                 case TokenTypes.ARRAY_DECLARATOR :
860                     break;
861
862                 default :
863                 //TODO: throw exception
864
if (mInitialized) {
865                         final Log log =
866                             mLogFactory.getInstance(this.getClass());
867                         log.error(
868                             "Unhandled expression type: "
869                                 + expression.getType());
870                     }
871                     break;
872             }
873         }
874         catch (Exception JavaDoc e) {
875             
876             result = new UnknownClass(expression.getText(), expression);
877 // TODO: This really should be logged
878
// if (mInitialized) {
879
// final Log log = mLogFactory.getInstance(this.getClass());
880
// log.error("Error resolving near " + expression);
881
// }
882
}
883
884         return result;
885     }
886
887     private IClass resolveTypecast(
888         SymTabAST node,
889         Scope location,
890         IClass context,
891         boolean referencePhase) {
892         SymTabAST typeNode = (SymTabAST) node.getFirstChild();
893         SymTabAST exprNode = (SymTabAST) typeNode.getNextSibling();
894         //handle Checkstyle grammar
895
if (exprNode.getType() == TokenTypes.RPAREN) {
896             exprNode = (SymTabAST) exprNode.getNextSibling();
897         }
898
899         IClass type = null;
900
901         final SymTabAST child = (SymTabAST) typeNode.getFirstChild();
902         // TODO: Checkstyle change.
903
// Do not create references from typecast.
904
// Original transmogrify code is equivalent to
905
// final boolean createReference = referencePhase;
906
// which creates non-existant references for variables.
907
final boolean createReference = false;
908         if (child.getType()
909             == TokenTypes.ARRAY_DECLARATOR) {
910             type =
911                 new ArrayDef(
912                     resolveType(
913                         (SymTabAST) typeNode.getFirstChild(),
914                         location,
915                         context,
916                         createReference));
917         }
918         else {
919             type = resolveType(typeNode, location, context, createReference);
920         }
921
922         resolveExpression(exprNode, location, context, referencePhase);
923         //TODO: Checkstyle change. Can this be ignored?
924
if (type != null) {
925             ((SymTabAST) typeNode.getFirstChild()).setDefinition(
926                 type,
927                 location,
928                 referencePhase);
929         }
930
931         return type;
932     }
933
934     private IClass resolveArrayAccess(
935         SymTabAST node,
936         Scope location,
937         IClass context,
938         boolean referencePhase) {
939
940         SymTabAST arrayNode = (SymTabAST) (node.getFirstChild());
941         SymTabAST exprNode = (SymTabAST) (arrayNode.getNextSibling());
942
943         //resolve index expressions
944
while (arrayNode.getType() == TokenTypes.INDEX_OP) {
945             resolveExpression(exprNode, location, context, referencePhase);
946             arrayNode = (SymTabAST) (arrayNode.getFirstChild());
947             exprNode = (SymTabAST) (arrayNode.getNextSibling());
948         }
949         
950         ArrayDef array =
951             (ArrayDef) resolveExpression(arrayNode,
952                 location,
953                 context,
954                 referencePhase);
955
956         resolveExpression(exprNode, location, context, referencePhase);
957
958         return array.getType();
959     }
960
961     private IClass resolveLiteralClass() {
962         return new ExternalClass(Class JavaDoc.class);
963     }
964
965     /**
966      * Resolves any dotted reference, returning the <code>Scope</code>
967      * identified by the reference.
968      *
969      * @param tree the root node of the dotted reference
970      * @param location the <code>Scope</code> in which the expression occours.
971      * @param context the <code>Scope</code> in which the search for the
972      * definition will start
973      * @return the <code>Scope</code> indentified by the reference
974      */

975     private IClass resolveDottedName(
976         SymTabAST tree,
977         Scope location,
978         IClass context,
979         boolean referencePhase) {
980         IClass result = null;
981
982         IClass localContext = context;
983         String JavaDoc name = null;
984
985         DotIterator it = new DotIterator(tree);
986         while (it.hasNext()) {
987             SymTabAST node = it.nextNode();
988             if (node.getType() != TokenTypes.COMMA) {
989                 localContext =
990                     resolveExpression(
991                         node,
992                         location,
993                         localContext,
994                         referencePhase);
995                 if (localContext == null) {
996                     node.setMeaningfulness(false);
997                     name = node.getText();
998                     while (localContext == null && it.hasNext()) {
999                         SymTabAST next = it.nextNode();
1000                        name = name + "." + next.getText();
1001                        localContext = location.getClassDefinition(name);
1002                        if (localContext != null && referencePhase) {
1003                            next.setDefinition(
1004                                localContext,
1005                                location,
1006                                referencePhase);
1007                        }
1008                        else {
1009                            next.setMeaningfulness(false);
1010                        }
1011                    }
1012                }
1013            }
1014        }
1015
1016        if (localContext != null) {
1017            result = localContext;
1018        }
1019        else {
1020            result = new UnknownClass(name, tree);
1021        }
1022
1023        return result;
1024    }
1025
1026    /**
1027     * Resolves a method call.
1028     *
1029     * @param methodNode the <code>SymTabAST</code> for the METHOD_CALL node
1030     * @param location the <code>Scope</code> where the expression occurs
1031     * @param context the <code>Scope</code> in which the expression occurs
1032     * (where the search for a defintion begins)
1033     * @param referencePhase whether or not this is the reference phase of
1034     * table construction
1035     *
1036     * @return the <code>ClassDef</code> for the type returned by the method
1037     */

1038    private IClass resolveMethod(
1039        SymTabAST methodNode,
1040        Scope location,
1041        IClass context,
1042        boolean referencePhase) {
1043        IClass result = new UnknownClass(methodNode.getText(), methodNode);
1044        IClass newContext = null;
1045
1046        if (context == null) {
1047            newContext = location.getEnclosingClass();
1048        }
1049        else {
1050            newContext = context;
1051        }
1052
1053        String JavaDoc name = null;
1054        boolean createReference = true;
1055
1056        SymTabAST nameNode = (SymTabAST) (methodNode.getFirstChild());
1057        SymTabAST parametersNode = (SymTabAST) (nameNode.getNextSibling());
1058
1059        ISignature signature =
1060            resolveParameters(
1061                parametersNode,
1062                location,
1063                context,
1064                referencePhase);
1065
1066        if (nameNode.getType() == TokenTypes.IDENT) {
1067            name = nameNode.getText();
1068        }
1069        else if (
1070            nameNode.getType() == TokenTypes.LITERAL_SUPER
1071                || (nameNode.getType() == TokenTypes.SUPER_CTOR_CALL)) {
1072            IClass superclass = location.getEnclosingClass().getSuperclass();
1073            newContext = superclass;
1074            name = superclass.getName();
1075            createReference = false;
1076        }
1077        else if (nameNode.getType() == TokenTypes.LITERAL_THIS) {
1078            newContext = location.getEnclosingClass();
1079            name = newContext.getName();
1080            createReference = false;
1081        }
1082        else {
1083            // REDTAG -- doing dotted name resolution on its own
1084
SymTabAST contextNode = (SymTabAST) (nameNode.getFirstChild());
1085            //TODO: handle Checkstyle grammar
1086
nameNode = (SymTabAST) contextNode.getNextSibling();
1087            //skip to IDENT
1088
while (nameNode.getType() != TokenTypes.IDENT) {
1089                nameNode = (SymTabAST) nameNode.getNextSibling();
1090            }
1091            
1092            name = nameNode.getText();
1093            newContext =
1094                resolveExpression(
1095                    contextNode,
1096                    location,
1097                    context,
1098                    referencePhase);
1099        }
1100
1101        if (newContext != null) {
1102            IMethod method = newContext.getMethodDefinition(name, signature);
1103
1104            if (method != null) {
1105                if (createReference && referencePhase) {
1106                    nameNode.setDefinition(method, location, referencePhase);
1107                }
1108                result = method.getType();
1109            }
1110        }
1111
1112        if (result == null) {
1113            result = new UnknownClass(methodNode.getText(), methodNode);
1114        }
1115
1116        return result;
1117    }
1118
1119    /**
1120     * resolves a literal "this"
1121     *
1122     * @param expression the <code>SymTabAST</code> of the expression
1123     * @param location the <code>Scope</code> where the expression occurs
1124     * @param context the <code>Scope</code> in which the expression occurs
1125     * (where the search for a defintion begins)
1126     *
1127     * @return the resulting scope of the expression (the type to which it evaluates)
1128     */

1129    private IClass resolveLiteralThis(
1130        SymTabAST thisNode,
1131        Scope location,
1132        IClass context) {
1133        return location.getEnclosingClass();
1134    }
1135
1136    /**
1137     * resolves a literal "super"
1138     *
1139     * @param expression the <code>SymTabAST</code> of the expression
1140     * @param location the <code>Scope</code> where the expression occurs
1141     * @param context the <code>Scope</code> in which the expression occurs
1142     * (where the search for a defintion begins)
1143     *
1144     * @return the resulting scope of the expression (the type to which it evaluates)
1145     */

1146    private IClass resolveLiteralSuper(
1147        SymTabAST superNode,
1148        Scope location,
1149        IClass context) {
1150        return location.getEnclosingClass().getSuperclass();
1151    }
1152
1153    private boolean newIsConstructor(SymTabAST newNode) {
1154        boolean result = false;
1155
1156        SymTabAST typeNode =
1157            (SymTabAST) (newNode.getFirstChild().getNextSibling());
1158        //handle Checkstyle grammar
1159
if (typeNode.getType() == TokenTypes.LPAREN) {
1160            typeNode = (SymTabAST) typeNode.getNextSibling();
1161        }
1162        if (typeNode.getType() == TokenTypes.ELIST) {
1163            result = true;
1164        }
1165        return result;
1166
1167    }
1168
1169    /**
1170     * resolves and expression of type TokenTypes.TYPE
1171     *
1172     * @param expression the <code>SymTabAST</code> of the expression
1173     * @param location the <code>Scope</code> where the expression occurs
1174     * @param context the <code>Scope</code> in which the expression occurs
1175     * (where the search for a defintion begins)
1176     * @param referencePhase whether or not this is the reference phase of
1177     * table construction
1178     * @return the resulting scope of the expression (the type to which it evaluates)
1179     * @see #resolveDottedName(SymTabAST, Scope, IClass, boolean)
1180     * @see #resolveClassIdent(SymTabAST, Scope, IClass, boolean)
1181     */

1182    public IClass resolveType(
1183        SymTabAST expr,
1184        Scope location,
1185        IClass context,
1186        boolean referencePhase) {
1187        IClass result = null;
1188        SymTabAST nameNode = (SymTabAST) expr.getFirstChild();
1189
1190        // TODO: Checkstyle change.
1191
// Do not create references from typecast.
1192
// Original transmogrify code is equivalent to
1193
// final boolean createReference = referencePhase;
1194
// which creates non-existant references for variables.
1195
final boolean createReference = false;
1196        if (nameNode.getType() == TokenTypes.DOT) {
1197            result =
1198                resolveDottedName(nameNode, location, context, createReference);
1199        }
1200        else {
1201            result =
1202                resolveClassIdent(nameNode, location, context, createReference);
1203        }
1204
1205        return result;
1206    }
1207
1208    /**
1209     * resolves Class type expression
1210     * @param expr node to be resolved
1211     * @param location scope of the <code>expr</code>
1212     * @param context context of the <code>expr</code> if exists
1213     * @param referencePhase <code>true</code> if this method is used to during
1214     * finding reference phase
1215     * <code>false</code> otherwise
1216     * @return <code>IClass</code> representing the type to which the
1217     * expression evalutes.
1218     * @see #resolveDottedName(SymTabAST, Scope, IClass, boolean)
1219     */

1220    public IClass resolveClass(
1221        SymTabAST expr,
1222        Scope location,
1223        IClass context,
1224        boolean referencePhase) {
1225
1226        IClass result =
1227            resolveDottedName(expr, location, context, referencePhase);
1228        if (result != null && referencePhase) {
1229            expr.setDefinition(result, location, referencePhase);
1230        }
1231
1232        return result;
1233    }
1234
1235    /**
1236     * resolves expression with <code>JavaTokenTypes<code> other than <code>DOT</code>
1237     * @param expr expression to be resolved
1238     * @param location scope of the expression
1239     * @param context context of the expression if any
1240     * @param referencePhase <code>true</code> if this method is used to during
1241     * finding reference phase
1242     * <code>false</code> otherwise
1243     * @return <code>IClass</code> representing the type to which the
1244     * expression evalutes.
1245     */

1246    public IClass resolveClassIdent(
1247        SymTabAST expr,
1248        Scope location,
1249        IClass context,
1250        boolean referencePhase) {
1251
1252        IClass result = location.getClassDefinition(expr.getText());
1253        if (result != null) {
1254            expr.setDefinition(result, location, referencePhase);
1255        }
1256
1257        return result;
1258    }
1259
1260    private IClass resolveNew(
1261        SymTabAST newNode,
1262        Scope location,
1263        IClass context,
1264        boolean referencePhase) {
1265
1266        IClass result;
1267
1268        if (newIsConstructor(newNode)) {
1269            result =
1270                resolveConstructor(newNode, location, context, referencePhase);
1271        }
1272        else {
1273            result =
1274                resolveNewArray(newNode, location, context, referencePhase);
1275        }
1276
1277        return result;
1278    }
1279
1280    private IClass resolveNewArray(
1281        SymTabAST newNode,
1282        Scope location,
1283        IClass context,
1284        boolean referencePhase) {
1285        IClass arrayType;
1286
1287        SymTabAST typeNode = (SymTabAST) (newNode.getFirstChild());
1288        SymTabAST declaratorNode = (SymTabAST) (typeNode.getNextSibling());
1289        SymTabAST initializerNode =
1290            (SymTabAST) (declaratorNode.getNextSibling());
1291
1292        arrayType = resolveClass(typeNode, location, context, referencePhase);
1293
1294        if (declaratorNode.getFirstChild() != null) {
1295            resolveExpression(
1296                ((SymTabAST) declaratorNode.getFirstChild()),
1297                location,
1298                context,
1299                referencePhase);
1300        }
1301
1302        if (initializerNode != null) {
1303            resolveArrayInitializer(
1304                initializerNode,
1305                location,
1306                context,
1307                referencePhase);
1308        }
1309
1310        return new ArrayDef(arrayType);
1311    }
1312
1313    private IClass resolveQuestion(
1314        SymTabAST question,
1315        Scope location,
1316        IClass context,
1317        boolean referencePhase) {
1318        SymTabAST test = (SymTabAST) question.getFirstChild();
1319        while (test.getType() == TokenTypes.LPAREN) {
1320            test = (SymTabAST) test.getNextSibling();
1321        }
1322        SymTabAST leftBranch = (SymTabAST) test.getNextSibling();
1323        while (leftBranch.getType() == TokenTypes.RPAREN) {
1324            leftBranch = (SymTabAST) leftBranch.getNextSibling();
1325        }
1326        SymTabAST rightBranch = (SymTabAST) leftBranch.getNextSibling();
1327        while (rightBranch.getType() != TokenTypes.COLON) {
1328            rightBranch = (SymTabAST) rightBranch.getNextSibling();
1329        }
1330        rightBranch = (SymTabAST) rightBranch.getNextSibling();
1331
1332        resolveExpression(test, location, context, referencePhase);
1333        IClass leftClass =
1334            resolveExpression(leftBranch, location, context, referencePhase);
1335        IClass rightClass =
1336            resolveExpression(rightBranch, location, context, referencePhase);
1337
1338        return moreGeneral(leftClass, rightClass);
1339    }
1340
1341    private IClass moreGeneral(IClass a, IClass b) {
1342        return (a.isCompatibleWith(b)) ? b : a;
1343    }
1344
1345    /**
1346     * Resolves a constructor call.
1347     *
1348     * @param tree the root node of the constructor call
1349     * @return the <code>ClassDef</code> for the class instantiated by the
1350     * constructor
1351     */

1352    private IClass resolveConstructor(
1353        SymTabAST constructor,
1354        Scope location,
1355        IClass context,
1356        boolean referencePhase) {
1357
1358        IClass classConstructed = null;
1359
1360        SymTabAST nameNode = (SymTabAST) (constructor.getFirstChild());
1361        //SymTabAST parametersNode = (SymTabAST) (nameNode.getNextSibling());
1362
SymTabAST parametersNode =
1363            constructor.findFirstToken(TokenTypes.ELIST);
1364        SymTabAST nameIdent = null;
1365        if (nameNode.getType() == TokenTypes.IDENT) {
1366            nameIdent = nameNode;
1367        }
1368        else {
1369            nameIdent = (SymTabAST) nameNode.getFirstChild().getNextSibling();
1370        }
1371
1372        classConstructed = resolveClass(nameNode, location, context, false);
1373        if (classConstructed != null) {
1374            MethodSignature signature =
1375                resolveParameters(
1376                    parametersNode,
1377                    location,
1378                    context,
1379                    referencePhase);
1380
1381            IMethod constructorDef =
1382                classConstructed.getMethodDefinition(
1383                    nameIdent.getText(),
1384                    signature);
1385
1386            if (constructorDef != null && referencePhase) {
1387                nameIdent.setDefinition(
1388                    constructorDef,
1389                    location,
1390                    referencePhase);
1391            }
1392        }
1393
1394        return classConstructed;
1395    }
1396
1397    /**
1398     * Resolves the types found in a method call. Any references found
1399     * in the process are created. Returns a <code>MethodSignature</code> for
1400     * the types of the parameters.
1401     *
1402     * @param elist The <code>SymTabAST</code> for the list of parameters
1403     * @return the signature of the parameters
1404     */

1405    private MethodSignature resolveParameters(
1406        SymTabAST elist,
1407        Scope location,
1408        IClass context,
1409        boolean referencePhase) {
1410        Vector JavaDoc parameters = new Vector JavaDoc();
1411
1412        SymTabAST expr = (SymTabAST) (elist.getFirstChild());
1413        while (expr != null) {
1414            if (expr.getType() != TokenTypes.COMMA) {
1415                IClass parameter =
1416                    resolveExpression((SymTabAST) (expr
1417                    .getFirstChild()),
1418                    location,
1419                    context,
1420                    referencePhase);
1421                parameters.add(parameter);
1422            }
1423
1424            expr = (SymTabAST) (expr.getNextSibling());
1425        }
1426
1427        return new MethodSignature(parameters);
1428    }
1429
1430    /**
1431     * Resolves an IDENT node of an AST, creating the appropriate reference and
1432     * returning the scope of the identifer.
1433     *
1434     * @param ident the IDENT node
1435     * @param location the <code>Scope</code> in which the IDENT is found
1436     * @return the <code>Scope</code> the identifier identifies
1437     */

1438    private IClass resolveIdent(
1439        SymTabAST ident,
1440        Scope location,
1441        IClass context,
1442        boolean referencePhase) {
1443
1444        IClass result = null;
1445        IDefinition def = null;
1446        String JavaDoc name = ident.getText();
1447
1448        // look for var
1449
if (context != null) {
1450            def = context.getVariableDefinition(name);
1451        }
1452        else {
1453            def = location.getVariableDefinition(name);
1454        }
1455
1456        if (def != null) {
1457            result = ((IVariable) def).getType();
1458        }
1459        else {
1460            // look for class
1461
if (context != null) {
1462                result = context.getClassDefinition(name);
1463            }
1464            else {
1465                result = location.getClassDefinition(name);
1466            }
1467            def = result;
1468        }
1469
1470        if (def != null) {
1471            ident.setDefinition(def, location, referencePhase);
1472        }
1473
1474        return result;
1475    }
1476
1477    /**
1478     * Resolves a (binary) boolean expression. The left and right sides of the
1479     * expression
1480     * are resolved in the process.
1481     *
1482     * @param expression the <code>SymTabAST</code> representing the boolean
1483     * expression.
1484     * @return the <code>Scope</code> for the boolean primitive type.
1485     */

1486    private IClass resolveBooleanExpression(
1487        SymTabAST expression,
1488        Scope location,
1489        IClass context,
1490        boolean referencePhase) {
1491        IClass result = null;
1492
1493        SymTabAST leftChild = findLeftChild(expression);
1494        resolveExpression(leftChild, location, context, referencePhase);
1495        SymTabAST rightChild = findRightSibling(leftChild);
1496
1497        resolveExpression(rightChild, location, context, referencePhase);
1498
1499        result = LiteralResolver.getDefinition(TokenTypes.LITERAL_BOOLEAN);
1500
1501        return result;
1502    }
1503
1504    /**
1505     * resolves references in an assignment expression
1506     *
1507     * @param expression the <code>SymTabAST</code> of the expression
1508     * @param location the <code>Scope</code> where the expression occurs
1509     * @param context the <code>Scope</code> in which the expression occurs
1510     * (where the search for a defintion begins)
1511     *
1512     * @return the resulting scope of the expression (the type to which it evaluates)
1513     */

1514    private IClass resolveAssignment(
1515        SymTabAST expression,
1516        Scope location,
1517        IClass context,
1518        boolean referencePhase) {
1519        IClass result = null;
1520
1521        SymTabAST leftNode = (SymTabAST) (expression.getFirstChild());
1522        SymTabAST rightNode = (SymTabAST) (leftNode.getNextSibling());
1523
1524        result = resolveExpression(leftNode, location, context, referencePhase);
1525        resolveExpression(rightNode, location, context, referencePhase);
1526
1527        return result;
1528    }
1529
1530    /**
1531     * Resolves a unary expression. Returns the type of the expression,
1532     * creating any references found along the way. Unary expressions are
1533     * increment (x++), decrement (x--), unary plus (+x), and unary minus (-x)
1534     *
1535     * @param expression the <code>SymTabAST</code> of the unary expression.
1536     * @return the <code>Scope</code> for the type to which the expression
1537     * evalutes.
1538     */

1539    private IClass resolveUnaryExpression(
1540        SymTabAST expression,
1541        Scope location,
1542        IClass context,
1543        boolean referencePhase) {
1544        SymTabAST operatee = (SymTabAST) (expression.getFirstChild());
1545        return resolveExpression(operatee, location, context, referencePhase);
1546    }
1547
1548    /**
1549     * Resolves an arithmetic expression. Returns the <code>Scope</code> for
1550     * the type to which the expression resolves. Any references found during
1551     * resolution are created and resolved.
1552     *
1553     * @param expression the <code>SymTabAST</code> representing the arithmetic
1554     * expression.
1555     *
1556     * @return the <code>Scope</code> for the type to which the expression
1557     * evaluates.
1558     */

1559    private IClass resolveArithmeticExpression(
1560        SymTabAST expression,
1561        Scope location,
1562        IClass context,
1563        boolean referencePhase) {
1564        IClass result = null;
1565
1566        SymTabAST leftChild = findLeftChild(expression);
1567        
1568        IClass leftType =
1569            (resolveExpression(leftChild,
1570            location,
1571            context,
1572            referencePhase));
1573                
1574        SymTabAST rightChild = findRightSibling(leftChild);
1575
1576        IClass rightType =
1577                    (resolveExpression(rightChild,
1578            location,
1579            context,
1580            referencePhase));
1581
1582        result = binaryResultType(leftType, rightType);
1583
1584        return result;
1585    }
1586
1587    /**
1588     * Finds the left child of a binary operator, skipping parentheses.
1589     * @param aExpression the node for the binary operator.
1590     * @return the node for the left child.
1591     */

1592    private SymTabAST findLeftChild(SymTabAST aExpression) {
1593        SymTabAST leftChild = (SymTabAST) (aExpression.getFirstChild());
1594        // handle Checkstyle grammar
1595
while (leftChild.getType() == TokenTypes.LPAREN) {
1596            leftChild = (SymTabAST) leftChild.getNextSibling();
1597        }
1598        return leftChild;
1599    }
1600
1601    /**
1602     * Finds the right sibling of the left child of a binary operator,
1603     * skipping parentheses.
1604     * @param aLeftChild the left child of a binary operator.
1605     * @return the node of the right sibling.
1606     */

1607    private SymTabAST findRightSibling(SymTabAST aLeftChild) {
1608        SymTabAST rightChild = (SymTabAST) (aLeftChild.getNextSibling());
1609        // handle Checkstyle grammar
1610
while ((rightChild != null)
1611            && (rightChild.getType() == TokenTypes.RPAREN))
1612        {
1613            rightChild = (SymTabAST) rightChild.getNextSibling();
1614        }
1615        return rightChild;
1616    }
1617
1618    /**
1619     * Returns the <code>ClassDef</code> for the type to which arithmetic
1620     * expressions evaluate.
1621     *
1622     * @param a the <code>ClassDef</code> of the first operand.
1623     * @param b the <code>ClassDef</code> of the second operand.
1624     *
1625     * @return the <code>ClassDef</code> to which the expression evaluates.
1626     */

1627    private IClass binaryResultType(IClass a, IClass b) {
1628
1629        IClass result = null;
1630
1631        // These may or may not be in line with the rules set forth in the java
1632
// language specification. Not being in line would be a BadThing(r).
1633

1634        IClass string = new ExternalClass(java.lang.String JavaDoc.class);
1635
1636        if (a.equals(string) || b.equals(string)) {
1637            result = string;
1638        }
1639        else if (a.equals(PrimitiveClasses.BOOLEAN)) {
1640            result = PrimitiveClasses.BOOLEAN;
1641        }
1642        else {
1643            result =
1644                PrimitiveClasses.binaryPromote(
1645                    a,
1646                    b);
1647        }
1648
1649        return result;
1650    }
1651
1652    /**
1653     * resolves references in an instanceof expression
1654     *
1655     * @param expression the <code>SymTabAST</code> of the expression
1656     * @param location the <code>Scope</code> where the expression occurs
1657     * @param context the <code>Scope</code> in which the expression occurs
1658     * (where the search for a defintion begins)
1659     *
1660     * @return the resulting scope of the expression (the type to which it evaluates)
1661     */

1662    private IClass resolveInstanceOf(
1663        SymTabAST expression,
1664        Scope location,
1665        IClass context,
1666        boolean referencePhase) {
1667        SymTabAST leftNode = (SymTabAST) (expression.getFirstChild());
1668        SymTabAST rightNode = (SymTabAST) (leftNode.getNextSibling());
1669
1670        resolveExpression(leftNode, location, context, referencePhase);
1671
1672        SymTabAST classNameNode = (SymTabAST) (rightNode.getFirstChild());
1673        resolveClass(classNameNode, location, context, referencePhase);
1674
1675        return LiteralResolver.getDefinition(TokenTypes.LITERAL_BOOLEAN);
1676    }
1677
1678    /**
1679     * resolves references in a a break statement
1680     *
1681     * @param expression the <code>SymTabAST</code> for the expression
1682     * @param location the <code>Scope</code> where the expression occurs
1683     * @param context the <code>Scope</code> in which the expression occurs
1684     * (where the search for a defintion begins)
1685     *
1686     * @return the <code>Scope</code> for the int primitive type
1687     */

1688    private IClass resolveGoto(
1689        SymTabAST expression,
1690        Scope location,
1691        IClass context,
1692        boolean referencePhase) {
1693        SymTabAST label = (SymTabAST) (expression.getFirstChild());
1694        // handle Checkstyle grammar
1695
if (label != null && (label.getType() != TokenTypes.SEMI)) {
1696            LabelDef def = location.getLabelDefinition(label.getText());
1697            if (def != null) {
1698                label.setDefinition(def, location, referencePhase);
1699            }
1700        }
1701
1702        return null;
1703    }
1704
1705    private IClass resolvePrimitiveType(
1706        SymTabAST primitive,
1707        Scope location,
1708        IClass context,
1709        boolean referencePhase) {
1710        IClass result =
1711            LiteralResolver.getDefinition(primitive.getType());
1712
1713        primitive.setDefinition(result, location, referencePhase);
1714        return result;
1715    }
1716
1717    /**
1718     * Returns the <code>ClassDef</code> of the int primitive type. This may
1719     * need to be amended, based on the Java Language spec, to return a long
1720     * if the literal is larger than an int can hold.
1721     *
1722     * @param expression the <code>SymTabAST</code> for the integer literal
1723     * @param location the <code>Scope</code> where the expression occurs
1724     * @param context the <code>Scope</code> in which the expression occurs
1725     * (where the search for a defintion begins)
1726     *
1727     * @return the <code>Scope</code> for the int primitive type
1728     */

1729    private IClass resolveNumInt(
1730        SymTabAST expression,
1731        Scope location,
1732        IClass context) {
1733        return PrimitiveClasses.INT;
1734    }
1735
1736    /**
1737     * Returns the <code>ClassDef</code> type of the float primitive type.
1738     * This may need to be amended, based on the Java Language spec, to return
1739     * a double if the literal is larger than a float can hold.
1740     *
1741     * @param expression the <code>SymTabAST</code> for the floating point
1742      literal
1743     * @param location the <code>Scope</code> where the expression occurs
1744     * @param context the <code>Scope</code> in which the expression occurs
1745     * (where the search for a defintion begins)
1746     *
1747     * @return the <code>Scope</code> for the float primitive type
1748     */

1749    private IClass resolveNumFloat(
1750        SymTabAST expression,
1751        Scope location,
1752        IClass context) {
1753        return PrimitiveClasses.DOUBLE;
1754    }
1755
1756    /**
1757     * Returns the <code>ClassDef</code> type of a string literal
1758     *
1759     * @param expression the <code>SymTabAST</code> for a string literal
1760     * @param location the <code>Scope</code> where the expression occurs
1761     * @param context the <code>Scope</code> in which the expression occurs
1762     * (where the search for a defintion begins)
1763     *
1764     * @return the <code>Scope</code> type of a string literal
1765     */

1766    private IClass resolveStringLiteral(
1767        SymTabAST expression,
1768        Scope location,
1769        IClass context) {
1770        return LiteralResolver.getDefinition(
1771            TokenTypes.STRING_LITERAL);
1772    }
1773
1774    /**
1775     * Returns the <code>ClassDef</code> type of a character literal
1776     *
1777     * @param expression the <code>SymTabAST</code> for a string literal
1778     * @param location the <code>Scope</code> where the expression occurs
1779     * @param context the <code>Scope</code> in which the expression occurs
1780     * (where the search for a defintion begins)
1781     *
1782     * @return the <code>Scope</code> type of a character literal
1783     */

1784    private IClass resolveCharLiteral(
1785        SymTabAST expression,
1786        Scope location,
1787        IClass context) {
1788        return LiteralResolver.getDefinition(
1789            TokenTypes.LITERAL_CHAR);
1790    }
1791
1792    /**
1793     * Describe <code>resolveBooleanLiteral</code> method here.
1794     *
1795     * @param expression the <code>SymTabAST</code> of the expression
1796     * @param location the <code>Scope</code> where the expression occurs
1797     * @param context the <code>Scope</code> in which the expression occurs
1798     * (where the search for a defintion begins)
1799     *
1800     * @return the <code>Scope</code> for the boolean primitive.
1801     */

1802    private IClass resolveBooleanLiteral(
1803        SymTabAST expression,
1804        Scope location,
1805        IClass context) {
1806        return LiteralResolver.getDefinition(TokenTypes.LITERAL_BOOLEAN);
1807    }
1808
1809    private IClass resolveBooleanUnary(
1810        SymTabAST expression,
1811        Scope location,
1812        IClass context,
1813        boolean referencePhase) {
1814        SymTabAST child = (SymTabAST) expression.getFirstChild();
1815        resolveExpression(child, location, context, referencePhase);
1816
1817        return LiteralResolver.getDefinition(TokenTypes.LITERAL_BOOLEAN);
1818    }
1819
1820    /**
1821     * Resolves a constructor call.
1822     *
1823     * @param tree the root node of the constructor call
1824     * @return the <code>ClassDef</code> for the class instantiated by the
1825     * constructor
1826     */

1827    private void resolveArrayInitializer(
1828        SymTabAST initializerNode,
1829        Scope location,
1830        IClass context,
1831        boolean referencePhase) {
1832        SymTabAST child = (SymTabAST) (initializerNode.getFirstChild());
1833        while (child != null) {
1834            if (child.getType() != TokenTypes.COMMA) {
1835                resolveExpression(child, location, context, referencePhase);
1836            }
1837            child = (SymTabAST) (child.getNextSibling());
1838        }
1839    }
1840
1841    /**
1842     * Resolves a constructor call.
1843     *
1844     * @param tree the root node of the constructor call
1845     * @return the <code>ClassDef</code> for the class instantiated by the
1846     * constructor
1847     */

1848    private void resolveThrowExpression(
1849        SymTabAST throwNode,
1850        Scope location,
1851        IClass context,
1852        boolean referencePhase) {
1853
1854        SymTabAST nameNode = (SymTabAST) (throwNode.getFirstChild());
1855        resolveExpression(nameNode, location, context, referencePhase);
1856    }
1857
1858    private IClass resolveShiftOperator(
1859        SymTabAST expression,
1860        Scope location,
1861        IClass context,
1862        boolean referencePhase) {
1863        IClass result = null;
1864
1865        SymTabAST leftChild = findLeftChild(expression);
1866        SymTabAST rightChild = findRightSibling(leftChild);
1867
1868        result =
1869            resolveExpression(leftChild, location, context, referencePhase);
1870        resolveExpression(rightChild, location, context, referencePhase);
1871
1872        result = PrimitiveClasses.unaryPromote(result);
1873
1874        return result;
1875    }
1876
1877    private IClass resolveBitwiseNot(
1878        SymTabAST expression,
1879        Scope location,
1880        IClass context,
1881        boolean referencePhase) {
1882        IClass result = null;
1883        SymTabAST child = (SymTabAST) expression.getFirstChild();
1884        result = resolveExpression(child, location, context, referencePhase);
1885
1886        result = PrimitiveClasses.unaryPromote(result);
1887
1888        return result;
1889    }
1890}
1891
Popular Tags