| /******************************************************************************* |
| * Copyright (c) 2000, 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 |
| * Felix Pahl (fpahl@web.de) - contributed fix for: |
| * o introduce parameter throws NPE if there are compiler errors |
| * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=48325) |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.corext.refactoring.code; |
| |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.LinkedHashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.StringTokenizer; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.SubProgressMonitor; |
| |
| import org.eclipse.jface.text.TextSelection; |
| |
| import org.eclipse.ltk.core.refactoring.Change; |
| import org.eclipse.ltk.core.refactoring.Refactoring; |
| import org.eclipse.ltk.core.refactoring.RefactoringContribution; |
| import org.eclipse.ltk.core.refactoring.RefactoringCore; |
| import org.eclipse.ltk.core.refactoring.RefactoringStatus; |
| import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; |
| import org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring; |
| |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.SourceRange; |
| import org.eclipse.jdt.core.dom.ASTNode; |
| import org.eclipse.jdt.core.dom.Annotation; |
| import org.eclipse.jdt.core.dom.ArrayInitializer; |
| import org.eclipse.jdt.core.dom.Assignment; |
| import org.eclipse.jdt.core.dom.ClassInstanceCreation; |
| import org.eclipse.jdt.core.dom.Expression; |
| import org.eclipse.jdt.core.dom.FieldAccess; |
| import org.eclipse.jdt.core.dom.IBinding; |
| import org.eclipse.jdt.core.dom.ITypeBinding; |
| import org.eclipse.jdt.core.dom.MethodDeclaration; |
| import org.eclipse.jdt.core.dom.MethodInvocation; |
| import org.eclipse.jdt.core.dom.Name; |
| import org.eclipse.jdt.core.dom.NodeFinder; |
| import org.eclipse.jdt.core.dom.NullLiteral; |
| import org.eclipse.jdt.core.dom.ParenthesizedExpression; |
| import org.eclipse.jdt.core.dom.QualifiedName; |
| import org.eclipse.jdt.core.dom.SimpleName; |
| import org.eclipse.jdt.core.refactoring.IJavaRefactorings; |
| import org.eclipse.jdt.core.refactoring.descriptors.ChangeMethodSignatureDescriptor; |
| import org.eclipse.jdt.core.refactoring.descriptors.IntroduceParameterDescriptor; |
| |
| import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory; |
| import org.eclipse.jdt.internal.corext.Corext; |
| import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; |
| import org.eclipse.jdt.internal.corext.dom.ASTNodes; |
| import org.eclipse.jdt.internal.corext.dom.Bindings; |
| import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer; |
| import org.eclipse.jdt.internal.corext.dom.fragments.ASTFragmentFactory; |
| import org.eclipse.jdt.internal.corext.dom.fragments.IASTFragment; |
| import org.eclipse.jdt.internal.corext.dom.fragments.IExpressionFragment; |
| 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.ParameterInfo; |
| import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester; |
| import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; |
| import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes; |
| import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; |
| import org.eclipse.jdt.internal.corext.refactoring.structure.BodyUpdater; |
| import org.eclipse.jdt.internal.corext.refactoring.structure.ChangeSignatureProcessor; |
| import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; |
| import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating; |
| 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.actions.SelectionConverter; |
| import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; |
| |
| |
| public class IntroduceParameterRefactoring extends Refactoring implements IDelegateUpdating { |
| |
| private static final String ATTRIBUTE_ARGUMENT= "argument"; //$NON-NLS-1$ |
| |
| private static final String[] KNOWN_METHOD_NAME_PREFIXES= {"get", "is"}; //$NON-NLS-2$ //$NON-NLS-1$ |
| |
| private ICompilationUnit fSourceCU; |
| private int fSelectionStart; |
| private int fSelectionLength; |
| |
| private IMethod fMethod; |
| private Refactoring fChangeSignatureRefactoring; |
| private ChangeSignatureProcessor fChangeSignatureProcessor; |
| private ParameterInfo fParameter; |
| private String fParameterName; |
| private JavaRefactoringArguments fArguments; |
| |
| private Expression fSelectedExpression; |
| private String[] fExcludedParameterNames; |
| |
| /** |
| * Creates a new introduce parameter refactoring. |
| * @param unit the compilation unit, or <code>null</code> if invoked by scripting |
| * @param selectionStart start |
| * @param selectionLength length |
| */ |
| public IntroduceParameterRefactoring(ICompilationUnit unit, int selectionStart, int selectionLength) { |
| Assert.isTrue(selectionStart >= 0); |
| Assert.isTrue(selectionLength >= 0); |
| fSourceCU= unit; |
| fSelectionStart= selectionStart; |
| fSelectionLength= selectionLength; |
| } |
| |
| public IntroduceParameterRefactoring(JavaRefactoringArguments arguments, RefactoringStatus status) { |
| this(null, 0, 0); |
| RefactoringStatus initializeStatus= initialize(arguments); |
| status.merge(initializeStatus); |
| } |
| |
| // ------------------- IDelegateUpdating ---------------------- |
| |
| public boolean canEnableDelegateUpdating() { |
| return true; |
| } |
| |
| public boolean getDelegateUpdating() { |
| return (fChangeSignatureProcessor != null) ? fChangeSignatureProcessor.getDelegateUpdating() : false; |
| } |
| |
| public void setDelegateUpdating(boolean updating) { |
| if (fChangeSignatureProcessor != null) |
| fChangeSignatureProcessor.setDelegateUpdating(updating); |
| } |
| |
| public void setDeprecateDelegates(boolean deprecate) { |
| if (fChangeSignatureProcessor != null) |
| fChangeSignatureProcessor.setDeprecateDelegates(deprecate); |
| } |
| |
| public boolean getDeprecateDelegates() { |
| return (fChangeSignatureProcessor != null) ? fChangeSignatureProcessor.getDeprecateDelegates() : false; |
| } |
| |
| // ------------------- /IDelegateUpdating --------------------- |
| |
| @Override |
| public String getName() { |
| return RefactoringCoreMessages.IntroduceParameterRefactoring_name; |
| } |
| |
| //--- checkActivation |
| |
| @Override |
| public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException { |
| try { |
| pm.beginTask("", 7); //$NON-NLS-1$ |
| |
| if (! fSourceCU.isStructureKnown()) |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceParameterRefactoring_syntax_error); |
| |
| IJavaElement enclosingElement= SelectionConverter.resolveEnclosingElement(fSourceCU, new TextSelection(fSelectionStart, fSelectionLength)); |
| if (! (enclosingElement instanceof IMethod)) |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceParameterRefactoring_expression_in_method); |
| |
| fMethod= (IMethod) enclosingElement; |
| pm.worked(1); |
| |
| RefactoringStatus result= new RefactoringStatus(); |
| if (fArguments != null) { |
| // invoked by script |
| fChangeSignatureProcessor= new ChangeSignatureProcessor(fArguments, result); |
| if (!result.hasFatalError()) { |
| fChangeSignatureRefactoring= new ProcessorBasedRefactoring(fChangeSignatureProcessor); |
| fChangeSignatureRefactoring.setValidationContext(getValidationContext()); |
| result.merge(fChangeSignatureProcessor.checkInitialConditions(new SubProgressMonitor(pm, 2))); |
| if (result.hasFatalError()) |
| return result; |
| } else { |
| pm.worked(2); |
| return result; |
| } |
| } else { |
| // first try: |
| fChangeSignatureProcessor= RefactoringAvailabilityTester.isChangeSignatureAvailable(fMethod) ? new ChangeSignatureProcessor(fMethod) : null; |
| if (fChangeSignatureProcessor == null) |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceParameterRefactoring_expression_in_method); |
| fChangeSignatureRefactoring= new ProcessorBasedRefactoring(fChangeSignatureProcessor); |
| fChangeSignatureRefactoring.setValidationContext(getValidationContext()); |
| result.merge(fChangeSignatureProcessor.checkInitialConditions(new SubProgressMonitor(pm, 1))); |
| if (result.hasFatalError()) { |
| RefactoringStatusEntry entry= result.getEntryMatchingSeverity(RefactoringStatus.FATAL); |
| if (entry.getCode() == RefactoringStatusCodes.OVERRIDES_ANOTHER_METHOD || entry.getCode() == RefactoringStatusCodes.METHOD_DECLARED_IN_INTERFACE) { |
| // second try: |
| IMethod method= (IMethod) entry.getData(); |
| fChangeSignatureProcessor= RefactoringAvailabilityTester.isChangeSignatureAvailable(method) ? new ChangeSignatureProcessor(method) : null; |
| if (fChangeSignatureProcessor == null) { |
| String msg= Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_cannot_introduce, entry.getMessage()); |
| return RefactoringStatus.createFatalErrorStatus(msg); |
| } |
| result= fChangeSignatureProcessor.checkInitialConditions(new SubProgressMonitor(pm, 1)); |
| if (result.hasFatalError()) |
| return result; |
| } else { |
| return result; |
| } |
| } else { |
| pm.worked(1); |
| } |
| } |
| |
| CompilationUnitRewrite cuRewrite= fChangeSignatureProcessor.getBaseCuRewrite(); |
| if (! cuRewrite.getCu().equals(fSourceCU)) |
| cuRewrite= new CompilationUnitRewrite(fSourceCU); // TODO: should try to avoid throwing away this AST |
| |
| initializeSelectedExpression(cuRewrite); |
| pm.worked(1); |
| |
| result.merge(checkSelection(cuRewrite, new SubProgressMonitor(pm, 3))); |
| if (result.hasFatalError()) |
| return result; |
| |
| initializeExcludedParameterNames(cuRewrite); |
| |
| addParameterInfo(cuRewrite); |
| |
| fChangeSignatureProcessor.setBodyUpdater(new BodyUpdater() { |
| @Override |
| public void updateBody(MethodDeclaration methodDeclaration, CompilationUnitRewrite rewrite, RefactoringStatus updaterResult) { |
| replaceSelectedExpression(rewrite); |
| } |
| }); |
| |
| return result; |
| } finally { |
| pm.done(); |
| if (fChangeSignatureRefactoring != null) |
| fChangeSignatureRefactoring.setValidationContext(null); |
| } |
| } |
| |
| private void addParameterInfo(CompilationUnitRewrite cuRewrite) throws JavaModelException { |
| ITypeBinding typeBinding= Bindings.normalizeForDeclarationUse(fSelectedExpression.resolveTypeBinding(), fSelectedExpression.getAST()); |
| String typeName= cuRewrite.getImportRewrite().addImport(typeBinding); |
| String name= fParameterName != null ? fParameterName : guessedParameterName(); |
| Expression expression= fSelectedExpression instanceof ParenthesizedExpression ? ((ParenthesizedExpression)fSelectedExpression).getExpression() : fSelectedExpression; |
| String defaultValue= fSourceCU.getBuffer().getText(expression.getStartPosition(), expression.getLength()); |
| fParameter= ParameterInfo.createInfoForAddedParameter(typeBinding, typeName, name, defaultValue); |
| if (fArguments == null) { |
| List<ParameterInfo> parameterInfos= fChangeSignatureProcessor.getParameterInfos(); |
| int parametersCount= parameterInfos.size(); |
| if (parametersCount > 0 && parameterInfos.get(parametersCount - 1).isOldVarargs()) |
| parameterInfos.add(parametersCount - 1, fParameter); |
| else |
| parameterInfos.add(fParameter); |
| } |
| } |
| |
| private void replaceSelectedExpression(CompilationUnitRewrite cuRewrite) { |
| if (! fSourceCU.equals(cuRewrite.getCu())) |
| return; |
| // TODO: do for all methodDeclarations and replace matching fragments? |
| |
| // cannot use fSelectedExpression here, since it could be from another AST (if method was replaced by overridden): |
| Expression expression= (Expression) NodeFinder.perform(cuRewrite.getRoot(), fSelectedExpression.getStartPosition(), fSelectedExpression.getLength()); |
| |
| ASTNode newExpression= cuRewrite.getRoot().getAST().newSimpleName(fParameter.getNewName()); |
| String description= RefactoringCoreMessages.IntroduceParameterRefactoring_replace; |
| cuRewrite.getASTRewrite().replace(expression.getParent() instanceof ParenthesizedExpression |
| ? expression.getParent() : expression, newExpression, cuRewrite.createGroupDescription(description)); |
| } |
| |
| private void initializeSelectedExpression(CompilationUnitRewrite cuRewrite) throws JavaModelException { |
| IASTFragment fragment= ASTFragmentFactory.createFragmentForSourceRange( |
| new SourceRange(fSelectionStart, fSelectionLength), cuRewrite.getRoot(), cuRewrite.getCu()); |
| |
| if (! (fragment instanceof IExpressionFragment)) |
| return; |
| |
| //TODO: doesn't handle selection of partial Expressions |
| Expression expression= ((IExpressionFragment) fragment).getAssociatedExpression(); |
| if (fragment.getStartPosition() != expression.getStartPosition() |
| || fragment.getLength() != expression.getLength()) |
| return; |
| |
| if (Checks.isInsideJavadoc(expression)) |
| return; |
| //TODO: exclude invalid selections |
| if (Checks.isEnumCase(expression.getParent())) |
| return; |
| |
| fSelectedExpression= expression; |
| } |
| |
| private RefactoringStatus checkSelection(CompilationUnitRewrite cuRewrite, IProgressMonitor pm) { |
| try { |
| if (fSelectedExpression == null){ |
| String message= RefactoringCoreMessages.IntroduceParameterRefactoring_select; |
| return CodeRefactoringUtil.checkMethodSyntaxErrors(fSelectionStart, fSelectionLength, cuRewrite.getRoot(), message); |
| } |
| |
| MethodDeclaration methodDeclaration= (MethodDeclaration) ASTNodes.getParent(fSelectedExpression, MethodDeclaration.class); |
| if (methodDeclaration == null || ASTNodes.getParent(fSelectedExpression, Annotation.class) != null) |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceParameterRefactoring_expression_in_method); |
| if (methodDeclaration.resolveBinding() == null) |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceParameterRefactoring_no_binding); |
| //TODO: check for rippleMethods -> find matching fragments, consider callers of all rippleMethods |
| |
| RefactoringStatus result= new RefactoringStatus(); |
| result.merge(checkExpression()); |
| if (result.hasFatalError()) |
| return result; |
| |
| result.merge(checkExpressionBinding()); |
| if (result.hasFatalError()) |
| return result; |
| |
| // if (isUsedInForInitializerOrUpdater(getSelectedExpression().getAssociatedExpression())) |
| // return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.getString("ExtractTempRefactoring.for_initializer_updater")); //$NON-NLS-1$ |
| // pm.worked(1); |
| // |
| // if (isReferringToLocalVariableFromFor(getSelectedExpression().getAssociatedExpression())) |
| // return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.getString("ExtractTempRefactoring.refers_to_for_variable")); //$NON-NLS-1$ |
| // pm.worked(1); |
| |
| return result; |
| } finally { |
| if (pm != null) |
| pm.done(); |
| } |
| } |
| |
| private RefactoringStatus checkExpression() { |
| //TODO: adjust error messages (or generalize for all refactorings on expression-selections?) |
| Expression selectedExpression= fSelectedExpression; |
| |
| if (selectedExpression instanceof Name && selectedExpression.getParent() instanceof ClassInstanceCreation) |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_name_in_new); |
| //TODO: let's just take the CIC automatically (no ambiguity -> no problem -> no dialog ;-) |
| |
| if (selectedExpression instanceof NullLiteral) { |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_null_literals); |
| } else if (selectedExpression instanceof ArrayInitializer) { |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_array_initializer); |
| } else if (selectedExpression instanceof Assignment) { |
| if (selectedExpression.getParent() instanceof Expression) |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_assignment); |
| else |
| return null; |
| |
| } else if (selectedExpression instanceof SimpleName){ |
| if ((((SimpleName)selectedExpression)).isDeclaration()) |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_names_in_declarations); |
| if (selectedExpression.getParent() instanceof QualifiedName && selectedExpression.getLocationInParent() == QualifiedName.NAME_PROPERTY |
| || selectedExpression.getParent() instanceof FieldAccess && selectedExpression.getLocationInParent() == FieldAccess.NAME_PROPERTY) |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_select_expression); |
| } |
| |
| return null; |
| } |
| |
| private RefactoringStatus checkExpressionBinding() { |
| return checkExpressionFragmentIsRValue(); |
| } |
| |
| // !! +/- same as in ExtractConstantRefactoring & ExtractTempRefactoring |
| private RefactoringStatus checkExpressionFragmentIsRValue() { |
| switch(Checks.checkExpressionIsRValue(fSelectedExpression)) { |
| case Checks.IS_RVALUE_GUESSED: |
| case Checks.NOT_RVALUE_MISC: |
| return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.IntroduceParameterRefactoring_select, null, Corext.getPluginId(), RefactoringStatusCodes.EXPRESSION_NOT_RVALUE, null); |
| case Checks.NOT_RVALUE_VOID: |
| return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.IntroduceParameterRefactoring_no_void, null, Corext.getPluginId(), RefactoringStatusCodes.EXPRESSION_NOT_RVALUE_VOID, null); |
| case Checks.IS_RVALUE: |
| return new RefactoringStatus(); |
| default: |
| Assert.isTrue(false); return null; |
| } |
| } |
| |
| public List<ParameterInfo> getParameterInfos() { |
| return fChangeSignatureProcessor.getParameterInfos(); |
| } |
| |
| public ParameterInfo getAddedParameterInfo() { |
| return fParameter; |
| } |
| |
| public String getMethodSignaturePreview() throws JavaModelException { |
| return fChangeSignatureProcessor.getNewMethodSignature(); |
| } |
| |
| //--- Input setting/validation |
| |
| public void setParameterName(String name) { |
| Assert.isNotNull(name); |
| fParameter.setNewName(name); |
| } |
| |
| /** |
| * must only be called <i>after</i> checkActivation() |
| * @return guessed parameter name |
| */ |
| public String guessedParameterName() { |
| String[] proposals= guessParameterNames(); |
| if (proposals.length == 0) |
| return ""; //$NON-NLS-1$ |
| else |
| return proposals[0]; |
| } |
| |
| // --- TODO: copied from ExtractTempRefactoring - should extract ------------------------------ |
| |
| /** |
| * Must only be called <i>after</i> checkActivation(). |
| * The first proposal should be used as "best guess" (if it exists). |
| * @return proposed variable names (may be empty, but not null). |
| */ |
| public String[] guessParameterNames() { |
| LinkedHashSet<String> proposals= new LinkedHashSet<String>(); //retain ordering, but prevent duplicates |
| if (fSelectedExpression instanceof MethodInvocation){ |
| proposals.addAll(guessTempNamesFromMethodInvocation((MethodInvocation) fSelectedExpression, fExcludedParameterNames)); |
| } |
| proposals.addAll(guessTempNamesFromExpression(fSelectedExpression, fExcludedParameterNames)); |
| return proposals.toArray(new String[proposals.size()]); |
| } |
| |
| private List<String> guessTempNamesFromMethodInvocation(MethodInvocation selectedMethodInvocation, String[] excludedVariableNames) { |
| String methodName= selectedMethodInvocation.getName().getIdentifier(); |
| for (int i= 0; i < KNOWN_METHOD_NAME_PREFIXES.length; i++) { |
| String prefix= KNOWN_METHOD_NAME_PREFIXES[i]; |
| if (! methodName.startsWith(prefix)) |
| continue; //not this prefix |
| if (methodName.length() == prefix.length()) |
| return Collections.emptyList(); // prefix alone -> don't take method name |
| char firstAfterPrefix= methodName.charAt(prefix.length()); |
| if (! Character.isUpperCase(firstAfterPrefix)) |
| continue; //not uppercase after prefix |
| //found matching prefix |
| String proposal= Character.toLowerCase(firstAfterPrefix) + methodName.substring(prefix.length() + 1); |
| methodName= proposal; |
| break; |
| } |
| String[] proposals= StubUtility.getLocalNameSuggestions(fSourceCU.getJavaProject(), methodName, 0, excludedVariableNames); |
| return Arrays.asList(proposals); |
| } |
| |
| private List<String> guessTempNamesFromExpression(Expression selectedExpression, String[] excluded) { |
| ITypeBinding expressionBinding= Bindings.normalizeForDeclarationUse( |
| selectedExpression.resolveTypeBinding(), |
| selectedExpression.getAST()); |
| String typeName= getQualifiedName(expressionBinding); |
| if (typeName.length() == 0) |
| typeName= expressionBinding.getName(); |
| if (typeName.length() == 0) |
| return Collections.emptyList(); |
| int typeParamStart= typeName.indexOf("<"); //$NON-NLS-1$ |
| if (typeParamStart != -1) |
| typeName= typeName.substring(0, typeParamStart); |
| String[] proposals= StubUtility.getLocalNameSuggestions(fSourceCU.getJavaProject(), typeName, expressionBinding.getDimensions(), excluded); |
| return Arrays.asList(proposals); |
| } |
| |
| // ---------------------------------------------------------------------- |
| |
| private static String getQualifiedName(ITypeBinding typeBinding) { |
| if (typeBinding.isAnonymous()) |
| return getQualifiedName(typeBinding.getSuperclass()); |
| if (! typeBinding.isArray()) |
| return typeBinding.getQualifiedName(); |
| else |
| return typeBinding.getElementType().getQualifiedName(); |
| } |
| |
| private void initializeExcludedParameterNames(CompilationUnitRewrite cuRewrite) { |
| IBinding[] bindings= new ScopeAnalyzer(cuRewrite.getRoot()).getDeclarationsInScope( |
| fSelectedExpression.getStartPosition(), ScopeAnalyzer.VARIABLES); |
| fExcludedParameterNames= new String[bindings.length]; |
| for (int i= 0; i < fExcludedParameterNames.length; i++) { |
| fExcludedParameterNames[i]= bindings[i].getName(); |
| } |
| } |
| |
| public RefactoringStatus validateInput() { |
| return fChangeSignatureProcessor.checkSignature(); |
| } |
| |
| //--- checkInput |
| |
| @Override |
| public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException { |
| fChangeSignatureRefactoring.setValidationContext(getValidationContext()); |
| try { |
| return fChangeSignatureRefactoring.checkFinalConditions(pm); |
| } finally { |
| fChangeSignatureRefactoring.setValidationContext(null); |
| } |
| } |
| |
| @Override |
| public Change createChange(IProgressMonitor pm) throws CoreException { |
| fChangeSignatureRefactoring.setValidationContext(getValidationContext()); |
| try { |
| Change[] changes= fChangeSignatureProcessor.getAllChanges(); |
| return new DynamicValidationRefactoringChange(getRefactoringDescriptor(), RefactoringCoreMessages.IntroduceParameterRefactoring_name, changes); |
| } finally { |
| fChangeSignatureRefactoring.setValidationContext(null); |
| pm.done(); |
| } |
| } |
| |
| private IntroduceParameterDescriptor getRefactoringDescriptor() { |
| ChangeMethodSignatureDescriptor extended= (ChangeMethodSignatureDescriptor) fChangeSignatureProcessor.createDescriptor(); |
| RefactoringContribution contribution= RefactoringCore.getRefactoringContribution(IJavaRefactorings.CHANGE_METHOD_SIGNATURE); |
| |
| Map<String, String> argumentsMap= contribution.retrieveArgumentMap(extended); |
| |
| final Map<String, String> arguments= new HashMap<String, String>(); |
| arguments.put(ATTRIBUTE_ARGUMENT, fParameter.getNewName()); |
| arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION, new Integer(fSelectionStart).toString() + " " + new Integer(fSelectionLength).toString()); //$NON-NLS-1$ |
| arguments.putAll(argumentsMap); |
| String signature= fChangeSignatureProcessor.getMethodName(); |
| try { |
| signature= fChangeSignatureProcessor.getOldMethodSignature(); |
| } catch (JavaModelException exception) { |
| JavaPlugin.log(exception); |
| } |
| final String description= Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_descriptor_description_short, BasicElementLabels.getJavaElementName(fChangeSignatureProcessor.getMethod().getElementName())); |
| final String header= Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_descriptor_description, new String[] { BasicElementLabels.getJavaElementName(fParameter.getNewName()), signature, BasicElementLabels.getJavaCodeString(ASTNodes.asString(fSelectedExpression))}); |
| final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(extended.getProject(), this, header); |
| comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_original_pattern, JavaElementLabels.getTextLabel(fChangeSignatureProcessor.getMethod(), |
| JavaElementLabels.ALL_FULLY_QUALIFIED))); |
| comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_expression_pattern, BasicElementLabels.getJavaCodeString(ASTNodes.asString(fSelectedExpression)))); |
| comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_parameter_pattern, BasicElementLabels.getJavaElementName(getAddedParameterInfo().getNewName()))); |
| return RefactoringSignatureDescriptorFactory.createIntroduceParameterDescriptor(extended.getProject(), description, comment.asString(), arguments, extended.getFlags()); |
| } |
| |
| private RefactoringStatus initialize(JavaRefactoringArguments arguments) { |
| fArguments= arguments; |
| final String selection= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION); |
| if (selection != null) { |
| int offset= -1; |
| int length= -1; |
| final StringTokenizer tokenizer= new StringTokenizer(selection); |
| if (tokenizer.hasMoreTokens()) |
| offset= Integer.valueOf(tokenizer.nextToken()).intValue(); |
| if (tokenizer.hasMoreTokens()) |
| length= Integer.valueOf(tokenizer.nextToken()).intValue(); |
| if (offset >= 0 && length >= 0) { |
| fSelectionStart= offset; |
| fSelectionLength= length; |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { selection, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION})); |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION)); |
| final String handle= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT); |
| if (handle != null) { |
| final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(arguments.getProject(), handle, false); |
| if (element == null || !element.exists() || element.getElementType() != IJavaElement.COMPILATION_UNIT) |
| return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getName(), IJavaRefactorings.INTRODUCE_PARAMETER); |
| else |
| fSourceCU= (ICompilationUnit)element; |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT)); |
| final String name= arguments.getAttribute(ATTRIBUTE_ARGUMENT); |
| if (name != null && !"".equals(name)) //$NON-NLS-1$ |
| fParameterName= name; |
| else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_ARGUMENT)); |
| return new RefactoringStatus(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public String getDelegateUpdatingTitle(boolean plural) { |
| if (plural) |
| return RefactoringCoreMessages.DelegateCreator_keep_original_changed_plural; |
| else |
| return RefactoringCoreMessages.DelegateCreator_keep_original_changed_singular; |
| } |
| } |