Source code: com/puppycrawl/tools/checkstyle/checks/usage/transmogrify/Resolver.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
32
33 import java.util.Vector;
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 (SymTabAST) (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 init = node.findFirstToken(TokenTypes.FOR_INIT);
333 // only need to handle the elist case. if the init node is a variable
334 // definition, the variable def will be handled later on in the resolution
335 if (init.getFirstChild() != null) {
336 if (init.getFirstChild().getType() == TokenTypes.ELIST) {
337 resolveExpression(
338 (SymTabAST) (init.getFirstChild()),
339 block,
340 null,
341 true);
342 }
343 }
344
345 SymTabAST cond = node.findFirstToken(TokenTypes.FOR_CONDITION);
346 if (cond.getFirstChild() != null) {
347 resolveExpression(
348 (SymTabAST) (cond.getFirstChild()),
349 block,
350 null,
351 true);
352 }
353
354 SymTabAST iterator = node.findFirstToken(TokenTypes.FOR_ITERATOR);
355 if (iterator.getFirstChild() != null) {
356 resolveExpression(
357 (SymTabAST) (iterator.getFirstChild()),
358 block,
359 null,
360 true);
361 }
362
363 //could be an SLIST, EXPR or an EMPTY_STAT
364 SymTabAST body = (SymTabAST) (iterator.getNextSibling());
365 // handle Checkstyle grammar
366 if (body.getType() == TokenTypes.RPAREN) {
367 body = (SymTabAST) body.getNextSibling();
368 }
369 if (body.getType() == TokenTypes.SLIST) {
370 handleSList(body, block);
371 }
372 else {
373 resolveExpression(body, block, null, true);
374 }
375
376 }
377
378 /**
379 * processes an if statement and resolves references in it
380 *
381 * @param block the <code>BlockDef</code> to process
382 */
383 private void handleIf(BlockDef block) {
384 SymTabAST node = block.getTreeNode();
385
386 SymTabAST conditional =
387 (SymTabAST) (node.findFirstToken(TokenTypes.EXPR));
388 resolveExpression(conditional, block, null, true);
389
390 SymTabAST body = (SymTabAST) conditional.getNextSibling();
391 // Handle Checkstyle grammar
392 if (body.getType() == TokenTypes.RPAREN) {
393 body = (SymTabAST) body.getNextSibling();
394 }
395 if (body != null && body.getType() == TokenTypes.SLIST) {
396 handleSList(body, block);
397 }
398 else {
399 resolveExpression(body, block, null, true);
400 }
401
402 SymTabAST elseBody = (SymTabAST) body.getNextSibling();
403 //handle Checkstyle grammar
404 while ((elseBody != null)
405 && (elseBody.getType() != TokenTypes.LITERAL_ELSE)) {
406 elseBody = (SymTabAST) elseBody.getNextSibling();
407 }
408 /*
409 if (elseBody != null && elseBody.getType() == TokenTypes.SLIST) {
410 handleSList(elseBody, block);
411 }else{
412 resolveExpression(elseBody, block, null, true);
413 }
414 */
415 if (elseBody != null) {
416 elseBody = (SymTabAST) elseBody.getFirstChild();
417 }
418 if (elseBody != null) {
419 resolveExpression(elseBody, block.getParentScope(), null, true);
420 }
421 }
422
423 /**
424 * processes a while loop and resolves references in it
425 *
426 * @param block the <code>BlockDef</code> to process
427 */
428 private void handleWhileAndSynchronized(BlockDef block) {
429 SymTabAST node = block.getTreeNode();
430
431 SymTabAST condition =
432 (SymTabAST) (node.findFirstToken(TokenTypes.EXPR));
433 SymTabAST slist = (SymTabAST) (condition.getNextSibling());
434 // handle Checkstyle grammar
435 if (slist.getType() == TokenTypes.RPAREN) {
436 slist = (SymTabAST) slist.getNextSibling();
437 }
438
439 resolveExpression(condition, block, null, true);
440 handleSList(slist, block);
441 }
442
443 private void handleDoWhile(BlockDef block) {
444 SymTabAST node = block.getTreeNode();
445
446 SymTabAST slist = (SymTabAST) node.getFirstChild();
447 SymTabAST condition =
448 (SymTabAST) node.findFirstToken(TokenTypes.EXPR);
449
450 handleSList(slist, block);
451 resolveExpression(condition, block, null, true);
452 }
453
454 /**
455 * processes a variable definition and resolves references in it
456 *
457 * @param variable the <code>VariableDef</code> to process
458 */
459 protected void handleVariable(VariableDef variable) {
460 SymTabAST node = variable.getTreeNode();
461 Scope location = variable.getParentScope();
462
463 SymTabAST nameNode = node.findFirstToken(TokenTypes.IDENT);
464 nameNode.setDefinition(variable, location, true);
465
466 SymTabAST typeNode = node.findFirstToken(TokenTypes.TYPE);
467 resolveType(typeNode, location, null, true);
468
469 SymTabAST assignmentNode = node.findFirstToken(TokenTypes.ASSIGN);
470 if (assignmentNode != null) {
471 resolveExpression(
472 (SymTabAST) (assignmentNode.getFirstChild()),
473 variable.getParentScope(),
474 null,
475 true);
476 }
477 }
478
479 /**
480 * processes a label and resolves references in it
481 *
482 * @param label the <code>LabelDef</code> to process
483 */
484 protected void handleLabel(LabelDef label) {
485 SymTabAST node = label.getTreeNode();
486 ((SymTabAST) node.getFirstChild()).setDefinition(
487 label,
488 label.getParentScope(),
489 true);
490 }
491
492 /**
493 * Resolves Java expressions, returning the type to which the expression
494 * evalutes. If this is the reference creation phase, any references found during resolution are created and
495 * resolved.
496 *
497 * @param expression the <code>SymTabAST</code> representing the expression
498 * @param location the <code>Scope</code> in which the expression occours.
499 * @param context the <code>Scope</code> in which the search for the
500 * definition will start
501 * @param referencePhase whether or not this is the reference phase of
502 * table construction
503 *
504 * @return the <code>ClassDef</code> representing the type to which the
505 * expression evalutes.
506 */
507 public IClass resolveExpression(
508 SymTabAST expression,
509 Scope location,
510 IClass context,
511 boolean referencePhase) {
512 IClass result = null;
513
514 try {
515
516 switch (expression.getType()) {
517
518 case TokenTypes.TYPECAST :
519 result =
520 resolveTypecast(
521 expression,
522 location,
523 context,
524 referencePhase);
525 break;
526 case TokenTypes.EXPR :
527 case TokenTypes.LITERAL_RETURN :
528 if (expression.getFirstChild() != null) {
529 result =
530 resolveExpression(
531 (SymTabAST) expression.getFirstChild(),
532 location,
533 context,
534 referencePhase);
535 }
536 else {
537 // YOU WRITE BAD CODE!
538 }
539 break;
540
541 case TokenTypes.ELIST :
542
543 SymTabAST child = (SymTabAST) (expression.getFirstChild());
544 while (child != null) {
545 if (child.getType() != TokenTypes.COMMA) {
546 resolveExpression(
547 child,
548 location,
549 context,
550 referencePhase);
551 }
552 child = (SymTabAST) (child.getNextSibling());
553 }
554 break;
555
556 case TokenTypes.IDENT :
557 result =
558 resolveIdent(
559 expression,
560 location,
561 context,
562 referencePhase);
563 break;
564
565 case TokenTypes.TYPE :
566 result =
567 resolveType(
568 expression,
569 location,
570 context,
571 referencePhase);
572 break;
573
574 case TokenTypes.METHOD_CALL :
575 //case TokenTypes.SUPER_CTOR_CALL :
576 result =
577 resolveMethod(
578 expression,
579 location,
580 context,
581 referencePhase);
582 break;
583
584 case TokenTypes.LITERAL_THIS :
585 result = resolveLiteralThis(expression, location, context);
586 break;
587
588 case TokenTypes.LITERAL_SUPER :
589 result = resolveLiteralSuper(expression, location, context);
590 break;
591
592 case TokenTypes.DOT :
593 result =
594 resolveDottedName(
595 expression,
596 location,
597 context,
598 referencePhase);
599 break;
600
601 case TokenTypes.LITERAL_NEW :
602 case TokenTypes.CTOR_CALL :
603 case TokenTypes.SUPER_CTOR_CALL :
604 result =
605 resolveNew(
606 expression,
607 location,
608 context,
609 referencePhase);
610 break;
611
612 case TokenTypes.LITERAL_BOOLEAN :
613 case TokenTypes.LITERAL_DOUBLE :
614 case TokenTypes.LITERAL_FLOAT :
615 case TokenTypes.LITERAL_LONG :
616 case TokenTypes.LITERAL_INT :
617 case TokenTypes.LITERAL_SHORT :
618 case TokenTypes.LITERAL_BYTE :
619 case TokenTypes.LITERAL_CHAR :
620 result =
621 resolvePrimitiveType(
622 expression,
623 location,
624 context,
625 referencePhase);
626 break;
627
628 case TokenTypes.NUM_INT :
629 case TokenTypes.NUM_LONG :
630 result = resolveNumInt(expression, location, context);
631 break;
632
633 case TokenTypes.NUM_FLOAT :
634 case TokenTypes.NUM_DOUBLE :
635 result = resolveNumFloat(expression, location, context);
636 break;
637
638 case TokenTypes.STRING_LITERAL :
639 result =
640 resolveStringLiteral(expression, location, context);
641 break;
642
643 case TokenTypes.CHAR_LITERAL :
644 result = resolveCharLiteral(expression, location, context);
645 break;
646
647 case TokenTypes.ASSIGN :
648 case TokenTypes.PLUS_ASSIGN :
649 case TokenTypes.MINUS_ASSIGN :
650 case TokenTypes.STAR_ASSIGN :
651 case TokenTypes.DIV_ASSIGN :
652 case TokenTypes.MOD_ASSIGN :
653 case TokenTypes.SR_ASSIGN :
654 case TokenTypes.BSR_ASSIGN :
655 case TokenTypes.SL_ASSIGN :
656 case TokenTypes.BAND_ASSIGN :
657 case TokenTypes.BXOR_ASSIGN :
658 case TokenTypes.BOR_ASSIGN :
659 resolveAssignment(
660 expression,
661 location,
662 context,
663 referencePhase);
664 break;
665
666 case TokenTypes.LOR :
667 case TokenTypes.LAND :
668 case TokenTypes.NOT_EQUAL :
669 case TokenTypes.EQUAL :
670 case TokenTypes.LT :
671 case TokenTypes.GT :
672 case TokenTypes.LE :
673 case TokenTypes.GE :
674 result =
675 resolveBooleanExpression(
676 expression,
677 location,
678 context,
679 referencePhase);
680 break;
681
682 case TokenTypes.LITERAL_INSTANCEOF :
683 result =
684 resolveInstanceOf(
685 expression,
686 location,
687 context,
688 referencePhase);
689 break;
690
691 case TokenTypes.LITERAL_TRUE :
692 case TokenTypes.LITERAL_FALSE :
693 result =
694 resolveBooleanLiteral(expression, location, context);
695 break;
696
697 case TokenTypes.LNOT :
698 result =
699 resolveBooleanUnary(
700 expression,
701 location,
702 context,
703 referencePhase);
704 break;
705
706 case TokenTypes.INC :
707 case TokenTypes.POST_INC :
708 case TokenTypes.DEC :
709 case TokenTypes.POST_DEC :
710 case TokenTypes.UNARY_PLUS :
711 case TokenTypes.UNARY_MINUS :
712 result =
713 resolveUnaryExpression(
714 expression,
715 location,
716 context,
717 referencePhase);
718 break;
719
720 case TokenTypes.PLUS :
721 case TokenTypes.MINUS :
722 case TokenTypes.DIV :
723 case TokenTypes.STAR :
724 case TokenTypes.BAND :
725 case TokenTypes.BOR :
726 case TokenTypes.BXOR :
727 case TokenTypes.MOD :
728 result =
729 resolveArithmeticExpression(
730 expression,
731 location,
732 context,
733 referencePhase);
734 break;
735
736 case TokenTypes.LITERAL_BREAK :
737 case TokenTypes.LITERAL_CONTINUE :
738 resolveGoto(expression, location, context, referencePhase);
739 break;
740
741 case TokenTypes.LPAREN :
742 result = resolveExpression(
743 //TODO: child || sibling?
744 (SymTabAST) (expression.getNextSibling()),
745 //(SymTabAST) (expression.getFirstChild()),
746 location, context, referencePhase);
747 break;
748
749 case TokenTypes.INDEX_OP :
750 result =
751 resolveArrayAccess(
752 expression,
753 location,
754 context,
755 referencePhase);
756 break;
757
758 case TokenTypes.LITERAL_NULL :
759 result = new NullClass();
760 break;
761
762 case TokenTypes.QUESTION :
763 result =
764 resolveQuestion(
765 expression,
766 location,
767 context,
768 referencePhase);
769 break;
770
771 case TokenTypes.LITERAL_CLASS :
772 result = resolveLiteralClass();
773 break;
774
775 case TokenTypes.ARRAY_INIT :
776 resolveArrayInitializer(
777 expression,
778 location,
779 context,
780 referencePhase);
781 break;
782
783 case TokenTypes.LITERAL_THROW :
784 resolveThrowExpression(
785 expression,
786 location,
787 context,
788 referencePhase);
789 break;
790
791 case TokenTypes.SL :
792 case TokenTypes.SR :
793 case TokenTypes.BSR :
794 result =
795 resolveShiftOperator(
796 expression,
797 location,
798 context,
799 referencePhase);
800 break;
801
802 case TokenTypes.BNOT :
803 resolveBitwiseNot(
804 expression,
805 location,
806 context,
807 referencePhase);
808 break;
809
810 case TokenTypes.LITERAL_ASSERT :
811 // resolveAssert(
812 // expression,
813 // location,
814 // context,
815 // referencePhase);
816 break;
817
818 case TokenTypes.RPAREN :
819 case TokenTypes.EMPTY_STAT :
820 // case TokenTypes.ML_COMMENT:
821 // case TokenTypes.SL_COMMENT:
822 case TokenTypes.VARIABLE_DEF :
823 case TokenTypes.METHOD_DEF :
824 case TokenTypes.CLASS_DEF :
825 case TokenTypes.LITERAL_FOR :
826 case TokenTypes.LITERAL_WHILE :
827 case TokenTypes.LITERAL_IF :
828 case TokenTypes.LITERAL_VOID :
829 // case TokenTypes.LITERAL_INTERFACE:
830 case TokenTypes.LITERAL_DO :
831 case TokenTypes.LITERAL_SWITCH :
832 case TokenTypes.LITERAL_STATIC :
833 case TokenTypes.LITERAL_TRANSIENT :
834 case TokenTypes.LITERAL_NATIVE :
835 // case TokenTypes.LITERAL_threadsafe:
836 case TokenTypes.LITERAL_SYNCHRONIZED :
837 case TokenTypes.LITERAL_VOLATILE :
838 case TokenTypes.LITERAL_TRY :
839 case TokenTypes.LITERAL_CATCH :
840 case TokenTypes.LITERAL_FINALLY :
841 case TokenTypes.LABELED_STAT :
842 case TokenTypes.LCURLY :
843 case TokenTypes.RCURLY :
844 case TokenTypes.SLIST :
845 case TokenTypes.SEMI :
846 case TokenTypes.COMMA :
847 case TokenTypes.ARRAY_DECLARATOR :
848 break;
849
850 default :
851 //TODO: throw exception
852 if (mInitialized) {
853 final Log log =
854 mLogFactory.getInstance(this.getClass());
855 log.error(
856 "Unhandled expression type: "
857 + expression.getType());
858 }
859 break;
860 }
861 }
862 catch (Exception e) {
863
864 result = new UnknownClass(expression.getText(), expression);
865 // TODO: This really should be logged
866 // if (mInitialized) {
867 // final Log log = mLogFactory.getInstance(this.getClass());
868 // log.error("Error resolving near " + expression);
869 // }
870 }
871
872 return result;
873 }
874
875 private IClass resolveTypecast(
876 SymTabAST node,
877 Scope location,
878 IClass context,
879 boolean referencePhase) {
880 SymTabAST typeNode = (SymTabAST) node.getFirstChild();
881 SymTabAST exprNode = (SymTabAST) typeNode.getNextSibling();
882 //handle Checkstyle grammar
883 if (exprNode.getType() == TokenTypes.RPAREN) {
884 exprNode = (SymTabAST) exprNode.getNextSibling();
885 }
886
887 IClass type = null;
888
889 final SymTabAST child = (SymTabAST) typeNode.getFirstChild();
890 // TODO: Checkstyle change.
891 // Do not create references from typecast.
892 // Original transmogrify code is equivalent to
893 // final boolean createReference = referencePhase;
894 // which creates non-existant references for variables.
895 final boolean createReference = false;
896 if (child.getType()
897 == TokenTypes.ARRAY_DECLARATOR) {
898 type =
899 new ArrayDef(
900 resolveType(
901 (SymTabAST) typeNode.getFirstChild(),
902 location,
903 context,
904 createReference));
905 }
906 else {
907 type = resolveType(typeNode, location, context, createReference);
908 }
909
910 resolveExpression(exprNode, location, context, referencePhase);
911 //TODO: Checkstyle change. Can this be ignored?
912 if (type != null) {
913 ((SymTabAST) typeNode.getFirstChild()).setDefinition(
914 type,
915 location,
916 referencePhase);
917 }
918
919 return type;
920 }
921
922 private IClass resolveArrayAccess(
923 SymTabAST node,
924 Scope location,
925 IClass context,
926 boolean referencePhase) {
927
928 SymTabAST arrayNode = (SymTabAST) (node.getFirstChild());
929 SymTabAST exprNode = (SymTabAST) (arrayNode.getNextSibling());
930
931 ArrayDef array =
932 (ArrayDef) resolveExpression(arrayNode,
933 location,
934 context,
935 referencePhase);
936 resolveExpression(exprNode, location, context, referencePhase);
937
938 return array.getType();
939 }
940
941 private IClass resolveLiteralClass() {
942 return new ExternalClass(Class.class);
943 }
944
945 /**
946 * Resolves any dotted reference, returning the <code>Scope</code>
947 * identified by the reference.
948 *
949 * @param tree the root node of the dotted reference
950 * @param location the <code>Scope</code> in which the expression occours.
951 * @param context the <code>Scope</code> in which the search for the
952 * definition will start
953 * @return the <code>Scope</code> indentified by the reference
954 */
955 private IClass resolveDottedName(
956 SymTabAST tree,
957 Scope location,
958 IClass context,
959 boolean referencePhase) {
960 IClass result = null;
961
962 IClass localContext = context;
963 String name = null;
964
965 DotIterator it = new DotIterator(tree);
966 while (it.hasNext()) {
967 SymTabAST node = it.nextNode();
968 if (node.getType() != TokenTypes.COMMA) {
969 localContext =
970 resolveExpression(
971 node,
972 location,
973 localContext,
974 referencePhase);
975 if (localContext == null) {
976 node.setMeaningfulness(false);
977 name = node.getText();
978 while (localContext == null && it.hasNext()) {
979 SymTabAST next = it.nextNode();
980 name = name + "." + next.getText();
981 localContext = location.getClassDefinition(name);
982 if (localContext != null && referencePhase) {
983 next.setDefinition(
984 localContext,
985 location,
986 referencePhase);
987 }
988 else {
989 next.setMeaningfulness(false);
990 }
991 }
992 }
993 }
994 }
995
996 if (localContext != null) {
997 result = localContext;
998 }
999 else {
1000 result = new UnknownClass(name, tree);
1001 }
1002
1003 return result;
1004 }
1005
1006 /**
1007 * Resolves a method call.
1008 *
1009 * @param methodNode the <code>SymTabAST</code> for the METHOD_CALL node
1010 * @param location the <code>Scope</code> where the expression occurs
1011 * @param context the <code>Scope</code> in which the expression occurs
1012 * (where the search for a defintion begins)
1013 * @param referencePhase whether or not this is the reference phase of
1014 * table construction
1015 *
1016 * @return the <code>ClassDef</code> for the type returned by the method
1017 */
1018 private IClass resolveMethod(
1019 SymTabAST methodNode,
1020 Scope location,
1021 IClass context,
1022 boolean referencePhase) {
1023 IClass result = new UnknownClass(methodNode.getText(), methodNode);
1024 IClass newContext = null;
1025
1026 if (context == null) {
1027 newContext = location.getEnclosingClass();
1028 }
1029 else {
1030 newContext = context;
1031 }
1032
1033 String name = null;
1034 boolean createReference = true;
1035
1036 SymTabAST nameNode = (SymTabAST) (methodNode.getFirstChild());
1037 SymTabAST parametersNode = (SymTabAST) (nameNode.getNextSibling());
1038
1039 ISignature signature =
1040 resolveParameters(
1041 parametersNode,
1042 location,
1043 context,
1044 referencePhase);
1045
1046 if (nameNode.getType() == TokenTypes.IDENT) {
1047 name = nameNode.getText();
1048 }
1049 else if (
1050 nameNode.getType() == TokenTypes.LITERAL_SUPER
1051 || (nameNode.getType() == TokenTypes.SUPER_CTOR_CALL)) {
1052 IClass superclass = location.getEnclosingClass().getSuperclass();
1053 newContext = superclass;
1054 name = superclass.getName();
1055 createReference = false;
1056 }
1057 else if (nameNode.getType() == TokenTypes.LITERAL_THIS) {
1058 newContext = location.getEnclosingClass();
1059 name = newContext.getName();
1060 createReference = false;
1061 }
1062 else {
1063 // REDTAG -- doing dotted name resolution on its own
1064 SymTabAST contextNode = (SymTabAST) (nameNode.getFirstChild());
1065 //TODO: handle Checkstyle grammar
1066 nameNode = (SymTabAST) contextNode.getNextSibling();
1067 //skip to IDENT
1068 while (nameNode.getType() != TokenTypes.IDENT) {
1069 nameNode = (SymTabAST) nameNode.getNextSibling();
1070 }
1071
1072 name = nameNode.getText();
1073 newContext =
1074 resolveExpression(
1075 contextNode,
1076 location,
1077 context,
1078 referencePhase);
1079 }
1080
1081 if (newContext != null) {
1082 IMethod method = newContext.getMethodDefinition(name, signature);
1083
1084 if (method != null) {
1085 if (createReference && referencePhase) {
1086 nameNode.setDefinition(method, location, referencePhase);
1087 }
1088 result = method.getType();
1089 }
1090 }
1091
1092 if (result == null) {
1093 result = new UnknownClass(methodNode.getText(), methodNode);
1094 }
1095
1096 return result;
1097 }
1098
1099 /**
1100 * resolves a literal "this"
1101 *
1102 * @param expression the <code>SymTabAST</code> of the expression
1103 * @param location the <code>Scope</code> where the expression occurs
1104 * @param context the <code>Scope</code> in which the expression occurs
1105 * (where the search for a defintion begins)
1106 *
1107 * @return the resulting scope of the expression (the type to which it evaluates)
1108 */
1109 private IClass resolveLiteralThis(
1110 SymTabAST thisNode,
1111 Scope location,
1112 IClass context) {
1113 return location.getEnclosingClass();
1114 }
1115
1116 /**
1117 * resolves a literal "super"
1118 *
1119 * @param expression the <code>SymTabAST</code> of the expression
1120 * @param location the <code>Scope</code> where the expression occurs
1121 * @param context the <code>Scope</code> in which the expression occurs
1122 * (where the search for a defintion begins)
1123 *
1124 * @return the resulting scope of the expression (the type to which it evaluates)
1125 */
1126 private IClass resolveLiteralSuper(
1127 SymTabAST superNode,
1128 Scope location,
1129 IClass context) {
1130 return location.getEnclosingClass().getSuperclass();
1131 }
1132
1133 private boolean newIsConstructor(SymTabAST newNode) {
1134 boolean result = false;
1135
1136 SymTabAST typeNode =
1137 (SymTabAST) (newNode.getFirstChild().getNextSibling());
1138 //handle Checkstyle grammar
1139 if (typeNode.getType() == TokenTypes.LPAREN) {
1140 typeNode = (SymTabAST) typeNode.getNextSibling();
1141 }
1142 if (typeNode.getType() == TokenTypes.ELIST) {
1143 result = true;
1144 }
1145 return result;
1146
1147 }
1148
1149 /**
1150 * resolves and expression of type TokenTypes.TYPE
1151 *
1152 * @param expression the <code>SymTabAST</code> of the expression
1153 * @param location the <code>Scope</code> where the expression occurs
1154 * @param context the <code>Scope</code> in which the expression occurs
1155 * (where the search for a defintion begins)
1156 * @param referencePhase whether or not this is the reference phase of
1157 * table construction
1158 * @return the resulting scope of the expression (the type to which it evaluates)
1159 * @see #resolveDottedName(SymTabAST, Scope, IClass, boolean)
1160 * @see #resolveClassIdent(SymTabAST, Scope, IClass, boolean)
1161 */
1162 public IClass resolveType(
1163 SymTabAST expr,
1164 Scope location,
1165 IClass context,
1166 boolean referencePhase) {
1167 IClass result = null;
1168 SymTabAST nameNode = (SymTabAST) expr.getFirstChild();
1169
1170 // TODO: Checkstyle change.
1171 // Do not create references from typecast.
1172 // Original transmogrify code is equivalent to
1173 // final boolean createReference = referencePhase;
1174 // which creates non-existant references for variables.
1175 final boolean createReference = false;
1176 if (nameNode.getType() == TokenTypes.DOT) {
1177 result =
1178 resolveDottedName(nameNode, location, context, createReference);
1179 }
1180 else {
1181 result =
1182 resolveClassIdent(nameNode, location, context, createReference);
1183 }
1184
1185 return result;
1186 }
1187
1188 /**
1189 * resolves Class type expression
1190 * @param expr node to be resolved
1191 * @param location scope of the <code>expr</code>
1192 * @param context context of the <code>expr</code> if exists
1193 * @param referencePhase <code>true</code> if this method is used to during
1194 * finding reference phase
1195 * <code>false</code> otherwise
1196 * @return <code>IClass</code> representing the type to which the
1197 * expression evalutes.
1198 * @see #resolveDottedName(SymTabAST, Scope, IClass, boolean)
1199 */
1200 public IClass resolveClass(
1201 SymTabAST expr,
1202 Scope location,
1203 IClass context,
1204 boolean referencePhase) {
1205
1206 IClass result =
1207 resolveDottedName(expr, location, context, referencePhase);
1208 if (result != null && referencePhase) {
1209 expr.setDefinition(result, location, referencePhase);
1210 }
1211
1212 return result;
1213 }
1214
1215 /**
1216 * resolves expression with <code>JavaTokenTypes<code> other than <code>DOT</code>
1217 * @param expr expression to be resolved
1218 * @param location scope of the expression
1219 * @param context context of the expression if any
1220 * @param referencePhase <code>true</code> if this method is used to during
1221 * finding reference phase
1222 * <code>false</c