001: // You can redistribute this software and/or modify it under the terms of
002: // the Infozone Software License version 2 published by the Infozone Group
003: // (http://www.infozone-group.org).
004: //
005: // Copyright (C) @year@ by The Infozone Group. All rights reserved.
006: //
007: // $Id: ExpressionHelper.java,v 1.1 2002/05/10 08:59:12 per_nyfelt Exp $
008:
009: package org.infozone.tools.janalyzer;
010:
011: import koala.dynamicjava.parser.wrapper.*; //import koala.dynamicjava.interpreter.context.wrapper.*;
012: import koala.dynamicjava.interpreter.context.*;
013: import koala.dynamicjava.interpreter.*;
014: import koala.dynamicjava.tree.*;
015: import koala.dynamicjava.tree.visitor.*;
016:
017: import java.util.List;
018: import java.util.ListIterator;
019: import java.io.FileReader;
020: import java.io.Serializable;
021: import java.util.Vector;
022:
023: /**
024: * This class is a part of the JavaCodeAnalyzer class.
025: * It's out sourced to lower the pure mass of data in the analyzer class.
026: * Are subclasses of expression, type, condition from package koala.dynamicjava.tree
027: * handled here.
028: *
029: * <pre>
030: *
031: * TODO:
032: * - more documentation
033: * - metric'S
034: * - method counting and so on
035: * </pre>
036: *
037: * @version $Revision: 1.1 $ $Date: 2002/05/10 08:59:12 $
038: * @author <a href="http://www.softwarebuero.de">SMB</a>
039: * @see org.infozone.janalyzer.JavaCodeAnalyzer
040: */
041: public final class ExpressionHelper extends java.lang.Object {
042:
043: //
044: // data
045: //
046:
047: /** The output class */
048: private JavaCodeOutput jco;
049: /** The Analyzer class for analyzing bugs */
050: private JavaCodeAnalyzer jca;
051: /** The level to help correct parentheses to binary expressions */
052: private int currentBinaryExpressionLevel = 0;
053:
054: public ExpressionHelper(JavaCodeAnalyzer aAnalyzer,
055: JavaCodeOutput aOutputClass) {
056: jca = aAnalyzer;
057: // output class
058: jco = aOutputClass;
059: }
060:
061: /**
062: * The representation of a Expression.
063: *
064: */
065: private void addExpressionString(Expression aExp) {
066: // printLog("addExpression"+aExp);
067: // System.err.println("addExpression" + aExp);
068: if (aExp == null) {
069: return;
070: }
071: // ....§1§....
072: if (aExp instanceof StringLiteral) {
073: jca
074: .addToOut(jco.mask(((Literal) aExp)
075: .getRepresentation()));
076: return;
077: }
078: if (aExp instanceof Literal) {
079: jca.addToOut(((Literal) aExp).getRepresentation());
080: return;
081: }
082: // this.method()
083: if (aExp instanceof ThisExpression) {
084: jca.addToOut("this");
085: return;
086: }
087: // (String)object
088: if (aExp instanceof CastExpression) {
089: CastExpression cas = (CastExpression) aExp;
090: jca
091: .addToOut("(" + getTypeString(cas.getTargetType())
092: + ")");
093: if (ConstantsManager
094: .getExpressionLevel(cas.getExpression()) < ConstantsManager
095: .getExpressionLevel(cas)) {
096: jca.addToOut("(");
097: addSuperConditionString(cas.getExpression());
098: jca.addToOut(")");
099: } else {
100: addSuperConditionString(cas.getExpression());
101: }
102: return;
103: }
104: // String.class
105: if (aExp instanceof TypeExpression) {
106: jca.addToOut(getTypeString(((TypeExpression) aExp)
107: .getType())
108: + ".class");
109: return;
110: }
111: // [5]
112: if (aExp instanceof ArrayAccess) {
113: ArrayAccess aa = (ArrayAccess) aExp;
114: if (ConstantsManager.getExpressionLevel(aa.getExpression()) < ConstantsManager
115: .getExpressionLevel(aa)) {
116: jca.addToOut("(");
117: addExpressionString(aa.getExpression());
118: jca.addToOut(")");
119: } else {
120: addExpressionString(aa.getExpression());
121: }
122: jca.addToOut("[");
123: addExpressionString(aa.getCellNumber());
124: jca.addToOut("]");
125: return;
126: }
127: // ...[] = {1,2,3}
128: if (aExp instanceof ArrayInitializer) {
129: ArrayInitializer ai = (ArrayInitializer) aExp;
130: if (ai.getCells() != null) {
131: // ...[] = {1,2,3}
132: jca.addToOut(jco.getLowSplitLevel() + "{");
133: ListIterator it = ai.getCells().listIterator();
134: while (it.hasNext()) {
135: addExpressionString((Expression) it.next());
136: jca.addToOut(", ");
137: }
138: if (jca.getOut().endsWith(", ")) {
139: jca.setToOut(jca.getOut().substring(0,
140: jca.getOut().length() - 2));
141: }
142: }
143: jca.addToOut("}");
144: return;
145: }
146: // a = (a<b)?c:d;
147: if (aExp instanceof ConditionalExpression) {
148: addConditionString(((ConditionalExpression) aExp)
149: .getConditionExpression());
150: jca.addToOut(" " + jco.getObligateSplitLevel() + "? ");
151: addExpressionString(((ConditionalExpression) aExp)
152: .getIfTrueExpression());
153: jca.addToOut(" " + jco.getObligateSplitLevel() + ": ");
154: addExpressionString(((ConditionalExpression) aExp)
155: .getIfFalseExpression());
156: return;
157: }
158: // a || b
159: if (aExp instanceof BinaryExpression) {
160: // printLog("BinaryExpression "+(++parenLevel));
161: BinaryExpression be = (BinaryExpression) aExp;
162: if (ConstantsManager.getExpressionLevel(be
163: .getLeftExpression()) < ConstantsManager
164: .getExpressionLevel(be)) {
165: jca.addToOut("(");
166: addConditionString(be.getLeftExpression());
167: jca.addToOut(")");
168: } else {
169: addConditionString(be.getLeftExpression());
170: }
171: jca
172: .addToOut(" "
173: + jco.getLowSplitLevel()
174: + ConstantsManager
175: .getBinaryExpressionString((Expression) aExp)
176: + " ");
177: // algebraic subtract sign needs parens
178: if (ConstantsManager.getExpressionLevel(be
179: .getRightExpression()) < ConstantsManager
180: .getExpressionLevel(be)
181: || be.getRightExpression() instanceof SubtractExpression
182: && be.getRightExpression() instanceof BinaryExpression) {
183: jca.addToOut("(");
184: addConditionString(be.getRightExpression());
185: jca.addToOut(")");
186: } else {
187: addConditionString(be.getRightExpression());
188: }
189: return;
190: }
191: //
192: if (aExp instanceof QualifiedName) {
193: jca.addToOut(((QualifiedName) aExp).getRepresentation());
194: return;
195: }
196: // Modifer.VOLATILE
197: if (aExp instanceof ObjectFieldAccess) {
198: ObjectFieldAccess ofa = (ObjectFieldAccess) aExp;
199: if (ofa.getExpression() != null) {
200: // extra parenthesis needed
201: if (ConstantsManager.getExpressionLevel(ofa
202: .getExpression()) < ConstantsManager
203: .getExpressionLevel(ofa)) {
204: jca.addToOut("(");
205: addConditionString(ofa.getExpression());
206: jca.addToOut(").");
207: } else {
208: addConditionString(ofa.getExpression());
209: jca.addToOut(".");
210: }
211: }
212: jca.addToOut(ofa.getFieldName());
213: return;
214: }
215: // super.fiild
216: if (aExp instanceof SuperFieldAccess) {
217: jca.addToOut("super."
218: + ((SuperFieldAccess) aExp).getFieldName());
219: return;
220: }
221:
222: // super method call
223: if (aExp instanceof SuperMethodCall) {
224: SuperMethodCall mc = (SuperMethodCall) aExp;
225: jca.addToOut("super." + mc.getMethodName() + "(");
226: addConditionListString(mc.getArguments());
227: jca.addToOut(")");
228: // jca.printOut(out+";");
229: return;
230: }
231:
232: // instanceof
233: if (aExp instanceof InstanceOfExpression) {
234: InstanceOfExpression iop = (InstanceOfExpression) aExp;
235: if (ConstantsManager
236: .getExpressionLevel(iop.getExpression()) < ConstantsManager
237: .getExpressionLevel(iop)) {
238: jca.addToOut("(");
239: addConditionString(iop.getExpression());
240: jca.addToOut(")");
241: } else {
242: addConditionString(iop.getExpression());
243: }
244: jca.addToOut(" instanceof "
245: + getTypeString(iop.getReferenceType()));
246: return;
247: }
248:
249: // allocations
250: // simple
251: if (aExp instanceof SimpleAllocation) {
252: SimpleAllocation sa = (SimpleAllocation) aExp;
253: jca.addToOut("new " + getTypeString(sa.getCreationType())
254: + "(");
255: addConditionListString(sa.getArguments());
256: jca.addToOut(")");
257: return;
258: }
259: // array
260: if (aExp instanceof ArrayAllocation) {
261: ArrayAllocation sa = (ArrayAllocation) aExp;
262: // direct initialization with {1,2,3}
263: if (sa.getInitialization() == null) {
264: jca.addToOut("new "
265: + getTypeString(sa.getCreationType()));
266: ListIterator it = sa.getSizes().listIterator();
267: int i = 0;
268: while (it.hasNext()) {
269: jca.addToOut("[");
270: addExpressionString((Expression) it.next());
271: jca.addToOut("]");
272: i++;
273: }
274: for (; i < sa.getDimension(); i++) {
275: jca.addToOut("[]");
276: }
277: } else {
278: jca.addToOut("new "
279: + getTypeString(sa.getCreationType()));
280: for (int i = 0; i < sa.getDimension(); i++) {
281: jca.addToOut("[]");
282: }
283: jca.addToOut(" ");
284: addExpressionString(sa.getInitialization());
285: }
286: return;
287: }
288: // operators
289: // increment
290: if (aExp instanceof PreIncrement) {
291: jca.addToOut("++");
292: addConditionString(((PreIncrement) aExp).getExpression());
293: return;
294: }
295: if (aExp instanceof PostIncrement) {
296: addConditionString(((PostIncrement) aExp).getExpression());
297: jca.addToOut("++");
298: return;
299: }
300: // decrement
301: if (aExp instanceof PreDecrement) {
302: jca.addToOut("--");
303: addConditionString(((PreDecrement) aExp).getExpression());
304: return;
305: }
306: if (aExp instanceof PostDecrement) {
307: addConditionString(((PostDecrement) aExp).getExpression());
308: jca.addToOut("--");
309: return;
310: }
311: // not
312: if (aExp instanceof NotExpression) {
313: NotExpression no = (NotExpression) aExp;
314: jca.addToOut("!");
315: if (ConstantsManager.getExpressionLevel(no.getExpression()) < ConstantsManager
316: .getExpressionLevel(no)) {
317: jca.addToOut("(");
318: addConditionString(no.getExpression());
319: jca.addToOut(")");
320: } else {
321: addConditionString(no.getExpression());
322: }
323: return;
324: }
325: // complement
326: if (aExp instanceof ComplementExpression) {
327: ComplementExpression no = (ComplementExpression) aExp;
328: jca.addToOut("~");
329: if (ConstantsManager.getExpressionLevel(no.getExpression()) < ConstantsManager
330: .getExpressionLevel(no)) {
331: jca.addToOut("(");
332: addConditionString(no.getExpression());
333: jca.addToOut(")");
334: } else {
335: addConditionString(no.getExpression());
336: }
337: return;
338: }
339: // +1
340: if (aExp instanceof PlusExpression) {
341: PlusExpression pe = (PlusExpression) aExp;
342: jca.addToOut("+");
343: if (ConstantsManager.getExpressionLevel(pe.getExpression()) < ConstantsManager
344: .getExpressionLevel(pe)) {
345: jca.addToOut("(");
346: addConditionString(pe.getExpression());
347: jca.addToOut(")");
348: } else {
349: addConditionString(pe.getExpression());
350: }
351: return;
352: }
353: // -1
354: if (aExp instanceof MinusExpression) {
355: MinusExpression me = (MinusExpression) aExp;
356: jca.addToOut("-");
357: if (ConstantsManager.getExpressionLevel(me.getExpression()) < ConstantsManager
358: .getExpressionLevel(me)) {
359: jca.addToOut("(");
360: addConditionString(me.getExpression());
361: jca.addToOut(")");
362: } else {
363: addConditionString(me.getExpression());
364: }
365: return;
366: }
367: // inner class invoked by object method call
368: if (aExp instanceof ClassAllocation) {
369: // jco.setStartLineNumber(aExp.getBeginLine());
370: // jco.setLastLineNumber(aExp.getEndLine());
371: ClassAllocation classNode = (ClassAllocation) aExp;
372: // jco.printClassComment(classNode);
373: // class
374: jca.addToOut("new "
375: + getTypeString(classNode.getCreationType()) + "(");
376: // arguments
377: addConditionListString(classNode.getArguments());
378: jca.addToOut(") {");
379: jca.printOut();
380: // class members
381: ListIterator it = classNode.getMembers().listIterator();
382: jco.increaseIndent();
383: while (it.hasNext()) {
384: jca.parseObject((Node) it.next());
385: }
386: jco.setCommentEnd(aExp.getEndLine());
387: jco.printComment();
388: jco.setCommentStart(aExp.getEndLine());
389:
390: // jco.printEndComment((Node)aExp);
391: jco.decreaseIndent();
392: // jco.setStartLineNumber(aExp.getEndLine());
393: jca.setToOut("}");
394: return;
395: }
396: //
397: if (aExp instanceof ObjectMethodCall) {
398: ObjectMethodCall mc = (ObjectMethodCall) aExp;
399: // String ret = "";
400: if (mc.getExpression() != null) {
401: // extra parenthesis needed
402: if (ConstantsManager.getExpressionLevel(mc
403: .getExpression()) < ConstantsManager
404: .getExpressionLevel(mc)) {
405: jca.addToOut("(");
406: // jca.parseObject(mc.getExpression());
407: addConditionString(mc.getExpression());
408: jca.addToOut(").");
409: } else {
410: addConditionString(mc.getExpression());
411: jca.addToOut(".");
412: }
413: }
414: jca.addToOut(mc.getMethodName() + "(");
415: addConditionListString(mc.getArguments());
416: jca.addToOut(")");
417: return;
418: }
419:
420: printErr(aExp, "getExpression Expression " + aExp
421: + " not found on line " + aExp.getBeginLine());
422: }
423:
424: /**
425: * Help method to encapsulate a often used loop.
426: *
427: * @return A String consist of several Strings in a List separated by
428: * ',MiddlePlitLevel ' with a LowSplitLevel if more than one element in it
429: *
430: */
431: protected void addConditionListString(List aList) {
432: addConditionListString(aList, true);
433: }
434:
435: protected void addConditionListString(List aList,
436: boolean trailingSpace) {
437: boolean findSome = false;
438: if (aList != null) {
439: // if (aList.size()>1) {
440: jca.addToOut(jco.getLowSplitLevel());
441: // }
442: ListIterator it = aList.listIterator();
443: while (it.hasNext()) {
444: findSome = true;
445: jca.addToOut(" ");
446: addConditionString((Expression) it.next());
447: jca.addToOut("," + jco.getMiddleSplitLevel());
448: }
449: }
450: if (jca.getOut().endsWith("," + jco.getMiddleSplitLevel())) {
451: jca.setToOut(jca.getOut().substring(
452: 0,
453: jca.getOut().length()
454: - ("," + jco.getMiddleSplitLevel())
455: .length()));
456: }
457: if (findSome && trailingSpace) {
458: jca.addToOut(" ");
459: }
460: }
461:
462: /**
463: * Inner conditions BinaryExpressions should have brackets.
464: *
465: */
466: public void addConditionString(Expression aExp) {
467: /*
468: * if (aExp instanceof BinaryExpression) {
469: boolean parens = false;
470: if (ConstantsManager.getBinaryExpressionLevel(
471: (BinaryExpression)aExp) < currentBinaryExpressionLevel) {
472: parens = true;
473: } else {
474: // save for next recursion
475: currentBinaryExpressionLevel =
476: ConstantsManager.getBinaryExpressionLevel(
477: (BinaryExpression)aExp);
478: }
479: // printLog("getExpressionString() "+currentBinaryExpressionLevel);
480: if (parens) {
481: jca.addToOut("(");
482: addExpressionString(aExp);
483: jca.addToOut(")");
484: } else {
485: addExpressionString(aExp);
486: }
487: * } else {
488: */
489: addExpressionString(aExp);
490: }
491:
492: /**
493: * BinaryExpression without brackets
494: *
495: */
496: public void addSuperConditionString(Expression aExp) {
497: currentBinaryExpressionLevel = 0;
498: addExpressionString(aExp);
499: }
500:
501: /**
502: * The representation of a Type.
503: *
504: */
505: protected String getTypeString(Type aType) {
506: if (aType instanceof ReferenceType) {
507: return ((ReferenceType) aType).getRepresentation();
508: }
509: if (aType instanceof PrimitiveType) {
510: return ((PrimitiveType) aType).getValue() + "";
511: }
512: if (aType instanceof ArrayType) {
513: return getTypeString(((ArrayType) aType).getElementType())
514: + "[]";
515: }
516: printErr(aType, "getTypeString Type " + aType
517: + " not found on line " + aType.getBeginLine());
518: return null;
519: }
520:
521: /**
522: * This method logs warnings on code violations.
523: * @param aLine
524: *
525: */
526: private void printLog(Node aNode, String aLine) {
527: System.err.println(getClass() + " Log line "
528: + aNode.getBeginLine() + ": " + aLine);
529: }
530:
531: private void printLog(String aLine) {
532: System.err.println(getClass() + " Log: " + aLine);
533: }
534:
535: /**
536: * This method print debug messages.
537: * @param aLine
538: *
539: */
540: private void printErr(Node aNode, String aLine) {
541: System.err.println(getClass() + " ERROR: " + aLine);
542: }
543: }
|