blob: cc9325d4eda2377609cd846865d7d69a3acd9030 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 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.reorg;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.participants.ReorgExecutionLog;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine;
import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
import org.eclipse.jdt.internal.corext.refactoring.nls.changes.CreateTextFileChange;
import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
import org.eclipse.jdt.internal.corext.util.JavaElementResourceMapping;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.SearchUtils;
public class CreateCopyOfCompilationUnitChange extends CreateTextFileChange {
private ICompilationUnit fOldCu;
private INewNameQuery fNameQuery;
public CreateCopyOfCompilationUnitChange(IPath path, String source, ICompilationUnit oldCu, INewNameQuery nameQuery) {
super(path, source, null, "java"); //$NON-NLS-1$
fOldCu= oldCu;
fNameQuery= nameQuery;
setEncoding(oldCu);
}
public Change perform(IProgressMonitor pm) throws CoreException {
ICompilationUnit unit= fOldCu;
ResourceMapping mapping= JavaElementResourceMapping.create(unit);
final Change result= super.perform(pm);
markAsExecuted(unit, mapping);
return result;
}
private void setEncoding(ICompilationUnit cunit) {
IResource resource= cunit.getResource();
// no file so the encoding is taken from the target
if (!(resource instanceof IFile))
return;
IFile file= (IFile)resource;
try {
String encoding= file.getCharset(false);
if (encoding != null) {
setEncoding(encoding, true);
} else {
encoding= file.getCharset(true);
if (encoding != null) {
setEncoding(encoding, false);
}
}
} catch (CoreException e) {
// do nothing. Take encoding from target
}
}
/*
* @see CreateFileChange#getOldFile()
*/
protected IFile getOldFile(IProgressMonitor pm) {
pm.beginTask("", 10); //$NON-NLS-1$
String oldSource= super.getSource();
IPath oldPath= super.getPath();
String newTypeName= fNameQuery.getNewName();
try {
String newSource= getCopiedFileSource(new SubProgressMonitor(pm, 9), fOldCu, newTypeName);
setSource(newSource);
setPath(constructNewPath(newTypeName));
return super.getOldFile(new SubProgressMonitor(pm, 1));
} catch (CoreException e) {
setSource(oldSource);
setPath(oldPath);
return super.getOldFile(pm);
}
}
private IPath constructNewPath(String newTypeName) {
String newCUName= JavaModelUtil.getRenamedCUName(fOldCu, newTypeName);
return ResourceUtil.getResource(fOldCu).getParent().getFullPath().append(newCUName);
}
private static String getCopiedFileSource(IProgressMonitor pm, ICompilationUnit cu, String newTypeName) throws CoreException {
ICompilationUnit wc= cu.getPrimary().getWorkingCopy(null);
try {
TextChangeManager manager= createChangeManager(pm, wc, newTypeName);
String result= manager.get(wc).getPreviewContent(new NullProgressMonitor());
return result;
} finally {
wc.discardWorkingCopy();
}
}
private static TextChangeManager createChangeManager(IProgressMonitor pm, ICompilationUnit wc, String newName) throws CoreException {
TextChangeManager manager= new TextChangeManager();
SearchResultGroup refs= getReferences(wc, pm);
if (refs == null)
return manager;
if (refs.getCompilationUnit() == null)
return manager;
String name= RefactoringCoreMessages.CopyRefactoring_update_ref;
SearchMatch[] results= refs.getSearchResults();
for (int j= 0; j < results.length; j++){
SearchMatch searchResult= results[j];
if (searchResult.getAccuracy() == SearchMatch.A_INACCURATE)
continue;
String oldName= wc.findPrimaryType().getElementName();
int length= oldName.length();
int offset= searchResult.getOffset() + searchResult.getLength() - length; // may be qualified
TextChangeCompatibility.addTextEdit(manager.get(wc), name, new ReplaceEdit(offset, length, newName));
}
return manager;
}
private static SearchResultGroup getReferences(ICompilationUnit wc, IProgressMonitor pm) throws JavaModelException{
pm.subTask(RefactoringCoreMessages.CopyRefactoring_searching);
IJavaSearchScope scope= SearchEngine.createJavaSearchScope(new IJavaElement[]{wc});
if (wc.findPrimaryType() == null)
return null;
SearchPattern pattern= createSearchPattern(wc.findPrimaryType());
SearchResultGroup[] groups= RefactoringSearchEngine.search(pattern, scope, pm, new ICompilationUnit[]{wc},
new RefactoringStatus()); //status cannot get an error by construction: search scope is only the CU.
// Assert.isTrue(groups.length <= 1); //just 1 file or none, but inaccurate matches can play bad here (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=106127)
for (int index= 0; index < groups.length; index++) {
SearchResultGroup group= groups[index];
if (group.getCompilationUnit().equals(wc))
return group;
}
return null;
}
private static SearchPattern createSearchPattern(IType type) throws JavaModelException{
SearchPattern pattern= SearchPattern.createPattern(type, IJavaSearchConstants.ALL_OCCURRENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
IMethod[] constructors= JavaElementUtil.getAllConstructors(type);
if (constructors.length == 0)
return pattern;
SearchPattern constructorDeclarationPattern= RefactoringSearchEngine.createOrPattern(constructors, IJavaSearchConstants.DECLARATIONS);
return SearchPattern.createOrPattern(pattern, constructorDeclarationPattern);
}
private void markAsExecuted(ICompilationUnit unit, ResourceMapping mapping) {
ReorgExecutionLog log= (ReorgExecutionLog)getAdapter(ReorgExecutionLog.class);
if (log != null) {
log.markAsProcessed(unit);
log.markAsProcessed(mapping);
}
}
}