blob: a4756baf9fc1e14570c20daa0da8772a55f52c4b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.dltk.internal.javascript.corext.refactoring.structure;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
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.dltk.core.IMethod;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.SourceRange;
import org.eclipse.dltk.core.manipulation.RefactoringChecks;
import org.eclipse.dltk.core.manipulation.SourceModuleChange;
import org.eclipse.dltk.core.search.IDLTKSearchConstants;
import org.eclipse.dltk.core.search.IDLTKSearchScope;
import org.eclipse.dltk.core.search.SearchMatch;
import org.eclipse.dltk.core.search.SearchPattern;
import org.eclipse.dltk.internal.corext.refactoring.CollectingSearchRequestor;
import org.eclipse.dltk.internal.corext.refactoring.RefactoringScopeFactory;
import org.eclipse.dltk.internal.corext.refactoring.RefactoringSearchEngine;
import org.eclipse.dltk.internal.corext.refactoring.ScriptRefactoringDescriptor;
import org.eclipse.dltk.internal.corext.refactoring.SearchResultGroup;
import org.eclipse.dltk.internal.corext.refactoring.base.ScriptStatusContext;
import org.eclipse.dltk.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
import org.eclipse.dltk.internal.corext.refactoring.util.ResourceUtil;
import org.eclipse.dltk.internal.corext.refactoring.util.TextChangeManager;
import org.eclipse.dltk.internal.javascript.core.manipulation.JavascriptManipulationPlugin;
import org.eclipse.dltk.internal.javascript.core.manipulation.Messages;
import org.eclipse.dltk.internal.javascript.corext.refactoring.Checks;
import org.eclipse.dltk.internal.javascript.corext.refactoring.ParameterInfo;
import org.eclipse.dltk.internal.javascript.corext.refactoring.RefactoringCoreMessages;
import org.eclipse.dltk.javascript.core.dom.CallExpression;
import org.eclipse.dltk.javascript.core.dom.DomFactory;
import org.eclipse.dltk.javascript.core.dom.DomPackage;
import org.eclipse.dltk.javascript.core.dom.Expression;
import org.eclipse.dltk.javascript.core.dom.FunctionExpression;
import org.eclipse.dltk.javascript.core.dom.Identifier;
import org.eclipse.dltk.javascript.core.dom.Node;
import org.eclipse.dltk.javascript.core.dom.Parameter;
import org.eclipse.dltk.javascript.core.dom.Source;
import org.eclipse.dltk.javascript.core.dom.VariableReference;
import org.eclipse.dltk.javascript.core.dom.rewrite.ASTConverter;
import org.eclipse.dltk.javascript.core.dom.rewrite.NodeFinder;
import org.eclipse.dltk.javascript.core.dom.rewrite.RefactoringUtils;
import org.eclipse.dltk.javascript.core.dom.rewrite.RewriteAnalyzer;
import org.eclipse.dltk.javascript.core.dom.rewrite.VariableLookup;
import org.eclipse.dltk.javascript.core.refactoring.descriptors.ChangeMethodSignatureDescriptor;
import org.eclipse.dltk.javascript.parser.JavaScriptParserUtil;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.change.ChangeDescription;
import org.eclipse.emf.ecore.change.util.ChangeRecorder;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
import org.eclipse.ltk.core.refactoring.TextChange;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
public class ChangeSignatureProcessor extends RefactoringProcessor {
//private static final String ATTRIBUTE_RETURN= "return"; //$NON-NLS-1$
//private static final String ATTRIBUTE_VISIBILITY= "visibility"; //$NON-NLS-1$
private static final String ATTRIBUTE_PARAMETER= "parameter"; //$NON-NLS-1$
private static final String ATTRIBUTE_DEFAULT= "default"; //$NON-NLS-1$
//private static final String ATTRIBUTE_KIND= "kind"; //$NON-NLS-1$
//private static final String ATTRIBUTE_DELEGATE= "delegate"; //$NON-NLS-1$
//private static final String ATTRIBUTE_DEPRECATE= "deprecate"; //$NON-NLS-1$
private List<ParameterInfo> fParameterInfos;
//private SourceModuleRewrite fBaseCuRewrite;
//private List fExceptionInfos;
private TextChangeManager fChangeManager;
private IMethod fMethod;
/*private IMethod fTopMethod;
private IMethod[] fRippleMethods;*/
private SearchResultGroup[] fReferences;
/*private ReturnTypeInfo fReturnTypeInfo;*/
private String fMethodName;
/*private int fVisibility;
private StubTypeContext fContextCuStartEnd;
private int fOldVarargIndex; // initialized in checkVarargs()*/
private BodyUpdater fBodyUpdater;
/*private IDefaultValueAdvisor fDefaultValueAdvisor;
private ITypeHierarchy fCachedTypeHierarchy= null;
private boolean fDelegateUpdating;
private boolean fDelegateDeprecation;
public ChangeSignatureProcessor(JavaRefactoringArguments arguments, RefactoringStatus status) throws JavaModelException {
this((IMethod) null);
status.merge(initialize(arguments));
}*/
/**
* Creates a new change signature refactoring.
* @param method the method, or <code>null</code> if invoked by scripting framework
* @throws JavaModelException if something's wrong with the given method
*/
public ChangeSignatureProcessor(IMethod method) {
fMethod= method;
//fOldVarargIndex= -1;
//fDelegateUpdating= false;
//fDelegateDeprecation= true;
if (fMethod != null) {
fParameterInfos= createParameterInfoList(method);
// fExceptionInfos is created in checkInitialConditions
//fReturnTypeInfo= new ReturnTypeInfo(Signature.toString(Signature.getReturnType(fMethod.getSignature())));
fMethodName= fMethod.getElementName();
//fVisibility= JdtFlags.getVisibilityCode(fMethod);
}
}
private static List<ParameterInfo> createParameterInfoList(IMethod method) {
try {
//String[] typeNames= method.getParameterTypes();
String[] oldNames= method.getParameterNames();
List<ParameterInfo> result= new ArrayList<ParameterInfo>(oldNames.length);
for (int i= 0; i < oldNames.length; i++){
ParameterInfo parameterInfo;
/*if (i == oldNames.length - 1 && Flags.isVarargs(method.getFlags())) {
String varargSignature= typeNames[i];
int arrayCount= Signature.getArrayCount(varargSignature);
String baseSignature= Signature.getElementType(varargSignature);
if (arrayCount > 1)
baseSignature= Signature.createArraySignature(baseSignature, arrayCount - 1);
parameterInfo= new ParameterInfo(Signature.toString(baseSignature) + ParameterInfo.ELLIPSIS, oldNames[i], i);
} else {
parameterInfo= new ParameterInfo(Signature.toString(typeNames[i]), oldNames[i], i);
}*/
// TODO retrieve types
parameterInfo = new ParameterInfo("", oldNames[i], i);
result.add(parameterInfo);
}
return result;
} catch(ModelException e) {
JavascriptManipulationPlugin.log(e);
return new ArrayList<ParameterInfo>(0);
}
}
/* (non-Javadoc)
* @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getProcessorName()
*/
public String getProcessorName() {
return RefactoringCoreMessages.ChangeSignatureRefactoring_modify_Parameters;
}
public IMethod getMethod() {
return fMethod;
}
public String getMethodName() {
return fMethodName;
}
/*public String getReturnTypeString() {
return fReturnTypeInfo.getNewTypeName();
}*/
public void setNewMethodName(String newMethodName){
Assert.isNotNull(newMethodName);
fMethodName= newMethodName;
}
/*public void setNewReturnTypeName(String newReturnTypeName){
Assert.isNotNull(newReturnTypeName);
fReturnTypeInfo.setNewTypeName(newReturnTypeName);
}*/
public boolean canChangeNameAndReturnType(){
try {
return ! fMethod.isConstructor();
} catch (ModelException e) {
JavascriptManipulationPlugin.log(e);
return false;
}
}
/**
* @return visibility
* @see org.eclipse.jdt.core.dom.Modifier
*/
/*public int getVisibility(){
return fVisibility;
}*/
/**
* @param visibility new visibility
* @see org.eclipse.jdt.core.dom.Modifier
*/
/*public void setVisibility(int visibility){
Assert.isTrue( visibility == Modifier.PUBLIC ||
visibility == Modifier.PROTECTED ||
visibility == Modifier.NONE ||
visibility == Modifier.PRIVATE);
fVisibility= visibility;
}*/
/*
* @see JdtFlags
*/
/*public int[] getAvailableVisibilities() throws JavaModelException{
if (fTopMethod.getDeclaringType().isInterface())
return new int[]{Modifier.PUBLIC};
else if (fTopMethod.getDeclaringType().isEnum() && fTopMethod.isConstructor())
return new int[]{ Modifier.NONE,
Modifier.PRIVATE};
else
return new int[]{ Modifier.PUBLIC,
Modifier.PROTECTED,
Modifier.NONE,
Modifier.PRIVATE};
}*/
/**
*
* @return List of <code>ParameterInfo</code> objects.
*/
public List<ParameterInfo> getParameterInfos(){
return fParameterInfos;
}
/**
* @return List of <code>ExceptionInfo</code> objects.
*/
/*public List getExceptionInfos(){
return fExceptionInfos;
}*/
public void setBodyUpdater(BodyUpdater bodyUpdater) {
fBodyUpdater= bodyUpdater;
}
/*public CompilationUnitRewrite getBaseCuRewrite() {
return fBaseCuRewrite;
}
//------------------- IDelegateUpdating ----------------------
public boolean canEnableDelegateUpdating() {
return true;
}
public boolean getDelegateUpdating() {
return fDelegateUpdating;
}
public void setDelegateUpdating(boolean updating) {
fDelegateUpdating= updating;
}
public void setDeprecateDelegates(boolean deprecate) {
fDelegateDeprecation= deprecate;
}
public boolean getDeprecateDelegates() {
return fDelegateDeprecation;
}
public String getDelegateUpdatingTitle(boolean plural) {
if (plural)
return RefactoringCoreMessages.DelegateCreator_keep_original_changed_plural;
else
return RefactoringCoreMessages.DelegateCreator_keep_original_changed_singular;
}*/
//------------------- /IDelegateUpdating ---------------------
public RefactoringStatus checkSignature() {
return checkSignature(false);
}
private RefactoringStatus checkSignature(boolean resolveBindings) {
RefactoringStatus result= new RefactoringStatus();
checkMethodName(result);
if (result.hasFatalError())
return result;
checkParameterNamesAndValues(result);
if (result.hasFatalError())
return result;
checkForDuplicateParameterNames(result);
if (result.hasFatalError())
return result;
/*try {
RefactoringStatus[] typeStati;
if (resolveBindings)
typeStati= TypeContextChecker.checkAndResolveMethodTypes(fMethod, getStubTypeContext(), getNotDeletedInfos(), fReturnTypeInfo);
else
typeStati= TypeContextChecker.checkMethodTypesSyntax(fMethod, getNotDeletedInfos(), fReturnTypeInfo);
for (int i= 0; i < typeStati.length; i++)
result.merge(typeStati[i]);
result.merge(checkVarargs());
} catch (CoreException e) {
//cannot do anything here
throw new RuntimeException(e);
}*/
//checkExceptions() unnecessary (IType always ok)
return result;
}
public boolean isSignatureSameAsInitial() throws ModelException {
//if (! isVisibilitySameAsInitial())
// return false;
if (! isMethodNameSameAsInitial())
return false;
//if (! isReturnTypeSameAsInitial())
// return false;
//if (! areExceptionsSameAsInitial())
// return false;
if (fMethod.getParameters().length == 0 && fParameterInfos.isEmpty())
return true;
if (areNamesSameAsInitial() && isOrderSameAsInitial() && areParameterTypesSameAsInitial())
return true;
return false;
}
/**
* @return true if the new method cannot coexist with the old method since
* the signatures are too much alike
*/
/*public boolean isSignatureClashWithInitial() {
if (!isMethodNameSameAsInitial())
return false; // name has changed.
if (fMethod.getNumberOfParameters() == 0 && fParameterInfos.isEmpty())
return true; // name is equal and both parameter lists are empty
// name is equal and there are some parameters.
// check if there are more or less parameters than before
int no= getNotDeletedInfos().size();
if (fMethod.getNumberOfParameters() != no)
return false;
// name is equal and parameter count is equal.
// check whether types remained the same
if (isOrderSameAsInitial())
return areParameterTypesSameAsInitial();
else
return false; // could be more specific here
}*/
private boolean areParameterTypesSameAsInitial() {
for (ParameterInfo info : fParameterInfos) {
if (! info.isAdded() && ! info.isDeleted() && info.isTypeNameChanged())
return false;
}
return true;
}
/*private boolean isReturnTypeSameAsInitial() {
return ! fReturnTypeInfo.isTypeNameChanged();
}*/
private boolean isMethodNameSameAsInitial() {
return fMethodName.equals(fMethod.getElementName());
}
/*private boolean areExceptionsSameAsInitial() {
for (Iterator iter= fExceptionInfos.iterator(); iter.hasNext();) {
ExceptionInfo info= (ExceptionInfo) iter.next();
if (! info.isOld())
return false;
}
return true;
}*/
private void checkParameterNamesAndValues(RefactoringStatus result) {
int i= 1;
for (ParameterInfo info : fParameterInfos) {
if (info.isDeleted())
continue;
checkParameterName(result, info, i);
if (result.hasFatalError())
return;
if (info.isAdded()) {
checkParameterDefaultValue(result, info);
if (result.hasFatalError())
return;
}
}
}
private void checkParameterName(RefactoringStatus result, ParameterInfo info, int position) {
if (info.getNewName().trim().length() == 0) {
result.addFatalError(Messages.format(
RefactoringCoreMessages.ChangeSignatureRefactoring_param_name_not_empty, Integer.toString(position)));
} else {
result.merge(Checks.validateIdentifier(info.getNewName()));
// TODO checkTempName is actually more complicated
//result.merge(Checks.checkTempName(info.getNewName(), fMethod));
}
}
private void checkMethodName(RefactoringStatus result) {
if (isMethodNameSameAsInitial() || ! canChangeNameAndReturnType())
return;
if ("".equals(fMethodName.trim())) { //$NON-NLS-1$
String msg= RefactoringCoreMessages.ChangeSignatureRefactoring_method_name_not_empty;
result.addFatalError(msg);
return;
}
result.merge(Checks.validateIdentifier(fMethodName));
//result.merge(Checks.checkMethodName(fMethodName, fMethod));
}
private void checkParameterDefaultValue(RefactoringStatus result, ParameterInfo info) {
/*if (fDefaultValueAdvisor != null)
return;
if (info.isNewVarargs()) {
if (! isValidVarargsExpression(info.getDefaultValue())){
String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_invalid_expression, new String[]{info.getDefaultValue()});
result.addFatalError(msg);
}
return;
}*/
if (info.getDefaultValue().trim().equals("")){ //$NON-NLS-1$
String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_default_value,
info.getNewName()/*BasicElementLabels.getJavaElementName(info.getNewName())*/);
result.addFatalError(msg);
return;
}
// TODO check default value for validity
/*if (! isValidExpression(info.getDefaultValue())) {
String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_invalid_expression, new String[]{info.getDefaultValue()});
result.addFatalError(msg);
}*/
}
/*private RefactoringStatus checkVarargs() throws JavaModelException {
RefactoringStatus result= checkOriginalVarargs();
if (result != null)
return result;
if (fRippleMethods != null) {
for (int iRipple= 0; iRipple < fRippleMethods.length; iRipple++) {
IMethod rippleMethod= fRippleMethods[iRipple];
if (! JdtFlags.isVarargs(rippleMethod))
continue;
// Vararg method can override method that takes an array as last argument
fOldVarargIndex= rippleMethod.getNumberOfParameters() - 1;
List notDeletedInfos= getNotDeletedInfos();
for (int i= 0; i < notDeletedInfos.size(); i++) {
ParameterInfo info= (ParameterInfo) notDeletedInfos.get(i);
if (fOldVarargIndex != -1 && info.getOldIndex() == fOldVarargIndex && ! info.isNewVarargs()) {
String rippleMethodType= rippleMethod.getDeclaringType().getFullyQualifiedName('.');
String message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_ripple_cannot_convert_vararg, new Object[] { BasicElementLabels.getJavaElementName(info.getNewName()), BasicElementLabels.getJavaElementName(rippleMethodType)});
return RefactoringStatus.createFatalErrorStatus(message, JavaStatusContext.create(rippleMethod));
}
}
}
}
return null;
}
private RefactoringStatus checkOriginalVarargs() throws JavaModelException {
if (JdtFlags.isVarargs(fMethod))
fOldVarargIndex= fMethod.getNumberOfParameters() - 1;
List notDeletedInfos= getNotDeletedInfos();
for (int i= 0; i < notDeletedInfos.size(); i++) {
ParameterInfo info= (ParameterInfo) notDeletedInfos.get(i);
if (info.isOldVarargs() && ! info.isNewVarargs())
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_cannot_convert_vararg, BasicElementLabels.getJavaElementName(info.getNewName())));
if (i != notDeletedInfos.size() - 1) {
// not the last parameter
if (info.isNewVarargs())
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_vararg_must_be_last, BasicElementLabels.getJavaElementName(info.getNewName())));
}
}
return null;
}
private RefactoringStatus checkTypeVariables() {
if (fRippleMethods.length == 1)
return null;
RefactoringStatus result= new RefactoringStatus();
if (fReturnTypeInfo.isTypeNameChanged() && fReturnTypeInfo.getNewTypeBinding() != null) {
HashSet typeVariablesCollector= new HashSet();
collectTypeVariables(fReturnTypeInfo.getNewTypeBinding(), typeVariablesCollector);
if (typeVariablesCollector.size() != 0) {
ITypeBinding first= (ITypeBinding) typeVariablesCollector.iterator().next();
String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_return_type_contains_type_variable, new String[] {BasicElementLabels.getJavaElementName(fReturnTypeInfo.getNewTypeName()), BasicElementLabels.getJavaElementName(first.getName())});
result.addError(msg);
}
}
for (Iterator iter= getNotDeletedInfos().iterator(); iter.hasNext();) {
ParameterInfo info= (ParameterInfo) iter.next();
if (info.isTypeNameChanged() && info.getNewTypeBinding() != null) {
HashSet typeVariablesCollector= new HashSet();
collectTypeVariables(info.getNewTypeBinding(), typeVariablesCollector);
if (typeVariablesCollector.size() != 0) {
ITypeBinding first= (ITypeBinding) typeVariablesCollector.iterator().next();
String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_parameter_type_contains_type_variable, new String[] {BasicElementLabels.getJavaElementName(info.getNewTypeName()), BasicElementLabels.getJavaElementName(info.getNewName()), BasicElementLabels.getJavaElementName(first.getName())});
result.addError(msg);
}
}
}
return result;
}
private void collectTypeVariables(ITypeBinding typeBinding, Set typeVariablesCollector) {
if (typeBinding.isTypeVariable()) {
typeVariablesCollector.add(typeBinding);
ITypeBinding[] typeBounds= typeBinding.getTypeBounds();
for (int i= 0; i < typeBounds.length; i++)
collectTypeVariables(typeBounds[i], typeVariablesCollector);
} else if (typeBinding.isArray()) {
collectTypeVariables(typeBinding.getElementType(), typeVariablesCollector);
} else if (typeBinding.isParameterizedType()) {
ITypeBinding[] typeArguments= typeBinding.getTypeArguments();
for (int i= 0; i < typeArguments.length; i++)
collectTypeVariables(typeArguments[i], typeVariablesCollector);
} else if (typeBinding.isWildcardType()) {
ITypeBinding bound= typeBinding.getBound();
if (bound != null) {
collectTypeVariables(bound, typeVariablesCollector);
}
}
}
public static boolean isValidExpression(String string){
String trimmed= string.trim();
if ("".equals(trimmed)) //speed up for a common case //$NON-NLS-1$
return false;
StringBuffer cuBuff= new StringBuffer();
cuBuff.append(CONST_CLASS_DECL)
.append("Object") //$NON-NLS-1$
.append(CONST_ASSIGN);
int offset= cuBuff.length();
cuBuff.append(trimmed)
.append(CONST_CLOSE);
ASTParser p= ASTParser.newParser(AST.JLS3);
p.setSource(cuBuff.toString().toCharArray());
CompilationUnit cu= (CompilationUnit) p.createAST(null);
Selection selection= Selection.createFromStartLength(offset, trimmed.length());
SelectionAnalyzer analyzer= new SelectionAnalyzer(selection, false);
cu.accept(analyzer);
ASTNode selected= analyzer.getFirstSelectedNode();
return (selected instanceof Expression) &&
trimmed.equals(cuBuff.substring(cu.getExtendedStartPosition(selected), cu.getExtendedStartPosition(selected) + cu.getExtendedLength(selected)));
}
public static boolean isValidVarargsExpression(String string) {
String trimmed= string.trim();
if ("".equals(trimmed)) //speed up for a common case //$NON-NLS-1$
return true;
StringBuffer cuBuff= new StringBuffer();
cuBuff.append("class A{ {m("); //$NON-NLS-1$
int offset= cuBuff.length();
cuBuff.append(trimmed)
.append(");}}"); //$NON-NLS-1$
ASTParser p= ASTParser.newParser(AST.JLS3);
p.setSource(cuBuff.toString().toCharArray());
CompilationUnit cu= (CompilationUnit) p.createAST(null);
Selection selection= Selection.createFromStartLength(offset, trimmed.length());
SelectionAnalyzer analyzer= new SelectionAnalyzer(selection, false);
cu.accept(analyzer);
ASTNode[] selectedNodes= analyzer.getSelectedNodes();
if (selectedNodes.length == 0)
return false;
for (int i= 0; i < selectedNodes.length; i++) {
if (! (selectedNodes[i] instanceof Expression))
return false;
}
return true;
}
public StubTypeContext getStubTypeContext() {
try {
if (fContextCuStartEnd == null)
fContextCuStartEnd= TypeContextChecker.createStubTypeContext(getCu(), fBaseCuRewrite.getRoot(), fMethod.getSourceRange().getOffset());
} catch (CoreException e) {
//cannot do anything here
throw new RuntimeException(e);
}
return fContextCuStartEnd;
}
private ITypeHierarchy getCachedTypeHierarchy(IProgressMonitor monitor) throws JavaModelException {
if (fCachedTypeHierarchy == null)
fCachedTypeHierarchy= fMethod.getDeclaringType().newTypeHierarchy(new SubProgressMonitor(monitor, 1));
return fCachedTypeHierarchy;
}*/
/* (non-Javadoc)
* @see org.eclipse.ltk.core.refactoring.Refactoring#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor)
*/
public RefactoringStatus checkInitialConditions(IProgressMonitor monitor) throws CoreException {
try {
monitor.beginTask("", 1); //$NON-NLS-1$
RefactoringStatus result= RefactoringChecks.checkIfCuBroken(fMethod);
if (result.hasFatalError())
return result;
if (fMethod == null || !fMethod.exists()) {
String message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_method_deleted,
getCu().getResource().getName()/*BasicElementLabels.getFileName(getCu())*/);
return RefactoringStatus.createFatalErrorStatus(message);
}
// TODO most of checks are irrelevant, not necessarily all of them
/*if (fMethod.getDeclaringType().isInterface()) {
fTopMethod= MethodChecks.overridesAnotherMethod(fMethod, fMethod.getDeclaringType().newSupertypeHierarchy(new SubProgressMonitor(monitor, 1)));
monitor.worked(1);
} else if (MethodChecks.isVirtual(fMethod)) {
ITypeHierarchy hierarchy= getCachedTypeHierarchy(new SubProgressMonitor(monitor, 1));
fTopMethod= MethodChecks.isDeclaredInInterface(fMethod, hierarchy, new SubProgressMonitor(monitor, 1));
if (fTopMethod == null)
fTopMethod= MethodChecks.overridesAnotherMethod(fMethod, hierarchy);
}
if (fTopMethod == null)
fTopMethod= fMethod;
if (! fTopMethod.equals(fMethod)) {
if (fTopMethod.getDeclaringType().isInterface()) {
RefactoringStatusContext context= JavaStatusContext.create(fTopMethod);
String message= Messages.format(RefactoringCoreMessages.MethodChecks_implements,
new String[]{JavaElementUtil.createMethodSignature(fTopMethod), BasicElementLabels.getJavaElementName(fTopMethod.getDeclaringType().getFullyQualifiedName('.'))});
return RefactoringStatus.createStatus(RefactoringStatus.FATAL, message, context, Corext.getPluginId(), RefactoringStatusCodes.METHOD_DECLARED_IN_INTERFACE, fTopMethod);
} else {
RefactoringStatusContext context= JavaStatusContext.create(fTopMethod);
String message= Messages.format(RefactoringCoreMessages.MethodChecks_overrides,
new String[]{JavaElementUtil.createMethodSignature(fTopMethod), BasicElementLabels.getJavaElementName(fTopMethod.getDeclaringType().getFullyQualifiedName('.'))});
return RefactoringStatus.createStatus(RefactoringStatus.FATAL, message, context, Corext.getPluginId(), RefactoringStatusCodes.OVERRIDES_ANOTHER_METHOD, fTopMethod);
}
}
if (monitor.isCanceled())
throw new OperationCanceledException();
if (fBaseCuRewrite == null || !fBaseCuRewrite.getCu().equals(getCu())) {
fBaseCuRewrite= new CompilationUnitRewrite(getCu());
fBaseCuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer());
}
RefactoringStatus[] status= TypeContextChecker.checkMethodTypesSyntax(fMethod, getParameterInfos(), fReturnTypeInfo);
for (int i= 0; i < status.length; i++) {
result.merge(status[i]);
}
monitor.worked(1);
result.merge(createExceptionInfoList());*/
monitor.worked(1);
return result;
} finally {
monitor.done();
}
}
/*private RefactoringStatus createExceptionInfoList() {
if (fExceptionInfos == null || fExceptionInfos.isEmpty()) {
fExceptionInfos= new ArrayList(0);
try {
ASTNode nameNode= NodeFinder.perform(fBaseCuRewrite.getRoot(), fMethod.getNameRange());
if (nameNode == null || !(nameNode instanceof Name) || !(nameNode.getParent() instanceof MethodDeclaration))
return null;
MethodDeclaration methodDeclaration= (MethodDeclaration) nameNode.getParent();
List exceptions= methodDeclaration.thrownExceptions();
List result= new ArrayList(exceptions.size());
for (int i= 0; i < exceptions.size(); i++) {
Name name= (Name) exceptions.get(i);
ITypeBinding typeBinding= name.resolveTypeBinding();
if (typeBinding == null)
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_no_exception_binding);
IJavaElement element= typeBinding.getJavaElement();
result.add(ExceptionInfo.createInfoForOldException(element, typeBinding));
}
fExceptionInfos= result;
} catch (JavaModelException e) {
JavaPlugin.log(e);
}
}
return null;
}*/
/* (non-Javadoc)
* @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkFinalConditions(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext)
*/
public RefactoringStatus checkFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException, OperationCanceledException {
try {
pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 8);
RefactoringStatus result= new RefactoringStatus();
//fBaseCuRewrite.clearASTAndImportRewrites();
//fBaseCuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer());
if (isSignatureSameAsInitial())
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_unchanged);
result.merge(checkSignature(true));
if (result.hasFatalError())
return result;
//if (fDelegateUpdating && isSignatureClashWithInitial())
// result.merge(RefactoringStatus.createErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_old_and_new_signatures_not_sufficiently_different ));
//String binaryRefsDescription= Messages.format(RefactoringCoreMessages.ReferencesInBinaryContext_ref_in_binaries_description , BasicElementLabels.getJavaElementName(getMethodName()));
//ReferencesInBinaryContext binaryRefs= new ReferencesInBinaryContext(binaryRefsDescription);
//fRippleMethods= RippleMethodFinder2.getRelatedMethods(fMethod, binaryRefs, new SubProgressMonitor(pm, 1), null);
//result.merge(checkVarargs());
if (result.hasFatalError())
return result;
fReferences= findReferences(new SubProgressMonitor(pm, 1), result);
/*binaryRefs.addErrorIfNecessary(result);
result.merge(checkVisibilityChanges());
result.merge(checkTypeVariables());
//TODO:
// We need a common way of dealing with possible compilation errors for all occurrences,
// including visibility problems, shadowing and missing throws declarations.
if (! isOrderSameAsInitial())
result.merge(checkReorderings(new SubProgressMonitor(pm, 1)));
else
pm.worked(1);
//TODO (bug 58616): check whether changed signature already exists somewhere in the ripple,
// - error if exists
// - warn if exists with different parameter types (may cause overloading)
if (! areNamesSameAsInitial())
result.merge(checkRenamings(new SubProgressMonitor(pm, 1)));
else
pm.worked(1);
if (result.hasFatalError())
return result;*/
// resolveTypesWithoutBindings(new SubProgressMonitor(pm, 1)); // already done in checkSignature(true)
createChangeManager(new SubProgressMonitor(pm, 1), result);
//fCachedTypeHierarchy= null;
/*if (mustAnalyzeAstOfDeclaringCu())
result.merge(checkCompilationofDeclaringCu()); //TODO: should also check in ripple methods (move into createChangeManager)
if (result.hasFatalError())
return result;*/
RefactoringChecks.addModifiedFilesToChecker(getAllFilesToModify(), context);
return result;
} finally {
pm.done();
}
}
protected void clearManagers() {
fChangeManager= null;
}
/*private RefactoringStatus checkVisibilityChanges() throws JavaModelException {
if (isVisibilitySameAsInitial())
return null;
if (fRippleMethods.length == 1)
return null;
Assert.isTrue(JdtFlags.getVisibilityCode(fMethod) != Modifier.PRIVATE);
if (fVisibility == Modifier.PRIVATE)
return RefactoringStatus.createWarningStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_non_virtual);
return null;
}*/
public String getOldMethodSignature() throws ModelException {
StringBuffer buff= new StringBuffer();
//buff.append(ScriptElementLabels.getElementLabel(fMethod.getParent(), JavaElementLabels.ALL_FULLY_QUALIFIED));
//buff.append('.');
buff.append(fMethod.getElementName())
.append("(") //$NON-NLS-1$
.append(getOldMethodParameters())
.append(")"); //$NON-NLS-1$
//return BasicElementLabels.getJavaCodeString(buff.toString());
return buff.toString();
}
public String getNewMethodSignature() throws ModelException {
StringBuffer buff= new StringBuffer();
buff.append("function ") //$NON-NLS-1$
.append(getMethodName())
.append("(") //$NON-NLS-1$
.append(getMethodParameters())
.append(")"); //$NON-NLS-1$
//return BasicElementLabels.getJavaCodeString(buff.toString());
return buff.toString();
}
/*private String getVisibilityString(int visibility) {
String visibilityString= JdtFlags.getVisibilityString(visibility);
if ("".equals(visibilityString)) //$NON-NLS-1$
return visibilityString;
return visibilityString + ' ';
}
private String getMethodThrows() {
final String throwsString= " throws "; //$NON-NLS-1$
StringBuffer buff= new StringBuffer(throwsString);
for (Iterator iter= fExceptionInfos.iterator(); iter.hasNext(); ) {
ExceptionInfo info= (ExceptionInfo) iter.next();
if (! info.isDeleted()) {
buff.append(info.getElement().getElementName());
buff.append(", "); //$NON-NLS-1$
}
}
if (buff.length() == throwsString.length())
return ""; //$NON-NLS-1$
buff.delete(buff.length() - 2, buff.length());
return buff.toString();
}
private String getOldMethodThrows() {
final String throwsString= " throws "; //$NON-NLS-1$
StringBuffer buff= new StringBuffer(throwsString);
for (Iterator iter= fExceptionInfos.iterator(); iter.hasNext(); ) {
ExceptionInfo info= (ExceptionInfo) iter.next();
if (! info.isAdded()) {
buff.append(info.getElement().getElementName());
buff.append(", "); //$NON-NLS-1$
}
}
if (buff.length() == throwsString.length())
return ""; //$NON-NLS-1$
buff.delete(buff.length() - 2, buff.length());
return buff.toString();
}*/
private void checkForDuplicateParameterNames(RefactoringStatus result){
Set<String> found= new HashSet<String>();
Set<String> doubled= new HashSet<String>();
for (ParameterInfo info : getNotDeletedInfos()) {
String newName= info.getNewName();
if (found.contains(newName) && !doubled.contains(newName)){
result.addFatalError(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_duplicate_name,
newName/*BasicElementLabels.getJavaElementName(newName)*/));
doubled.add(newName);
} else {
found.add(newName);
}
}
}
private ISourceModule getCu() {
return fMethod.getSourceModule();
}
/*private boolean mustAnalyzeAstOfDeclaringCu() throws JavaModelException{
if (JdtFlags.isAbstract(getMethod()))
return false;
else if (JdtFlags.isNative(getMethod()))
return false;
else if (getMethod().getDeclaringType().isInterface())
return false;
else
return true;
}
private RefactoringStatus checkCompilationofDeclaringCu() throws CoreException {
ICompilationUnit cu= getCu();
TextChange change= fChangeManager.get(cu);
String newCuSource= change.getPreviewContent(new NullProgressMonitor());
CompilationUnit newCUNode= new RefactoringASTParser(AST.JLS3).parse(newCuSource, cu, true, false, null);
IProblem[] problems= RefactoringAnalyzeUtil.getIntroducedCompileProblems(newCUNode, fBaseCuRewrite.getRoot());
RefactoringStatus result= new RefactoringStatus();
for (int i= 0; i < problems.length; i++) {
IProblem problem= problems[i];
if (shouldReport(problem, newCUNode))
result.addEntry(new RefactoringStatusEntry((problem.isError() ? RefactoringStatus.ERROR : RefactoringStatus.WARNING), problem.getMessage(), new JavaStringStatusContext(newCuSource, SourceRangeFactory.create(problem))));
}
return result;
}*/
/**
* Evaluates if a problem needs to be reported.
* @param problem the problem
* @param cu the AST containing the new source
* @return return <code>true</code> if the problem needs to be reported
*/
/*protected boolean shouldReport(IProblem problem, CompilationUnit cu) {
if (! problem.isError())
return false;
if (problem.getID() == IProblem.UndefinedType) //reported when trying to import
return false;
return true;
}*/
private String getOldMethodParameters() {
StringBuffer buff= new StringBuffer();
boolean first = true;
for (Object element : getNotAddedInfos()) {
ParameterInfo info= (ParameterInfo) element;
if (!first)
buff.append(", "); //$NON-NLS-1$
buff.append(createDeclarationString(info));
first = false;
}
return buff.toString();
}
private String getMethodParameters() {
StringBuffer buff= new StringBuffer();
boolean first = true;
for (ParameterInfo info : getNotDeletedInfos()) {
if (!first)
buff.append(", "); //$NON-NLS-1$
buff.append(createDeclarationString(info));
first = false;
}
return buff.toString();
}
private List<ParameterInfo> getAddedInfos(){
List<ParameterInfo> result= new ArrayList<ParameterInfo>(1);
for (ParameterInfo info : fParameterInfos) {
if (info.isAdded())
result.add(info);
}
return result;
}
private List<ParameterInfo> getDeletedInfos(){
List<ParameterInfo> result= new ArrayList<ParameterInfo>(1);
for (ParameterInfo info : fParameterInfos) {
if (info.isDeleted())
result.add(info);
}
return result;
}
private List<ParameterInfo> getNotAddedInfos(){
List<ParameterInfo> all= new ArrayList<ParameterInfo>(fParameterInfos);
all.removeAll(getAddedInfos());
return all;
}
private List<ParameterInfo> getNotDeletedInfos(){
List<ParameterInfo> all= new ArrayList<ParameterInfo>(fParameterInfos);
all.removeAll(getDeletedInfos());
return all;
}
private boolean areNamesSameAsInitial() {
for (ParameterInfo info : fParameterInfos) {
if (info.isRenamed())
return false;
}
return true;
}
private boolean isOrderSameAsInitial(){
int i= 0;
for (ParameterInfo info : fParameterInfos) {
if (info.isDeleted() || info.getOldIndex() != i)
return false;
i++;
}
return true;
}
/*private RefactoringStatus checkReorderings(IProgressMonitor pm) throws JavaModelException {
try{
pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 1);
return checkNativeMethods();
} finally{
pm.done();
}
}*/
/*private RefactoringStatus checkRenamings(IProgressMonitor pm) throws ModelException {
try{
pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 1);
return checkParameterNamesInRippleMethods();
} finally{
pm.done();
}
}
private RefactoringStatus checkParameterNamesInRippleMethods() throws ModelException {
RefactoringStatus result= new RefactoringStatus();
Set newParameterNames= getNewParameterNamesList();
for (int i= 0; i < fRippleMethods.length; i++) {
String[] paramNames= fRippleMethods[i].getParameterNames();
for (int j= 0; j < paramNames.length; j++) {
if (newParameterNames.contains(paramNames[j])){
String[] args= new String[]{ JavaElementUtil.createMethodSignature(fRippleMethods[i]), BasicElementLabels.getJavaElementName(paramNames[j])};
String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_already_has, args);
RefactoringStatusContext context= JavaStatusContext.create(fRippleMethods[i].getCompilationUnit(), fRippleMethods[i].getNameRange());
result.addError(msg, context);
}
}
}
return result;
}
private Set getNewParameterNamesList() {
Set oldNames= getOriginalParameterNames();
Set currentNames= getNamesOfNotDeletedParameters();
currentNames.removeAll(oldNames);
return currentNames;
}
private Set getNamesOfNotDeletedParameters() {
Set result= new HashSet();
for (Iterator iter= getNotDeletedInfos().iterator(); iter.hasNext();) {
ParameterInfo info= (ParameterInfo) iter.next();
result.add(info.getNewName());
}
return result;
}
private Set getOriginalParameterNames() {
Set result= new HashSet();
for (Iterator iter= fParameterInfos.iterator(); iter.hasNext();) {
ParameterInfo info= (ParameterInfo) iter.next();
if (! info.isAdded())
result.add(info.getOldName());
}
return result;
}
private RefactoringStatus checkNativeMethods() throws JavaModelException{
RefactoringStatus result= new RefactoringStatus();
for (int i= 0; i < fRippleMethods.length; i++) {
if (JdtFlags.isNative(fRippleMethods[i])){
String message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_native,
new String[]{JavaElementUtil.createMethodSignature(fRippleMethods[i]), BasicElementLabels.getJavaElementName(fRippleMethods[i].getDeclaringType().getFullyQualifiedName('.'))});
result.addError(message, JavaStatusContext.create(fRippleMethods[i]));
}
}
return result;
}*/
private IFile[] getAllFilesToModify(){
return ResourceUtil.getFiles(fChangeManager.getAllSourceModules());
}
public Change[] getAllChanges() {
return fChangeManager.getAllChanges();
}
/* (non-Javadoc)
* @see org.eclipse.ltk.core.refactoring.Refactoring#createChange(org.eclipse.core.runtime.IProgressMonitor)
*/
public Change createChange(IProgressMonitor pm) {
pm.beginTask("", 1); //$NON-NLS-1$
try {
return new DynamicValidationRefactoringChange(createDescriptor(), doGetRefactoringChangeName(), getAllChanges());
} finally {
clearManagers();
pm.done();
}
}
/*private ChangeMethodSignatureArguments getParticipantArguments() {
ArrayList parameterList= new ArrayList();
List pis= getParameterInfos();
String[] originalParameterTypeSigs= fMethod.getParameterTypes();
for (Iterator iter= pis.iterator(); iter.hasNext();) {
ParameterInfo pi= (ParameterInfo) iter.next();
if (!pi.isDeleted()) {
int oldIndex= pi.isAdded() ? -1 : pi.getOldIndex();
String newName= pi.getNewName();
String typeSig;
if (pi.isTypeNameChanged()) {
String newType= pi.getNewTypeName();
if (pi.isNewVarargs()) {
newType= ParameterInfo.stripEllipsis(newType) + "[]"; //$NON-NLS-1$
}
typeSig= Signature.createTypeSignature(newType, false);
} else {
typeSig= originalParameterTypeSigs[pi.getOldIndex()];
}
String defaultValue= pi.getDefaultValue();
parameterList.add(new Parameter(oldIndex, newName, typeSig, defaultValue));
}
}
Parameter[] parameters= (Parameter[]) parameterList.toArray(new Parameter[parameterList.size()]);
ArrayList exceptionList= new ArrayList();
List exceptionInfos= getExceptionInfos();
for (int i= 0; i < exceptionInfos.size(); i++) {
ExceptionInfo ei= (ExceptionInfo) exceptionInfos.get(i);
if (!ei.isDeleted()) {
int oldIndex= ei.isAdded() ? -1 : i;
String qualifiedTypeName= ei.getFullyQualifiedName();
String newTypeSig= Signature.createTypeSignature(qualifiedTypeName, true);
exceptionList.add(new ThrownException(oldIndex, newTypeSig));
}
}
ThrownException[] exceptions= (ThrownException[]) exceptionList.toArray(new ThrownException[exceptionList.size()]);
String returnTypeSig;
if (fReturnTypeInfo.isTypeNameChanged()) {
returnTypeSig= Signature.createTypeSignature(fReturnTypeInfo.getNewTypeName(), false);
} else {
try {
returnTypeSig= fMethod.getReturnType();
} catch (JavaModelException e) {
returnTypeSig= Signature.createTypeSignature(fReturnTypeInfo.getNewTypeName(), false);
}
}
return new ChangeMethodSignatureArguments(fMethodName, returnTypeSig, fVisibility, parameters, exceptions, fDelegateUpdating);
}*/
public ScriptRefactoringDescriptor createDescriptor() {
final Map arguments= new HashMap();
String project= null;
IScriptProject scriptProject= fMethod.getScriptProject();
if (scriptProject != null)
project= scriptProject.getElementName();
ChangeMethodSignatureDescriptor descriptor= null;
//try {
final String description= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_descriptor_description_short,
fMethod.getElementName()/*BasicElementLabels.getJavaElementName(fMethod.getElementName())*/);
//final String header= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_descriptor_description, new String[] { getOldMethodSignature(), getNewMethodSignature()});
//final JDTRefactoringDescriptorComment comment= createComment(project, header);
descriptor= new ChangeMethodSignatureDescriptor(project, description, ""/*comment.asString()*/, arguments, getDescriptorFlags());
arguments.put(ScriptRefactoringDescriptor.ATTRIBUTE_INPUT, ScriptRefactoringDescriptor.elementToHandle(project,fMethod));
arguments.put(ScriptRefactoringDescriptor.ATTRIBUTE_NAME, fMethodName);
/*arguments.put(ATTRIBUTE_DELEGATE, Boolean.valueOf(fDelegateUpdating).toString());
arguments.put(ATTRIBUTE_DEPRECATE, Boolean.valueOf(fDelegateDeprecation).toString());
if (fReturnTypeInfo.isTypeNameChanged())
arguments.put(ATTRIBUTE_RETURN, fReturnTypeInfo.getNewTypeName());
try {
if (!isVisibilitySameAsInitial())
arguments.put(ATTRIBUTE_VISIBILITY, new Integer(fVisibility).toString());
} catch (JavaModelException exception) {
JavaPlugin.log(exception);
}*/
int count= 1;
for (ParameterInfo info : fParameterInfos) {
final StringBuffer buffer= new StringBuffer(64);
if (info.isAdded())
buffer.append("{added}"); //$NON-NLS-1$
else
buffer.append(info.getOldTypeName());
buffer.append(" "); //$NON-NLS-1$
if (info.isAdded())
buffer.append("{added}"); //$NON-NLS-1$
else
buffer.append(info.getOldName());
buffer.append(" "); //$NON-NLS-1$
buffer.append(info.getOldIndex());
buffer.append(" "); //$NON-NLS-1$
if (info.isDeleted())
buffer.append("{deleted}"); //$NON-NLS-1$
else
buffer.append(info.getNewTypeName().replaceAll(" ", "")); //$NON-NLS-1$//$NON-NLS-2$
buffer.append(" "); //$NON-NLS-1$
if (info.isDeleted())
buffer.append("{deleted}"); //$NON-NLS-1$
else
buffer.append(info.getNewName());
buffer.append(" "); //$NON-NLS-1$
buffer.append(info.isDeleted());
arguments.put(ATTRIBUTE_PARAMETER + count, buffer.toString());
final String value= info.getDefaultValue();
if (value != null && !"".equals(value)) //$NON-NLS-1$
arguments.put(ATTRIBUTE_DEFAULT + count, value);
count++;
}
/*count= 1;
for (final Iterator iterator= fExceptionInfos.iterator(); iterator.hasNext();) {
final ExceptionInfo info= (ExceptionInfo) iterator.next();
arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + count, JavaRefactoringDescriptorUtil.elementToHandle(project,info.getElement()));
arguments.put(ATTRIBUTE_KIND + count, new Integer(info.getKind()).toString());
count++;
}
} catch (ModelException exception) {
JavascriptManipulationPlugin.log(exception);
return null;
}*/
return descriptor;
}
protected int getDescriptorFlags() {
/*int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE;
try {
if (!Flags.isPrivate(fMethod.getFlags()))
flags|= RefactoringDescriptor.MULTI_CHANGE;
final IType declaring= fMethod.getDeclaringType();
if (declaring.isAnonymous() || declaring.isLocal())
flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
} catch (JavaModelException exception) {
JavaPlugin.log(exception);
}
return flags;*/
return ScriptRefactoringDescriptor.ARCHIVE_IMPORTABLE | ScriptRefactoringDescriptor.ARCHIVE_REFACTORABLE
| RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE;
}
/*private JDTRefactoringDescriptorComment createComment(String project, final String header) throws JavaModelException {
final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
if (!fMethod.getElementName().equals(fMethodName))
comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_name_pattern, BasicElementLabels.getJavaElementName(fMethodName)));
if (!isVisibilitySameAsInitial()) {
String visibility= JdtFlags.getVisibilityString(fVisibility);
if ("".equals(visibility)) //$NON-NLS-1$
visibility= RefactoringCoreMessages.ChangeSignatureRefactoring_default_visibility;
comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_visibility_pattern, visibility));
}
if (fReturnTypeInfo.isTypeNameChanged())
comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_return_type_pattern, BasicElementLabels.getJavaElementName(fReturnTypeInfo.getNewTypeName())));
List deleted= new ArrayList();
List added= new ArrayList();
List changed= new ArrayList();
for (final Iterator iterator= fParameterInfos.iterator(); iterator.hasNext();) {
final ParameterInfo info= (ParameterInfo) iterator.next();
if (info.isDeleted())
deleted.add(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_deleted_parameter_pattern, new String[] { BasicElementLabels.getJavaElementName(info.getOldTypeName()), BasicElementLabels.getJavaElementName(info.getOldName())}));
else if (info.isAdded())
added.add(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_added_parameter_pattern, new String[] { BasicElementLabels.getJavaElementName(info.getNewTypeName()), BasicElementLabels.getJavaElementName(info.getNewName())}));
else if (info.isRenamed() || info.isTypeNameChanged() || info.isVarargChanged())
changed.add(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_changed_parameter_pattern, new String[] { BasicElementLabels.getJavaElementName(info.getOldTypeName()), BasicElementLabels.getJavaElementName(info.getOldName())}));
}
if (!added.isEmpty())
comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_added_parameters, (String[]) added.toArray(new String[added.size()])));
if (!deleted.isEmpty())
comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_removed_parameters, (String[]) deleted.toArray(new String[deleted.size()])));
if (!changed.isEmpty())
comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_changed_parameters, (String[]) changed.toArray(new String[changed.size()])));
added.clear();
deleted.clear();
changed.clear();
for (final Iterator iterator= fExceptionInfos.iterator(); iterator.hasNext();) {
final ExceptionInfo info= (ExceptionInfo) iterator.next();
if (info.isAdded())
added.add(info.getElement().getElementName());
else if (info.isDeleted())
deleted.add(info.getElement().getElementName());
}
if (!added.isEmpty())
comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_added_exceptions, (String[]) added.toArray(new String[added.size()])));
if (!deleted.isEmpty())
comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_removed_exceptions, (String[]) deleted.toArray(new String[deleted.size()])));
return comment;
}*/
protected String doGetRefactoringChangeName() {
return RefactoringCoreMessages.ChangeSignatureRefactoring_restructure_parameters;
}
private TextChangeManager createChangeManager(IProgressMonitor pm, RefactoringStatus result) throws CoreException {
pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_preview, 1);
fChangeManager= new TextChangeManager();
/*boolean isNoArgConstructor= isNoArgConstructor();
Map namedSubclassMapping= null;
if (isNoArgConstructor){
//create only when needed;
namedSubclassMapping= createNamedSubclassMapping(new SubProgressMonitor(pm, 1));
}else{
pm.worked(1);
}*/
boolean decl = false;
for (int i= 0; i < fReferences.length; i++) {
SearchResultGroup group= fReferences[i];
ISourceModule cu= group.getSourceModule();
if (pm.isCanceled())
throw new OperationCanceledException();
processCu(cu,group.getSearchResults(),result);
if (cu.equals(fMethod.getSourceModule()))
decl = true;
}
if (!decl) {
if (pm.isCanceled())
throw new OperationCanceledException();
processCu(fMethod.getSourceModule(),Collections.EMPTY_LIST,result);
}
pm.done();
return fChangeManager;
}
private void processCu(ISourceModule cu, List<SearchMatch> searchResults, RefactoringStatus result)
throws ModelException {
if (cu == null)
return;
/*SourceModuleRewrite cuRewrite;
if (cu.equals(getCu())) {
cuRewrite= fBaseCuRewrite;
} else {
cuRewrite= new SourceModuleRewrite(cu);
cuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer());
}*/
Source root = (Source)ASTConverter.convert(JavaScriptParserUtil.parse(cu));
Node[] nodes= NodeFinder.findNodes(root, searchResults);
ChangeRecorder cr = new ChangeRecorder(root);
for(Node node : nodes) {
CallExpression call = RefactoringUtils.getFunctionReference(node);
if (call != null) {
Identifier id = (node instanceof Identifier) ? (Identifier)node : ((VariableReference)node).getVariable();
id.setName(fMethodName);
if (call.getArguments().size() != fMethod.getParameters().length)
result.addWarning(RefactoringCoreMessages.ChangeSignatureRefactoring_different_num_of_args,
ScriptStatusContext.create(cu, new SourceRange(node.getBegin(), node.getEnd()-node.getBegin())));
reshuffleElements(call.getArguments(),new NewElementsProvider<Expression>(){
@Override
Expression createElement(ParameterInfo info) {
// XXX Dirty hack indeed
VariableReference ref = DomFactory.eINSTANCE.createVariableReference();
Identifier id = DomFactory.eINSTANCE.createIdentifier();
if (info.getDefaultValue() == null) {
id.setName(ParameterInfo.DEFAULT_VALUE);
} else
id.setName(info.getDefaultValue());
ref.setVariable(id);
return ref;
}
});
} else {
result.addError(RefactoringCoreMessages.ChangeSignatureRefactoring_unknown_reference,
ScriptStatusContext.create(cu, new SourceRange(node.getBegin(), node.getEnd()-node.getBegin())));
tryRename(node);
}
}
if (cu.equals(fMethod.getSourceModule())) {
Node node = NodeFinder.findNode(root, fMethod.getNameRange());
FunctionExpression expr = null;
if (node == null) {
Node anon = NodeFinder.findNode(root, fMethod.getSourceRange());
if (anon.eClass().getClassifierID() == DomPackage.FUNCTION_EXPRESSION)
expr = (FunctionExpression)anon;
} else
expr = RefactoringUtils.getFunctionDeclaration(node);
if (expr != null) {
if (node != null)
((Identifier)node).setName(fMethodName);
else {
Identifier id = DomFactory.eINSTANCE.createIdentifier();
id.setName(fMethodName);
expr.setIdentifier(id);
}
reshuffleElements(expr.getParameters(),new NewElementsProvider<Parameter>(){
@Override
Parameter createElement(ParameterInfo info) {
Parameter param = DomFactory.eINSTANCE.createParameter();
Identifier id = DomFactory.eINSTANCE.createIdentifier();
id.setName(info.getNewName());
param.setName(id);
return param;
}
});
modifyElements(expr.getParameters());
result.merge(checkIfDeletedParametersUsed(expr.getBody(),cu));
updateBody(expr.getBody());
if (fBodyUpdater != null)
fBodyUpdater.updateBody(expr);
} else {
result.addError(RefactoringCoreMessages.ChangeSignatureRefactoring_unknown_reference,
ScriptStatusContext.create(cu, fMethod.getNameRange()));
tryRename(node);
}
}
ChangeDescription cd = cr.endRecording();
RewriteAnalyzer rewrite = new RewriteAnalyzer(cd, cu.getSource());
rewrite.rewrite(root);
cd.apply();
TextChange change = new SourceModuleChange(cu.getElementName(), cu);
change.setEdit(rewrite.getEdit());
fChangeManager.manage(cu, change);
}
private RefactoringStatus checkIfDeletedParametersUsed(Node node, ISourceModule cu) {
Set<String> deleted = new HashSet<String>();
for (ParameterInfo info : getDeletedInfos()) {
if (info.isDeleted())
deleted.add(info.getOldName());
}
List<Identifier> refs = VariableLookup.findReferences(node,deleted,true);
RefactoringStatus status = new RefactoringStatus();
for(Identifier ref : refs) {
SourceRange range = new SourceRange(ref.getBegin(), ref.getEnd()-ref.getBegin());
RefactoringStatusContext context= ScriptStatusContext.create(cu, range);
String[] keys= new String[]{ ref.getName(), fMethodName };
String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_parameter_used, keys);
status.addWarning(msg, context);
}
return status;
}
private void updateBody(Node node) {
Map<String,String> renaming = new HashMap<String,String>();
for (ParameterInfo info : getNotDeletedInfos()) {
if (!info.isDeleted())
renaming.put(info.getOldName(),info.getNewName());
}
List<Identifier> refs = VariableLookup.findReferences(node,renaming.keySet());
for(Identifier ref : refs) {
ref.setName(renaming.get(ref.getName()));
}
}
private static abstract class NewElementsProvider<T> {
abstract T createElement(ParameterInfo info);
}
private final <T extends Node> void reshuffleElements(EList<T> original, NewElementsProvider<T> provider) {
List<T> dst = new ArrayList<T>();
Set<T> deleted = new HashSet<T>();
{
for(ParameterInfo info : fParameterInfos) {
if (info.isDeleted()) {
if (info.getOldIndex() < original.size())
deleted.add(original.get(info.getOldIndex()));
} else {
if (info.isAdded() || info.getOldIndex() >= original.size())
dst.add(provider.createElement(info));
else
dst.add(original.get(info.getOldIndex()));
}
}
}
for(int i=0;i<dst.size()+1;i++) {
while (i < original.size() && deleted.contains(original.get(i)))
original.remove(i);
if (i == dst.size())
break;
T node = dst.get(i);
if (i < original.size() && original.get(i) == node)
continue;
if (original.contains(node))
original.move(i, node);
else
original.add(i, dst.get(i));
}
}
private final <T extends Node> void modifyElements(EList<Parameter> original) {
int i=0;
for(ParameterInfo info : fParameterInfos) {
if (info.isDeleted()) break;
if (!info.isAdded() && info.isRenamed())
original.get(i).getName().setName(info.getNewName());
// TODO check for types
i++;
}
}
private IDLTKSearchScope createRefactoringScope() throws ModelException {
return RefactoringScopeFactory.create(fMethod, true, false);
}
private SearchResultGroup[] findReferences(IProgressMonitor pm, RefactoringStatus status) throws CoreException {
//final boolean isConstructor= fMethod.isConstructor();
/*CuCollectingSearchRequestor requestor= new CuCollectingSearchRequestor(binaryRefs) {
protected void acceptSearchMatch(ISourceModule unit, SearchMatch match) throws CoreException {
// workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=27236 :
if (isConstructor && match instanceof MethodReferenceMatch) {
MethodReferenceMatch mrm= (MethodReferenceMatch) match;
if (mrm.isSynthetic()) {
return;
}
}
collectMatch(match);
}
};*/
CollectingSearchRequestor requestor = new CollectingSearchRequestor(true);
/*SearchPattern pattern;
if (isConstructor) {
// // workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=226151 : don't find binary refs for constructors for now
// return ConstructorReferenceFinder.getConstructorOccurrences(fMethod, pm, status);
// SearchPattern occPattern= SearchPattern.createPattern(fMethod, IJavaSearchConstants.ALL_OCCURRENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
SearchPattern declPattern= SearchPattern.createPattern(fMethod, IJavaSearchConstants.DECLARATIONS, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
SearchPattern refPattern= SearchPattern.createPattern(fMethod, IJavaSearchConstants.REFERENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
// pattern= SearchPattern.createOrPattern(declPattern, refPattern);
// pattern= occPattern;
// workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=226151 : do two searches
try {
SearchEngine engine= new SearchEngine();
engine.search(declPattern, SearchUtils.getDefaultSearchParticipants(), createRefactoringScope(), requestor, new NullProgressMonitor());
engine.search(refPattern, SearchUtils.getDefaultSearchParticipants(), createRefactoringScope(), requestor, pm);
} catch (CoreException e) {
throw new JavaModelException(e);
}
return RefactoringSearchEngine.groupByCu(requestor.getResults(), status);
} else {
pattern= RefactoringSearchEngine.createOrPattern(fRippleMethods, IJavaSearchConstants.ALL_OCCURRENCES);
}*/
SearchPattern pattern = SearchPattern.createPattern(fMethod, IDLTKSearchConstants.REFERENCES);
return RefactoringSearchEngine.search(pattern, createRefactoringScope(), requestor, pm, status);
}
private static String createDeclarationString(ParameterInfo info) {
return info.getNewName() + ("".equals(info.getNewTypeName()) ? "" : ":" + info.getNewTypeName()); //$NON-NL0S-1$
}
private void tryRename(Node node) {
if (node instanceof Identifier)
((Identifier) node).setName(fMethodName);
if (node instanceof VariableReference)
((VariableReference) node).getVariable().setName(fMethodName);
}
public Object[] getElements() {
return new Object[] { fMethod };
}
public String getIdentifier() {
return "org.eclipse.dltk.javascript.ui.changeMethodSignatureRefactoring"; //$NON-NLS-1$;
}
public boolean isApplicable() throws CoreException {
return Checks.isAvailable(fMethod);
//return RefactoringAvailabilityTester.isChangeSignatureAvailable(fMethod);
}
/*public final RefactoringParticipant[] loadParticipants(RefactoringStatus status, SharableParticipants shared) throws CoreException {
return getRenameModifications().loadParticipants(status, this, getAffectedProjectNatures(), shared);
}*/
public RefactoringParticipant[] loadParticipants(RefactoringStatus status, SharableParticipants sharedParticipants) throws CoreException {
//String[] affectedNatures= ScriptProcessors.computeAffectedNatures(fMethod);
return new RefactoringParticipant[0];
//return JavaParticipantManager.loadChangeMethodSignatureParticipants(status, this, fMethod, getParticipantArguments(), null, affectedNatures, sharedParticipants);
}
}