001: // This file is part of KeY - Integrated Deductive Software Design
002: // Copyright (C) 2001-2007 Universitaet Karlsruhe, Germany
003: // Universitaet Koblenz-Landau, Germany
004: // Chalmers University of Technology, Sweden
005: //
006: // The KeY system is protected by the GNU General Public License.
007: // See LICENSE.TXT for details.
008: //
009: // This file is part of KeY - Integrated Deductive Software Design
010: // Copyright (C) 2001-2004 Universitaet Karlsruhe, Germany
011: // Universitaet Koblenz-Landau, Germany
012: // Chalmers University of Technology, Sweden
013: //
014: // The KeY system is protected by the GNU General Public License.
015: // See LICENSE.TXT for details.
016: package de.uka.ilkd.key.java.recoderext;
017:
018: import recoder.CrossReferenceServiceConfiguration;
019: import recoder.abstraction.ClassType;
020: import recoder.java.Identifier;
021: import recoder.java.declaration.ClassDeclaration;
022: import recoder.java.declaration.FieldDeclaration;
023: import recoder.java.declaration.TypeDeclaration;
024: import recoder.java.declaration.modifier.Private;
025: import recoder.java.declaration.modifier.Public;
026: import recoder.java.declaration.modifier.Static;
027: import recoder.java.reference.TypeReference;
028: import recoder.kit.ProblemReport;
029: import recoder.list.CompilationUnitMutableList;
030: import recoder.list.ModifierArrayList;
031: import recoder.list.ModifierMutableList;
032: import de.uka.ilkd.key.util.Debug;
033:
034: /**
035: * The Java DL requires some implicit fields and methods, that are
036: * available in each Java class. The name of the implicit fields/methods
037: * is usually enclosed between two angle brackets. To access them in a
038: * uniform way, they are added as usual fields to the classes, in
039: * particular this makes it possible to parse them in a natural way.
040: * The ImplicitFieldAdder is responsible to add all implicit fields to
041: * the type declarations of the model. As the implicit methods and only
042: * them will access these fields, this transformer has to be executed
043: * before the other transformers are called.
044: */
045: public class ImplicitFieldAdder extends RecoderModelTransformer {
046:
047: public static final String IMPLICT_ARRAY_TRA_INITIALIZED = "<traInitialized>";
048:
049: public static final String IMPLICIT_CLASS_PREPARED = "<classPrepared>";
050: public static final String IMPLICIT_CLASS_INITIALIZED = "<classInitialized>";
051: public static final String IMPLICIT_CLASS_INIT_IN_PROGRESS = "<classInitializationInProgress>";
052: public static final String IMPLICIT_CLASS_ERRONEOUS = "<classErroneous>";
053:
054: public static final String IMPLICIT_NEXT_TO_CREATE = "<nextToCreate>";
055: public static final String IMPLICIT_CREATED = "<created>";
056:
057: public static final String IMPLICIT_INITIALIZED = "<initialized>";
058: public static final String IMPLICIT_TRANSIENT = "<transient>";
059:
060: /** flag set if java.lang.Object has been already transformed */
061: private boolean transformedObject = false;
062: private ClassType javaLangObject;
063:
064: /**
065: * creates a transformation that adds all implicit fields,
066: * for example <code><created></code>,
067: * <code><initialized></code> and
068: * <code><nextToCreate></code> etc.
069: * @param services the CrossReferenceServiceConfiguration to access
070: * model information
071: * @param units the array of CompilationUnits describing the model
072: * to be transformed
073: */
074: public ImplicitFieldAdder(
075: CrossReferenceServiceConfiguration services,
076: CompilationUnitMutableList units) {
077: super (services, units);
078: }
079:
080: /**
081: * creates an implicit field of the given type and name
082: * @param typeName the name of the type of the new field to create
083: * @param fieldName the name of the field
084: * @param isStatic a boolean that is true if the field has to be
085: * created as static (class) field
086: * @return the new created field declaration
087: */
088: public static FieldDeclaration createImplicitRecoderField(
089: String typeName, String fieldName, boolean isStatic,
090: boolean isPrivate) {
091:
092: ModifierMutableList modifiers = new ModifierArrayList(
093: 1 + (isStatic ? 1 : 0));
094:
095: if (isStatic) {
096: modifiers.add(new Static());
097: }
098: if (isPrivate) {
099: modifiers.add(new Private());
100: } else {
101: modifiers.add(new Public());
102: }
103:
104: Identifier id = typeName.charAt(0) == '<' ? new ImplicitIdentifier(
105: typeName)
106: : new Identifier(typeName);
107:
108: FieldDeclaration fd = new FieldDeclaration(modifiers,
109: new TypeReference(id),
110: new ImplicitIdentifier(fieldName), null);
111:
112: fd.makeAllParentRolesValid();
113:
114: return fd;
115: }
116:
117: /**
118: * The implicit fields divide up into two categories. Global fields
119: * declared just in java.lang.Object and type specific one declared
120: * in each reference type. This method adds the global ones.
121: */
122: private void addGlobalImplicitRecoderFields(TypeDeclaration td) {
123: // instance
124: attach(createImplicitRecoderField("byte", IMPLICIT_TRANSIENT,
125: false, false), td, 0);
126: attach(createImplicitRecoderField("boolean",
127: IMPLICIT_INITIALIZED, false, false), td, 0);
128: attach(createImplicitRecoderField("boolean", IMPLICIT_CREATED,
129: false, false), td, 0);
130: }
131:
132: /**
133: * adds implicit fields to the given type declaration
134: * @param td the recoder.java.TypeDeclaration to be enriched with
135: * implicit fields
136: */
137: private void addImplicitRecoderFields(
138: recoder.java.declaration.TypeDeclaration td) {
139:
140: // static
141: String className = td.getName();
142: if (className == null) {
143: Debug
144: .out("makeImplicitMembersExplicit: anonymous class will not add"
145: + "implicit fields");
146: return;
147: }
148: attach(createImplicitRecoderField("boolean",
149: IMPLICIT_CLASS_INIT_IN_PROGRESS, true, true), td, 0);
150: attach(createImplicitRecoderField("boolean",
151: IMPLICIT_CLASS_ERRONEOUS, true, true), td, 0);
152: attach(createImplicitRecoderField("boolean",
153: IMPLICIT_CLASS_INITIALIZED, true, true), td, 0);
154: attach(createImplicitRecoderField("boolean",
155: IMPLICIT_CLASS_PREPARED, true, true), td, 0);
156:
157: if (!td.isInterface() && !td.isAbstract()) {
158: attach(createImplicitRecoderField("int",
159: IMPLICIT_NEXT_TO_CREATE, true, true), td, 0);
160: }
161: }
162:
163: public ProblemReport analyze() {
164: javaLangObject = services.getNameInfo().getJavaLangObject();
165: if (!(javaLangObject instanceof ClassDeclaration)) {
166: Debug
167: .fail("Could not find class java.lang.Object or only as bytecode");
168: }
169: return super .analyze();
170: }
171:
172: protected void makeExplicit(TypeDeclaration td) {
173:
174: addImplicitRecoderFields(td);
175:
176: int typeCount = td.getTypeDeclarationCount();
177: for (int j = 0; j < typeCount; j++) {
178: makeExplicit(td.getTypeDeclarationAt(j));
179: }
180:
181: if (!transformedObject && td == javaLangObject) {
182: addGlobalImplicitRecoderFields(td);
183: transformedObject = true;
184: }
185: td.makeAllParentRolesValid();
186: // if (td instanceof ClassDeclaration) {
187: // java.io.StringWriter sw = new java.io.StringWriter();
188: // services.getProgramFactory().getPrettyPrinter(sw).visitClassDeclaration((ClassDeclaration)td);
189: // System.out.println(sw.toString());
190: // try { sw.close(); } catch (Exception e) {}
191: // }
192:
193: }
194: }
|