| /******************************************************************************* |
| * Copyright (c) 2006, 2011 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.corext.refactoring.code; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.core.runtime.SubProgressMonitor; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IResource; |
| |
| import org.eclipse.text.edits.MalformedTreeException; |
| import org.eclipse.text.edits.MultiTextEdit; |
| import org.eclipse.text.edits.TextEdit; |
| import org.eclipse.text.edits.TextEditGroup; |
| |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.Document; |
| import org.eclipse.jface.text.IDocument; |
| |
| import org.eclipse.ltk.core.refactoring.Change; |
| import org.eclipse.ltk.core.refactoring.Refactoring; |
| import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; |
| import org.eclipse.ltk.core.refactoring.RefactoringStatus; |
| import org.eclipse.ltk.core.refactoring.participants.ResourceChangeChecker; |
| |
| import org.eclipse.jdt.core.Flags; |
| import org.eclipse.jdt.core.IClassFile; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.ITypeHierarchy; |
| import org.eclipse.jdt.core.ITypeRoot; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.dom.AST; |
| import org.eclipse.jdt.core.dom.ASTNode; |
| import org.eclipse.jdt.core.dom.ASTParser; |
| import org.eclipse.jdt.core.dom.Block; |
| import org.eclipse.jdt.core.dom.BodyDeclaration; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.ExpressionStatement; |
| import org.eclipse.jdt.core.dom.IBinding; |
| import org.eclipse.jdt.core.dom.IMethodBinding; |
| import org.eclipse.jdt.core.dom.MethodDeclaration; |
| import org.eclipse.jdt.core.dom.MethodInvocation; |
| import org.eclipse.jdt.core.dom.Modifier; |
| import org.eclipse.jdt.core.dom.NodeFinder; |
| import org.eclipse.jdt.core.dom.SimpleName; |
| import org.eclipse.jdt.core.dom.SingleVariableDeclaration; |
| import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; |
| import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; |
| import org.eclipse.jdt.core.refactoring.CompilationUnitChange; |
| import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; |
| |
| import org.eclipse.jdt.internal.corext.refactoring.Checks; |
| import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; |
| import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; |
| import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil; |
| import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; |
| import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; |
| import org.eclipse.jdt.internal.corext.refactoring.base.ReferencesInBinaryContext; |
| import org.eclipse.jdt.internal.corext.refactoring.binary.StubCreator; |
| import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; |
| import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; |
| import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; |
| import org.eclipse.jdt.internal.corext.util.Messages; |
| |
| import org.eclipse.jdt.ui.JavaElementLabels; |
| |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; |
| import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; |
| import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider; |
| |
| public class ReplaceInvocationsRefactoring extends Refactoring { |
| |
| private static final String ID_REPLACE_INVOCATIONS= "org.eclipse.jdt.ui.replace.invocations"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_MODE= "mode"; //$NON-NLS-1$ |
| |
| public static class Mode { |
| private Mode() { |
| } |
| public static final Mode REPLACE_ALL= new Mode(); |
| public static final Mode REPLACE_SINGLE= new Mode(); |
| } |
| |
| private final ITypeRoot fSelectionTypeRoot; |
| /** |
| * only set if initial mode is REPLACE_SINGLE |
| */ |
| private final int fSelectionStart; |
| /** |
| * only set if initial mode is REPLACE_SINGLE |
| */ |
| private final int fSelectionLength; |
| |
| private ASTNode fSelectionNode; |
| /** |
| * only set after checkInitialConditions |
| */ |
| private IMethod fMethod; |
| |
| private String fBody; |
| private String[] fParameterNames; |
| |
| private SourceProvider fSourceProvider; // resolved once in checkInitialConditions |
| private TargetProvider fTargetProvider; // flexible |
| |
| private TextChangeManager fChangeManager; |
| private IMethodBinding fMethodBinding; |
| |
| public ReplaceInvocationsRefactoring(ITypeRoot typeRoot, int offset, int length) { |
| fSelectionTypeRoot= typeRoot; |
| fSelectionStart= offset; |
| fSelectionLength= length; |
| } |
| |
| public ReplaceInvocationsRefactoring(IMethod method) { |
| fMethod= method; |
| fSelectionTypeRoot= method.getTypeRoot(); |
| fSelectionStart= -1; |
| fSelectionLength= -1; |
| } |
| |
| public ReplaceInvocationsRefactoring(JavaRefactoringArguments arguments, RefactoringStatus status) { |
| this(null, 0, 0); |
| RefactoringStatus initializeStatus= initialize(arguments); |
| status.merge(initializeStatus); |
| } |
| |
| @Override |
| public String getName() { |
| return RefactoringCoreMessages.ReplaceInvocationsRefactoring_name; |
| } |
| |
| /* |
| * Only to be called after {@link #checkInitialConditions(IProgressMonitor)} |
| */ |
| public boolean canReplaceSingle() { |
| return fSelectionNode instanceof MethodInvocation; |
| } |
| |
| /* |
| * Only to be called after {@link #checkInitialConditions(IProgressMonitor)} |
| */ |
| public RefactoringStatus setCurrentMode(Mode mode) throws JavaModelException { |
| if (fTargetProvider.isSingle() == (mode == Mode.REPLACE_SINGLE)) |
| return new RefactoringStatus(); |
| Assert.isTrue(canReplaceSingle()); |
| if (mode == Mode.REPLACE_SINGLE) { |
| fTargetProvider= TargetProvider.create((ICompilationUnit) fSelectionTypeRoot, (MethodInvocation) fSelectionNode); |
| } else { |
| fTargetProvider= TargetProvider.create(fSourceProvider.getDeclaration()); |
| } |
| return fTargetProvider.checkActivation(); |
| } |
| |
| public void setBody(String body, String[] parameterNames) { |
| //TODO: validate parameter name count and body |
| fBody= body; |
| fParameterNames= parameterNames; |
| } |
| |
| @Override |
| public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException { |
| // TargetProvider must get an untampered AST with original invocation node |
| // SourceProvider must get a tweaked AST with method body / parameter names replaced |
| |
| RefactoringStatus result= new RefactoringStatus(); |
| |
| if (fMethod == null) { |
| if (! (fSelectionTypeRoot instanceof ICompilationUnit)) |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ReplaceInvocationsRefactoring_cannot_replace_in_binary); |
| |
| ICompilationUnit cu= (ICompilationUnit) fSelectionTypeRoot; |
| CompilationUnit root= new RefactoringASTParser(ASTProvider.SHARED_AST_LEVEL).parse(cu, true); |
| fSelectionNode= getTargetNode(cu, root, fSelectionStart, fSelectionLength); |
| if (fSelectionNode == null) |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ReplaceInvocationsRefactoring_select_method_to_apply); |
| |
| if (fSelectionNode.getNodeType() == ASTNode.METHOD_DECLARATION) { |
| MethodDeclaration methodDeclaration= (MethodDeclaration) fSelectionNode; |
| fTargetProvider= TargetProvider.create(methodDeclaration); |
| fMethodBinding= methodDeclaration.resolveBinding(); |
| } else { |
| MethodInvocation methodInvocation= (MethodInvocation) fSelectionNode; |
| fTargetProvider= TargetProvider.create(cu, methodInvocation); |
| fMethodBinding= methodInvocation.resolveMethodBinding(); |
| } |
| if (fMethodBinding == null) |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InlineMethodRefactoring_error_noMethodDeclaration); |
| fMethod= (IMethod) fMethodBinding.getJavaElement(); |
| |
| } else { |
| ASTParser parser= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL); |
| parser.setProject(fMethod.getJavaProject()); |
| IBinding[] bindings= parser.createBindings(new IJavaElement[] { fMethod }, null); |
| fMethodBinding= (IMethodBinding) bindings[0]; |
| if (fMethodBinding == null) |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InlineMethodRefactoring_error_noMethodDeclaration); |
| |
| fTargetProvider= TargetProvider.create(fMethodBinding); |
| } |
| |
| result.merge(fTargetProvider.checkActivation()); |
| return result; |
| } |
| |
| private SourceProvider resolveSourceProvider(IMethodBinding methodBinding, RefactoringStatus status) throws JavaModelException { |
| final IMethod method= (IMethod) methodBinding.getJavaElement(); |
| |
| ITypeRoot typeRoot; |
| IDocument source; |
| CompilationUnit methodDeclarationAstRoot; |
| |
| ICompilationUnit methodCu= (method).getCompilationUnit(); |
| if (methodCu != null) { |
| typeRoot= methodCu; |
| ASTParser parser= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL); |
| parser.setSource(methodCu); |
| parser.setFocalPosition(method.getNameRange().getOffset()); |
| CompilationUnit compilationUnit= (CompilationUnit) parser.createAST(null); |
| MethodDeclaration methodDecl= (MethodDeclaration) NodeFinder.perform(compilationUnit, method.getNameRange()).getParent(); |
| AST ast= compilationUnit.getAST(); |
| ASTRewrite rewrite= ASTRewrite.create(ast); |
| Block newBody= ast.newBlock(); |
| newBody.statements().add(rewrite.createStringPlaceholder(fBody, ASTNode.EMPTY_STATEMENT)); |
| rewrite.replace(methodDecl.getBody(), newBody, null); |
| List<SingleVariableDeclaration> parameters= methodDecl.parameters(); |
| for (int i= 0; i < parameters.size(); i++) { |
| SingleVariableDeclaration parameter= parameters.get(i); |
| rewrite.set(parameter.getName(), SimpleName.IDENTIFIER_PROPERTY, fParameterNames[i], null); |
| } |
| TextEdit textEdit= rewrite.rewriteAST(); |
| Document document= new Document(methodCu.getBuffer().getContents()); |
| try { |
| textEdit.apply(document); |
| } catch (MalformedTreeException e) { |
| JavaPlugin.log(e); |
| } catch (BadLocationException e) { |
| JavaPlugin.log(e); |
| } |
| source= document; |
| |
| methodDeclarationAstRoot= new RefactoringASTParser(ASTProvider.SHARED_AST_LEVEL).parse(source.get(), methodCu, true, true, null); |
| |
| } else { |
| IClassFile classFile= method.getClassFile(); |
| //TODO: use source if available? |
| StubCreator stubCreator= new StubCreator(true) { |
| @Override |
| protected void appendMethodBody(IMethod currentMethod) throws JavaModelException { |
| if (currentMethod.equals(method)) { |
| fBuffer.append(fBody); |
| } else { |
| super.appendMethodBody(currentMethod); |
| } |
| } |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.binary.StubCreator#appendMethodParameterName(org.eclipse.jdt.core.IMethod, int) |
| */ |
| @Override |
| protected void appendMethodParameterName(IMethod currentMethod, int index) { |
| if (currentMethod.equals(method)) { |
| fBuffer.append(fParameterNames[index]); |
| } else { |
| super.appendMethodParameterName(currentMethod, index); |
| } |
| } |
| }; |
| |
| String stub= stubCreator.createStub(classFile.getType(), null); |
| source= new Document(stub); |
| methodDeclarationAstRoot= new RefactoringASTParser(ASTProvider.SHARED_AST_LEVEL).parse(stub, classFile, true, true, null); |
| typeRoot= classFile; |
| } |
| ASTNode node= methodDeclarationAstRoot.findDeclaringNode(methodBinding.getKey()); |
| if (node instanceof MethodDeclaration) { |
| return new SourceProvider(typeRoot, source, (MethodDeclaration) node); |
| } else { |
| status.addFatalError(RefactoringCoreMessages.ReplaceInvocationsRefactoring_cannot_find_method_declaration); |
| return null; |
| } |
| } |
| |
| /* |
| * @return an invocation or declaration node |
| */ |
| private static ASTNode getTargetNode(ICompilationUnit unit, CompilationUnit root, int offset, int length) { |
| ASTNode node= null; |
| try { |
| node= checkNode(NodeFinder.perform(root, offset, length, unit)); |
| } catch(JavaModelException e) { |
| // Do nothing |
| } |
| if (node != null) |
| return node; |
| return checkNode(NodeFinder.perform(root, offset, length)); |
| } |
| |
| private static ASTNode checkNode(ASTNode node) { |
| if (node == null) |
| return null; |
| if (node.getNodeType() == ASTNode.SIMPLE_NAME) { |
| node= node.getParent(); |
| } else if (node.getNodeType() == ASTNode.EXPRESSION_STATEMENT) { |
| node= ((ExpressionStatement)node).getExpression(); |
| } |
| switch(node.getNodeType()) { |
| case ASTNode.METHOD_DECLARATION: |
| case ASTNode.METHOD_INVOCATION: |
| // not yet... |
| // case ASTNode.SUPER_METHOD_INVOCATION: |
| // case ASTNode.CONSTRUCTOR_INVOCATION: |
| return node; |
| } |
| return null; |
| } |
| |
| @Override |
| public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException { |
| pm.beginTask("", 20); //$NON-NLS-1$ |
| fChangeManager= new TextChangeManager(); |
| RefactoringStatus result= new RefactoringStatus(); |
| |
| fSourceProvider= resolveSourceProvider(fMethodBinding, result); |
| if (result.hasFatalError()) |
| return result; |
| |
| result.merge(fSourceProvider.checkActivation()); |
| if (result.hasFatalError()) |
| return result; |
| |
| fSourceProvider.initialize(); |
| fTargetProvider.initialize(); |
| |
| pm.setTaskName(RefactoringCoreMessages.InlineMethodRefactoring_searching); |
| RefactoringStatus searchStatus= new RefactoringStatus(); |
| String binaryRefsDescription= Messages.format(RefactoringCoreMessages.ReferencesInBinaryContext_ref_in_binaries_description , BasicElementLabels.getJavaElementName(fSourceProvider.getMethodName())); |
| ReferencesInBinaryContext binaryRefs= new ReferencesInBinaryContext(binaryRefsDescription); |
| ICompilationUnit[] units= fTargetProvider.getAffectedCompilationUnits(searchStatus, binaryRefs, new SubProgressMonitor(pm, 1)); |
| binaryRefs.addErrorIfNecessary(searchStatus); |
| |
| if (searchStatus.hasFatalError()) { |
| result.merge(searchStatus); |
| return result; |
| } |
| IFile[] filesToBeModified= getFilesToBeModified(units); |
| result.merge(Checks.validateModifiesFiles(filesToBeModified, getValidationContext())); |
| if (result.hasFatalError()) |
| return result; |
| result.merge(ResourceChangeChecker.checkFilesToBeChanged(filesToBeModified, new SubProgressMonitor(pm, 1))); |
| checkOverridden(result, new SubProgressMonitor(pm, 4)); |
| IProgressMonitor sub= new SubProgressMonitor(pm, 15); |
| sub.beginTask("", units.length * 3); //$NON-NLS-1$ |
| for (int c= 0; c < units.length; c++) { |
| ICompilationUnit unit= units[c]; |
| sub.subTask(Messages.format(RefactoringCoreMessages.InlineMethodRefactoring_processing, BasicElementLabels.getFileName(unit))); |
| CallInliner inliner= null; |
| try { |
| boolean added= false; |
| MultiTextEdit root= new MultiTextEdit(); |
| CompilationUnitChange change= (CompilationUnitChange)fChangeManager.get(unit); |
| change.setEdit(root); |
| BodyDeclaration[] bodies= fTargetProvider.getAffectedBodyDeclarations(unit, new SubProgressMonitor(pm, 1)); |
| if (bodies.length == 0) |
| continue; |
| inliner= new CallInliner(unit, (CompilationUnit) bodies[0].getRoot(), fSourceProvider); |
| for (int b= 0; b < bodies.length; b++) { |
| BodyDeclaration body= bodies[b]; |
| inliner.initialize(body); |
| RefactoringStatus nestedInvocations= new RefactoringStatus(); |
| ASTNode[] invocations= removeNestedCalls(nestedInvocations, unit, |
| fTargetProvider.getInvocations(body, new SubProgressMonitor(sub, 2))); |
| for (int i= 0; i < invocations.length; i++) { |
| ASTNode invocation= invocations[i]; |
| result.merge(inliner.initialize(invocation, fTargetProvider.getStatusSeverity())); |
| if (result.hasFatalError()) |
| break; |
| if (result.getSeverity() < fTargetProvider.getStatusSeverity()) { |
| added= true; |
| TextEditGroup group= new TextEditGroup(RefactoringCoreMessages.InlineMethodRefactoring_edit_inline); |
| change.addTextEditGroup(group); |
| result.merge(inliner.perform(group)); |
| } |
| } |
| // do this after we have inlined the method calls. We still want |
| // to generate the modifications. |
| result.merge(nestedInvocations); |
| } |
| if (!added) { |
| fChangeManager.remove(unit); |
| } else { |
| root.addChild(inliner.getModifications()); |
| ImportRewrite rewrite= inliner.getImportEdit(); |
| if (rewrite.hasRecordedChanges()) { |
| TextEdit edit= rewrite.rewriteImports(null); |
| if (edit instanceof MultiTextEdit ? ((MultiTextEdit)edit).getChildrenSize() > 0 : true) { |
| root.addChild(edit); |
| change.addTextEditGroup( |
| new TextEditGroup(RefactoringCoreMessages.InlineMethodRefactoring_edit_import, new TextEdit[] {edit})); |
| } |
| } |
| } |
| } finally { |
| if (inliner != null) |
| inliner.dispose(); |
| } |
| sub.worked(1); |
| if (sub.isCanceled()) |
| throw new OperationCanceledException(); |
| } |
| result.merge(searchStatus); |
| sub.done(); |
| pm.done(); |
| return result; |
| } |
| |
| @Override |
| public Change createChange(IProgressMonitor pm) throws CoreException { |
| // TODO: update for fSelectionStart == -1 |
| final Map<String, String> arguments= new HashMap<String, String>(); |
| String project= null; |
| IJavaProject javaProject= fSelectionTypeRoot.getJavaProject(); |
| if (javaProject != null) |
| project= javaProject.getElementName(); |
| final IMethodBinding binding= fSourceProvider.getDeclaration().resolveBinding(); |
| int flags= RefactoringDescriptor.STRUCTURAL_CHANGE | JavaRefactoringDescriptor.JAR_REFACTORING | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT; |
| if (!Modifier.isPrivate(binding.getModifiers())) |
| flags|= RefactoringDescriptor.MULTI_CHANGE; |
| final String description= Messages.format(RefactoringCoreMessages.ReplaceInvocationsRefactoring_descriptor_description_short, BasicElementLabels.getJavaElementName(binding.getName())); |
| final String header= Messages.format(RefactoringCoreMessages.ReplaceInvocationsRefactoring_descriptor_description, new String[] { BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED), BindingLabelProvider.getBindingLabel(binding.getDeclaringClass(), JavaElementLabels.ALL_FULLY_QUALIFIED)}); |
| final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header); |
| comment.addSetting(Messages.format(RefactoringCoreMessages.ReplaceInvocationsRefactoring_original_pattern, BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED))); |
| if (!fTargetProvider.isSingle()) |
| comment.addSetting(RefactoringCoreMessages.ReplaceInvocationsRefactoring_replace_references); |
| final JavaRefactoringDescriptor descriptor= new JavaRefactoringDescriptor(ID_REPLACE_INVOCATIONS, project, description, comment.asString(), arguments, flags){}; //REVIEW Unregistered ID! |
| arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT, JavaRefactoringDescriptorUtil.elementToHandle(project, fSelectionTypeRoot)); |
| arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION, new Integer(fSelectionStart).toString() + " " + new Integer(fSelectionLength).toString()); //$NON-NLS-1$ |
| arguments.put(ATTRIBUTE_MODE, new Integer(fTargetProvider.isSingle() ? 0 : 1).toString()); |
| return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.ReplaceInvocationsRefactoring_change_name, fChangeManager.getAllChanges()); |
| } |
| |
| private IFile[] getFilesToBeModified(ICompilationUnit[] units) { |
| List<IFile> result= new ArrayList<IFile>(units.length + 1); |
| IFile file; |
| for (int i= 0; i < units.length; i++) { |
| file= getFile(units[i]); |
| if (file != null) |
| result.add(file); |
| } |
| return result.toArray(new IFile[result.size()]); |
| } |
| |
| private IFile getFile(ICompilationUnit unit) { |
| unit= unit.getPrimary(); |
| IResource resource= unit.getResource(); |
| if (resource != null && resource.getType() == IResource.FILE) |
| return (IFile)resource; |
| return null; |
| } |
| |
| private void checkOverridden(RefactoringStatus status, IProgressMonitor pm) throws JavaModelException { |
| pm.beginTask("", 9); //$NON-NLS-1$ |
| pm.setTaskName(RefactoringCoreMessages.InlineMethodRefactoring_checking_overridden); |
| MethodDeclaration decl= fSourceProvider.getDeclaration(); |
| IMethod method= (IMethod) decl.resolveBinding().getJavaElement(); |
| if (method == null || Flags.isPrivate(method.getFlags())) { |
| pm.worked(8); |
| return; |
| } |
| IType type= method.getDeclaringType(); |
| ITypeHierarchy hierarchy= type.newTypeHierarchy(new SubProgressMonitor(pm, 6)); |
| checkSubTypes(status, method, hierarchy.getAllSubtypes(type), new SubProgressMonitor(pm, 1)); |
| checkSuperClasses(status, method, hierarchy.getAllSuperclasses(type), new SubProgressMonitor(pm, 1)); |
| checkSuperInterfaces(status, method, hierarchy.getAllSuperInterfaces(type), new SubProgressMonitor(pm, 1)); |
| pm.setTaskName(""); //$NON-NLS-1$ |
| } |
| |
| private void checkSubTypes(RefactoringStatus result, IMethod method, IType[] types, IProgressMonitor pm) { |
| checkTypes( |
| result, method, types, |
| RefactoringCoreMessages.InlineMethodRefactoring_checking_overridden_error, |
| pm); |
| } |
| |
| private void checkSuperClasses(RefactoringStatus result, IMethod method, IType[] types, IProgressMonitor pm) { |
| checkTypes( |
| result, method, types, |
| RefactoringCoreMessages.InlineMethodRefactoring_checking_overrides_error, |
| pm); |
| } |
| |
| private void checkSuperInterfaces(RefactoringStatus result, IMethod method, IType[] types, IProgressMonitor pm) { |
| checkTypes( |
| result, method, types, |
| RefactoringCoreMessages.InlineMethodRefactoring_checking_implements_error, |
| pm); |
| } |
| private void checkTypes(RefactoringStatus result, IMethod method, IType[] types, String key, IProgressMonitor pm) { |
| pm.beginTask("", types.length); //$NON-NLS-1$ |
| for (int i= 0; i < types.length; i++) { |
| pm.worked(1); |
| IMethod[] overridden= types[i].findMethods(method); |
| if (overridden != null && overridden.length > 0) { |
| result.addError( |
| Messages.format(key, BasicElementLabels.getJavaElementName(types[i].getElementName())), |
| JavaStatusContext.create(overridden[0])); |
| } |
| } |
| } |
| |
| private ASTNode[] removeNestedCalls(RefactoringStatus status, ICompilationUnit unit, ASTNode[] invocations) { |
| if (invocations.length <= 1) |
| return invocations; |
| ASTNode[] parents= new ASTNode[invocations.length]; |
| for (int i= 0; i < invocations.length; i++) { |
| parents[i]= invocations[i].getParent(); |
| } |
| for (int i= 0; i < invocations.length; i++) { |
| removeNestedCalls(status, unit, parents, invocations, i); |
| } |
| List<ASTNode> result= new ArrayList<ASTNode>(); |
| for (int i= 0; i < invocations.length; i++) { |
| if (invocations[i] != null) |
| result.add(invocations[i]); |
| } |
| return result.toArray(new ASTNode[result.size()]); |
| } |
| |
| private void removeNestedCalls(RefactoringStatus status, ICompilationUnit unit, ASTNode[] parents, ASTNode[] invocations, int index) { |
| ASTNode invocation= invocations[index]; |
| for (int i= 0; i < parents.length; i++) { |
| ASTNode parent= parents[i]; |
| while (parent != null) { |
| if (parent == invocation) { |
| status.addError(RefactoringCoreMessages.InlineMethodRefactoring_nestedInvocation, |
| JavaStatusContext.create(unit, parent)); |
| invocations[index]= null; |
| } |
| parent= parent.getParent(); |
| } |
| } |
| } |
| |
| private RefactoringStatus initialize(JavaRefactoringArguments arguments) { |
| final String value= arguments.getAttribute(ATTRIBUTE_MODE); |
| if (value != null && !"".equals(value)) {//$NON-NLS-1$ |
| int mode= 0; |
| try { |
| mode= Integer.parseInt(value); |
| } catch (NumberFormatException exception) { |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_MODE)); |
| } |
| try { |
| setCurrentMode(mode == 1 ? Mode.REPLACE_ALL : Mode.REPLACE_SINGLE); |
| } catch (JavaModelException exception) { |
| return RefactoringStatus.createFatalErrorStatus(exception.getLocalizedMessage()); |
| } |
| } |
| return new RefactoringStatus(); |
| } |
| |
| public IMethod getMethod() { |
| return fMethod; |
| } |
| |
| } |