001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.corext.codemanipulation;
011:
012: import java.util.ArrayList;
013: import java.util.List;
014:
015: import org.eclipse.text.edits.MultiTextEdit;
016: import org.eclipse.text.edits.TextEdit;
017:
018: import org.eclipse.core.runtime.CoreException;
019: import org.eclipse.core.runtime.IProgressMonitor;
020: import org.eclipse.core.runtime.NullProgressMonitor;
021: import org.eclipse.core.runtime.SubProgressMonitor;
022: import org.eclipse.core.runtime.jobs.ISchedulingRule;
023:
024: import org.eclipse.core.resources.IWorkspaceRunnable;
025: import org.eclipse.core.resources.ResourcesPlugin;
026:
027: import org.eclipse.jdt.core.ICompilationUnit;
028: import org.eclipse.jdt.core.dom.AST;
029: import org.eclipse.jdt.core.dom.ASTNode;
030: import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
031: import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
032: import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
033: import org.eclipse.jdt.core.dom.CompilationUnit;
034: import org.eclipse.jdt.core.dom.IMethodBinding;
035: import org.eclipse.jdt.core.dom.ITypeBinding;
036: import org.eclipse.jdt.core.dom.MethodDeclaration;
037: import org.eclipse.jdt.core.dom.Modifier;
038: import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
039: import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
040: import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
041:
042: import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
043:
044: import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
045:
046: /**
047: * Workspace runnable to add unimplemented constructors.
048: *
049: * @since 3.1
050: */
051: public final class AddUnimplementedConstructorsOperation implements
052: IWorkspaceRunnable {
053:
054: /** Should the resulting edit be applied? */
055: private final boolean fApply;
056:
057: /** The qualified names of the generated imports */
058: private String[] fCreatedImports;
059:
060: /** The method binding keys for which a constructor was generated */
061: private final List fCreatedMethods = new ArrayList();
062:
063: /** Should the import edits be applied? */
064: private final boolean fImports;
065:
066: /** The insertion point, or <code>-1</code> */
067: private final int fInsertPos;
068:
069: /** The method bindings to implement */
070: private final IMethodBinding[] fConstructorsToImplement;
071:
072: /** Should the call to the super constructor be omitted? */
073: private boolean fOmitSuper;
074:
075: /** Should the compilation unit content be saved? */
076: private final boolean fSave;
077:
078: /** Specified if comments should be created */
079: private boolean fCreateComments;
080:
081: /** The type declaration to add the constructors to */
082: private final ITypeBinding fType;
083:
084: /** The compilation unit AST node */
085: private final CompilationUnit fASTRoot;
086:
087: /** The visibility flags of the new constructor */
088: private int fVisibility;
089:
090: /**
091: * Creates a new add unimplemented constructors operation.
092: *
093: * @param astRoot the compilation unit AST node
094: * @param type the type to add the methods to
095: * @param constructorsToImplement the method binding keys to implement
096: * @param insertPos the insertion point, or <code>-1</code>
097: * @param imports <code>true</code> if the import edits should be applied, <code>false</code> otherwise
098: * @param apply <code>true</code> if the resulting edit should be applied, <code>false</code> otherwise
099: * @param save <code>true</code> if the changed compilation unit should be saved, <code>false</code> otherwise
100: */
101: public AddUnimplementedConstructorsOperation(
102: CompilationUnit astRoot, ITypeBinding type,
103: IMethodBinding[] constructorsToImplement, int insertPos,
104: final boolean imports, final boolean apply,
105: final boolean save) {
106: if (astRoot == null
107: || !(astRoot.getJavaElement() instanceof ICompilationUnit)) {
108: throw new IllegalArgumentException(
109: "AST must not be null and has to be created from a ICompilationUnit"); //$NON-NLS-1$
110: }
111: if (type == null) {
112: throw new IllegalArgumentException(
113: "The type must not be null"); //$NON-NLS-1$
114: }
115: ASTNode node = astRoot.findDeclaringNode(type);
116: if (!(node instanceof AnonymousClassDeclaration || node instanceof AbstractTypeDeclaration)) {
117: throw new IllegalArgumentException(
118: "type has to map to a type declaration in the AST"); //$NON-NLS-1$
119: }
120:
121: fType = type;
122: fInsertPos = insertPos;
123: fASTRoot = astRoot;
124: fConstructorsToImplement = constructorsToImplement;
125: fSave = save;
126: fApply = apply;
127: fImports = imports;
128:
129: fCreateComments = StubUtility.doAddComments(astRoot
130: .getJavaElement().getJavaProject());
131: fVisibility = Modifier.PUBLIC;
132: fOmitSuper = false;
133: }
134:
135: /**
136: * Returns the method binding keys for which a constructor has been generated.
137: *
138: * @return the method binding keys
139: */
140: public String[] getCreatedConstructors() {
141: final String[] keys = new String[fCreatedMethods.size()];
142: fCreatedMethods.toArray(keys);
143: return keys;
144: }
145:
146: /**
147: * Returns the qualified names of the generated imports.
148: *
149: * @return the generated imports
150: */
151: public String[] getCreatedImports() {
152: return fCreatedImports;
153: }
154:
155: /**
156: * Returns the scheduling rule for this operation.
157: *
158: * @return the scheduling rule
159: */
160: public ISchedulingRule getSchedulingRule() {
161: return ResourcesPlugin.getWorkspace().getRoot();
162: }
163:
164: /**
165: * Returns the visibility of the constructors.
166: *
167: * @return the visibility
168: */
169: public int getVisibility() {
170: return fVisibility;
171: }
172:
173: /**
174: * Returns whether the super call should be omitted.
175: *
176: * @return <code>true</code> to omit the super call, <code>false</code> otherwise
177: */
178: public boolean isOmitSuper() {
179: return fOmitSuper;
180: }
181:
182: /**
183: * Determines whether to create comments.
184: * @param comments <code>true</code> to create comments, <code>false</code> otherwise
185: */
186: public void setCreateComments(final boolean comments) {
187: fCreateComments = comments;
188: }
189:
190: /*
191: * @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor)
192: */
193: public void run(IProgressMonitor monitor) throws CoreException {
194: if (monitor == null)
195: monitor = new NullProgressMonitor();
196: try {
197: monitor.beginTask("", 2); //$NON-NLS-1$
198: monitor
199: .setTaskName(CodeGenerationMessages.AddUnimplementedMethodsOperation_description);
200: fCreatedMethods.clear();
201: ICompilationUnit cu = (ICompilationUnit) fASTRoot
202: .getJavaElement();
203:
204: AST ast = fASTRoot.getAST();
205:
206: ASTRewrite astRewrite = ASTRewrite.create(ast);
207: ImportRewrite importRewrite = StubUtility
208: .createImportRewrite(fASTRoot, true);
209:
210: ITypeBinding currTypeBinding = fType;
211: ListRewrite memberRewriter = null;
212:
213: ASTNode node = fASTRoot.findDeclaringNode(currTypeBinding);
214: if (node instanceof AnonymousClassDeclaration) {
215: memberRewriter = astRewrite
216: .getListRewrite(
217: node,
218: AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY);
219: } else if (node instanceof AbstractTypeDeclaration) {
220: ChildListPropertyDescriptor property = ((AbstractTypeDeclaration) node)
221: .getBodyDeclarationsProperty();
222: memberRewriter = astRewrite.getListRewrite(node,
223: property);
224: } else {
225: throw new IllegalArgumentException();
226: // not possible, we checked this in the constructor
227: }
228:
229: final CodeGenerationSettings settings = JavaPreferencesSettings
230: .getCodeGenerationSettings(cu.getJavaProject());
231: settings.createComments = fCreateComments;
232:
233: ASTNode insertion = getNodeToInsertBefore(memberRewriter);
234:
235: IMethodBinding[] toImplement = fConstructorsToImplement;
236: if (toImplement == null) {
237: toImplement = StubUtility2.getVisibleConstructors(
238: currTypeBinding, true, true);
239: }
240:
241: int deprecationCount = 0;
242: for (int i = 0; i < toImplement.length; i++) {
243: if (toImplement[i].isDeprecated())
244: deprecationCount++;
245: }
246: boolean createDeprecated = deprecationCount == toImplement.length;
247: for (int i = 0; i < toImplement.length; i++) {
248: IMethodBinding curr = toImplement[i];
249: if (!curr.isDeprecated() || createDeprecated) {
250: MethodDeclaration stub = StubUtility2
251: .createConstructorStub(cu, astRewrite,
252: importRewrite, curr,
253: currTypeBinding.getName(),
254: fVisibility, fOmitSuper, true,
255: settings);
256: if (stub != null) {
257: fCreatedMethods.add(curr.getKey());
258: if (insertion != null)
259: memberRewriter.insertBefore(stub,
260: insertion, null);
261: else
262: memberRewriter.insertLast(stub, null);
263: }
264: }
265: }
266: MultiTextEdit edit = new MultiTextEdit();
267:
268: TextEdit importEdits = importRewrite
269: .rewriteImports(new SubProgressMonitor(monitor, 1));
270: fCreatedImports = importRewrite.getCreatedImports();
271: if (fImports) {
272: edit.addChild(importEdits);
273: }
274: edit.addChild(astRewrite.rewriteAST());
275:
276: if (fApply) {
277: JavaModelUtil.applyEdit(cu, edit, fSave,
278: new SubProgressMonitor(monitor, 1));
279: }
280: } finally {
281: monitor.done();
282: }
283: }
284:
285: /**
286: * Determines whether the super call should be omitted.
287: *
288: * @param omit <code>true</code> to omit the super call, <code>false</code> otherwise
289: */
290: public void setOmitSuper(final boolean omit) {
291: fOmitSuper = omit;
292: }
293:
294: /**
295: * Determines the visibility of the constructors.
296: *
297: * @param visibility the visibility
298: */
299: public void setVisibility(final int visibility) {
300: fVisibility = visibility;
301: }
302:
303: private ASTNode getNodeToInsertBefore(ListRewrite rewriter) {
304: if (fInsertPos != -1) {
305: List members = rewriter.getOriginalList();
306: for (int i = 0; i < members.size(); i++) {
307: ASTNode curr = (ASTNode) members.get(i);
308: if (curr.getStartPosition() >= fInsertPos) {
309: return curr;
310: }
311: }
312: }
313: return null;
314: }
315: }
|