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: //
010:
011: package de.uka.ilkd.key.java;
012:
013: import java.io.IOException;
014: import java.io.StringWriter;
015:
016: import de.uka.ilkd.key.java.declaration.ArrayOfTypeDeclaration;
017: import de.uka.ilkd.key.java.declaration.TypeDeclaration;
018: import de.uka.ilkd.key.java.declaration.TypeDeclarationContainer;
019: import de.uka.ilkd.key.java.visitor.Visitor;
020: import de.uka.ilkd.key.util.ExtList;
021:
022: /**
023: * A node representing a single source file containing
024: * {@link TypeDeclaration}s and an optional {@link PackageSpecification}
025: * and an optional set of {@link Import}s. In Java, any source file
026: * may contain at most one public class type definition.
027: * This class is taken from COMPOST and changed so that it can be
028: * used as an immutable class
029: */
030:
031: public class CompilationUnit extends JavaNonTerminalProgramElement
032: implements TypeDeclarationContainer, TypeScope {
033:
034: /**
035: * Package spec.
036: */
037:
038: protected final PackageSpecification packageSpec;
039:
040: /**
041: * Imports.
042: */
043:
044: protected final ArrayOfImport imports;
045:
046: /**
047: * Type declarations.
048: */
049: protected final ArrayOfTypeDeclaration typeDeclarations;
050:
051: /** creates a compilation unit
052: * @param packageSpec a PackageSpecification (pck of this CU)
053: * @param imports an array of Import (all it imports)
054: * @param typeDeclarations an array of TypeDeclaration (the
055: * type declared in it)
056: */
057: public CompilationUnit(PackageSpecification packageSpec,
058: Import[] imports, TypeDeclaration[] typeDeclarations) {
059: this .packageSpec = packageSpec;
060: this .imports = new ArrayOfImport(imports);
061: this .typeDeclarations = new ArrayOfTypeDeclaration(
062: typeDeclarations);
063: }
064:
065: /** creates a compilation unit
066: * @param children list with the children of this unit
067: */
068: public CompilationUnit(ExtList children) {
069: super (children);
070: packageSpec = (PackageSpecification) children
071: .get(PackageSpecification.class);
072: this .imports = new ArrayOfImport((Import[]) children
073: .collect(Import.class));
074: this .typeDeclarations = new ArrayOfTypeDeclaration(
075: (TypeDeclaration[]) children
076: .collect(TypeDeclaration.class));
077: }
078:
079: public SourceElement getFirstElement() {
080: return (getChildCount() > 0) ? getChildAt(0).getFirstElement()
081: : this ;
082: }
083:
084: public SourceElement getLastElement() {
085: return typeDeclarations.getTypeDeclaration(typeDeclarations
086: .size() - 1);
087: }
088:
089: /**
090: * Get name of the unit. The name is empty if no data location is set;
091: * otherwise, the name of the current data location is returned.
092: * @return the name of this compilation unit.
093: *
094: */
095: public String getName() {
096: return ""; //(location == null) ? "" : location.toString();
097: }
098:
099: /**
100: * Returns the number of children of this node.
101: * @return an int giving the number of children of this node
102: */
103:
104: public int getChildCount() {
105: int result = 0;
106: if (packageSpec != null)
107: result++;
108: if (imports != null)
109: result += imports.size();
110: if (typeDeclarations != null)
111: result += typeDeclarations.size();
112: return result;
113: }
114:
115: /**
116: * Returns the child at the specified index in this node's "virtual"
117: * child array
118: * @param index an index into this node's "virtual" child array
119: * @return the program element at the given position
120: * @exception ArrayIndexOutOfBoundsException if <tt>index</tt> is out
121: * of bounds
122: */
123:
124: public ProgramElement getChildAt(int index) {
125: int len;
126: if (packageSpec != null) {
127: if (index == 0)
128: return packageSpec;
129: index--;
130: }
131: if (imports != null) {
132: len = imports.size();
133: if (len > index) {
134: return imports.getImport(index);
135: }
136: index -= len;
137: }
138: if (typeDeclarations != null) {
139: return typeDeclarations.getTypeDeclaration(index);
140: }
141: throw new ArrayIndexOutOfBoundsException();
142: }
143:
144: /**
145: * Get imports.
146: * @return the wrapped import array.
147: */
148:
149: public ArrayOfImport getImports() {
150: return imports;
151: }
152:
153: /**
154: * Get package specification.
155: * @return the package specification.
156: */
157:
158: public PackageSpecification getPackageSpecification() {
159: return packageSpec;
160: }
161:
162: /**
163: * Get the number of type declarations in this container.
164: * @return the number of type declarations.
165: */
166:
167: public int getTypeDeclarationCount() {
168: return (typeDeclarations != null) ? typeDeclarations.size() : 0;
169: }
170:
171: /*
172: Return the type declaration at the specified index in this node's
173: "virtual" type declaration array.
174: @param index an index for a type declaration.
175: @return the type declaration with the given index.
176: @exception ArrayIndexOutOfBoundsException if <tt>index</tt> is out
177: of bounds.
178: */
179:
180: public TypeDeclaration getTypeDeclarationAt(int index) {
181: if (typeDeclarations != null) {
182: return typeDeclarations.getTypeDeclaration(index);
183: }
184: throw new ArrayIndexOutOfBoundsException();
185: }
186:
187: /**
188: * Get declarations.
189: * @return the wrapped array of type declarations .
190: */
191: public ArrayOfTypeDeclaration getDeclarations() {
192: return typeDeclarations;
193: }
194:
195: /**
196: * Gets the primary type declaration of the compilation unit.
197: * The primary declaration is the first declaration of the unit,
198: * or the single public declaration. If there is no unambiguous primary
199: * declaration, this method returns <CODE>null</CODE>.
200: */
201:
202: public TypeDeclaration getPrimaryTypeDeclaration() {
203: TypeDeclaration res = null;
204: int s = typeDeclarations.size();
205: for (int i = 0; i < s; i += 1) {
206: TypeDeclaration t = typeDeclarations.getTypeDeclaration(i);
207: if (t.isPublic()) {
208: if (res == null || !res.isPublic()) {
209: res = t;
210: } else {
211: res = null;
212: break;
213: }
214: } else {
215: if (res == null) {
216: res = t;
217: }
218: }
219: }
220: return res;
221: }
222:
223: public void prettyPrint(PrettyPrinter p) throws java.io.IOException {
224: p.printCompilationUnit(this );
225: }
226:
227: /** calls the corresponding method of a visitor in order to
228: * perform some action/transformation on this element
229: * @param v the Visitor
230: */
231: public void visit(Visitor v) {
232: v.performActionOnCompilationUnit(this );
233: }
234:
235: /** toString */
236: public String toString() {
237: StringWriter sw = new StringWriter();
238: try {
239: PrettyPrinter pp = new PrettyPrinter(sw);
240: pp.setIndentationLevel(3);
241: prettyPrint(pp);
242: } catch (IOException e) {
243: System.err
244: .println("Pretty printing of compilation unit failed");
245: System.err.println("Due to " + e);
246: e.printStackTrace();
247: }
248: return sw.toString();
249: }
250:
251: }
|