diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core')
11 files changed, 0 insertions, 3680 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipant.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipant.java deleted file mode 100644 index b821777a5..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipant.java +++ /dev/null @@ -1,547 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.internal.refactorings.core; - -import static com.android.SdkConstants.ANDROID_URI; -import static com.android.SdkConstants.ATTR_CLASS; -import static com.android.SdkConstants.ATTR_CONTEXT; -import static com.android.SdkConstants.ATTR_NAME; -import static com.android.SdkConstants.ATTR_PACKAGE; -import static com.android.SdkConstants.DOT_XML; -import static com.android.SdkConstants.EXT_XML; -import static com.android.SdkConstants.TOOLS_URI; -import static com.android.SdkConstants.VIEW_FRAGMENT; -import static com.android.SdkConstants.VIEW_TAG; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.ide.common.xml.ManifestData; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities; -import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper; -import com.android.ide.eclipse.adt.internal.sdk.ProjectState; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.resources.ResourceFolderType; -import com.android.utils.SdkUtils; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.OperationCanceledException; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IPackageFragment; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.internal.corext.refactoring.changes.RenamePackageChange; -import org.eclipse.jdt.internal.corext.refactoring.rename.RenameCompilationUnitProcessor; -import org.eclipse.jdt.internal.corext.refactoring.rename.RenameTypeProcessor; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.Region; -import org.eclipse.ltk.core.refactoring.Change; -import org.eclipse.ltk.core.refactoring.CompositeChange; -import org.eclipse.ltk.core.refactoring.FileStatusContext; -import org.eclipse.ltk.core.refactoring.NullChange; -import org.eclipse.ltk.core.refactoring.RefactoringStatus; -import org.eclipse.ltk.core.refactoring.RefactoringStatusContext; -import org.eclipse.ltk.core.refactoring.TextFileChange; -import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; -import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor; -import org.eclipse.ltk.core.refactoring.participants.RenameParticipant; -import org.eclipse.text.edits.MultiTextEdit; -import org.eclipse.text.edits.ReplaceEdit; -import org.eclipse.text.edits.TextEdit; -import org.eclipse.wst.sse.core.StructuredModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * A participant to participate in refactorings that rename a package in an Android project. - * The class updates android manifest and the layout file - * The user can suppress refactoring by disabling the "Update references" checkbox - * <p> - * Rename participants are registered via the extension point <code> - * org.eclipse.ltk.core.refactoring.renameParticipants</code>. - * Extensions to this extension point must therefore extend - * <code>org.eclipse.ltk.core.refactoring.participants.RenameParticipant</code>. - * </p> - */ -@SuppressWarnings("restriction") -public class AndroidPackageRenameParticipant extends RenameParticipant { - - private IProject mProject; - private IFile mManifestFile; - private IPackageFragment mPackageFragment; - private String mOldPackage; - private String mNewPackage; - private String mAppPackage; - private boolean mRefactoringAppPackage; - - @Override - public String getName() { - return "Android Package Rename"; - } - - @Override - public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) - throws OperationCanceledException { - if (mAppPackage.equals(mOldPackage) && !mRefactoringAppPackage) { - IRegion region = null; - Document document = DomUtilities.getDocument(mManifestFile); - if (document != null && document.getDocumentElement() != null) { - Attr attribute = document.getDocumentElement().getAttributeNode(ATTR_PACKAGE); - if (attribute instanceof IndexedRegion) { - IndexedRegion ir = (IndexedRegion) attribute; - int start = ir.getStartOffset(); - region = new Region(start, ir.getEndOffset() - start); - } - } - if (region == null) { - region = new Region(0, 0); - } - // There's no line wrapping in the error dialog, so split up the message into - // individually digestible pieces of information - RefactoringStatusContext ctx = new FileStatusContext(mManifestFile, region); - RefactoringStatus status = RefactoringStatus.createInfoStatus( - "You are refactoring the same package as your application's " + - "package (specified in the manifest).\n", ctx); - status.addInfo( - "Note that this refactoring does NOT also update your " + - "application package.", ctx); - status.addInfo("The application package defines your application's identity.", ctx); - status.addInfo( - "If you change it, then it is considered to be a different application.", ctx); - status.addInfo("(Users of the previous version cannot update to the new version.)", - ctx); - status.addInfo( - "The application package, and the package containing the code, can differ.", - ctx); - status.addInfo( - "To really change application package, " + - "choose \"Android Tools\" > \"Rename Application Package.\" " + - "from the project context menu.", ctx); - return status; - } - - return new RefactoringStatus(); - } - - @Override - protected boolean initialize(final Object element) { - mRefactoringAppPackage = false; - try { - // Only propose this refactoring if the "Update References" checkbox is set. - if (!getArguments().getUpdateReferences()) { - return false; - } - - if (element instanceof IPackageFragment) { - mPackageFragment = (IPackageFragment) element; - if (!mPackageFragment.containsJavaResources()) { - return false; - } - IJavaProject javaProject = (IJavaProject) mPackageFragment - .getAncestor(IJavaElement.JAVA_PROJECT); - mProject = javaProject.getProject(); - IResource manifestResource = mProject.findMember(AdtConstants.WS_SEP - + SdkConstants.FN_ANDROID_MANIFEST_XML); - - if (manifestResource == null || !manifestResource.exists() - || !(manifestResource instanceof IFile)) { - RefactoringUtil.logInfo("Invalid or missing the " - + SdkConstants.FN_ANDROID_MANIFEST_XML + " in the " - + mProject.getName() + " project."); - return false; - } - mManifestFile = (IFile) manifestResource; - String packageName = mPackageFragment.getElementName(); - ManifestData manifestData; - manifestData = AndroidManifestHelper.parseForData(mManifestFile); - if (manifestData == null) { - return false; - } - mAppPackage = manifestData.getPackage(); - mOldPackage = packageName; - mNewPackage = getArguments().getNewName(); - if (mOldPackage == null || mNewPackage == null) { - return false; - } - - if (RefactoringUtil.isRefactorAppPackage() - && mAppPackage != null - && mAppPackage.equals(packageName)) { - mRefactoringAppPackage = true; - } - - return true; - } - } catch (JavaModelException ignore) { - } - return false; - } - - - @Override - public Change createChange(IProgressMonitor pm) throws CoreException, - OperationCanceledException { - if (pm.isCanceled()) { - return null; - } - if (!getArguments().getUpdateReferences()) { - return null; - } - - RefactoringProcessor p = getProcessor(); - if (p instanceof RenameCompilationUnitProcessor) { - RenameTypeProcessor rtp = - ((RenameCompilationUnitProcessor) p).getRenameTypeProcessor(); - if (rtp != null) { - String pattern = rtp.getFilePatterns(); - boolean updQualf = rtp.getUpdateQualifiedNames(); - if (updQualf && pattern != null && pattern.contains("xml")) { //$NON-NLS-1$ - // Do not propose this refactoring if the - // "Update fully qualified names in non-Java files" option is - // checked and the file patterns mention XML. [c.f. SDK bug 21589] - return null; - } - } - } - - IPath pkgPath = mPackageFragment.getPath(); - IPath genPath = mProject.getFullPath().append(SdkConstants.FD_GEN_SOURCES); - if (genPath.isPrefixOf(pkgPath)) { - RefactoringUtil.logInfo(getName() + ": Cannot rename generated package."); - return null; - } - CompositeChange result = new CompositeChange(getName()); - result.markAsSynthetic(); - - addManifestFileChanges(result); - - // Update layout files; we don't just need to react to custom view - // changes, we need to update fragment references and even tool:context activity - // references - addLayoutFileChanges(mProject, result); - - // Also update in dependent projects - ProjectState projectState = Sdk.getProjectState(mProject); - if (projectState != null) { - Collection<ProjectState> parentProjects = projectState.getFullParentProjects(); - for (ProjectState parentProject : parentProjects) { - IProject project = parentProject.getProject(); - addLayoutFileChanges(project, result); - } - } - - if (mRefactoringAppPackage) { - Change genChange = getGenPackageChange(pm); - if (genChange != null) { - result.add(genChange); - } - - return new NullChange("Update Imports") { - @Override - public Change perform(IProgressMonitor monitor) throws CoreException { - FixImportsJob job = new FixImportsJob("Fix Rename Package", - mManifestFile, mNewPackage); - job.schedule(500); - - // Not undoable: just return null instead of an undo-change. - return null; - } - }; - } - - return (result.getChildren().length == 0) ? null : result; - } - - /** - * Returns Android gen package text change - * - * @param pm the progress monitor - * - * @return Android gen package text change - * @throws CoreException if an error happens - * @throws OperationCanceledException if the operation is canceled - */ - public Change getGenPackageChange(IProgressMonitor pm) throws CoreException, - OperationCanceledException { - if (mRefactoringAppPackage) { - IPackageFragment genJavaPackageFragment = getGenPackageFragment(); - if (genJavaPackageFragment != null && genJavaPackageFragment.exists()) { - return new RenamePackageChange(genJavaPackageFragment, mNewPackage, true); - } - } - return null; - } - - /** - * Return the gen package fragment - */ - private IPackageFragment getGenPackageFragment() throws JavaModelException { - IJavaProject javaProject = (IJavaProject) mPackageFragment - .getAncestor(IJavaElement.JAVA_PROJECT); - if (javaProject != null && javaProject.isOpen()) { - IProject project = javaProject.getProject(); - IFolder genFolder = project.getFolder(SdkConstants.FD_GEN_SOURCES); - if (genFolder.exists()) { - String javaPackagePath = mAppPackage.replace('.', '/'); - IPath genJavaPackagePath = genFolder.getFullPath().append(javaPackagePath); - IPackageFragment genPackageFragment = javaProject - .findPackageFragment(genJavaPackagePath); - return genPackageFragment; - } - } - return null; - } - - /** - * Returns the new class name - * - * @param fqcn the fully qualified class name in the renamed package - * @return the new class name - */ - private String getNewClassName(String fqcn) { - assert isInRenamedPackage(fqcn) : fqcn; - int lastDot = fqcn.lastIndexOf('.'); - if (lastDot < 0) { - return mNewPackage; - } - String name = fqcn.substring(lastDot, fqcn.length()); - String newClassName = mNewPackage + name; - return newClassName; - } - - private void addManifestFileChanges(CompositeChange result) { - addXmlFileChanges(mManifestFile, result, true); - } - - private void addLayoutFileChanges(IProject project, CompositeChange result) { - try { - // Update references in XML resource files - IFolder resFolder = project.getFolder(SdkConstants.FD_RESOURCES); - - IResource[] folders = resFolder.members(); - for (IResource folder : folders) { - String folderName = folder.getName(); - ResourceFolderType folderType = ResourceFolderType.getFolderType(folderName); - if (folderType != ResourceFolderType.LAYOUT) { - continue; - } - if (!(folder instanceof IFolder)) { - continue; - } - IResource[] files = ((IFolder) folder).members(); - for (int i = 0; i < files.length; i++) { - IResource member = files[i]; - if ((member instanceof IFile) && member.exists()) { - IFile file = (IFile) member; - String fileName = member.getName(); - - if (SdkUtils.endsWith(fileName, DOT_XML)) { - addXmlFileChanges(file, result, false); - } - } - } - } - } catch (CoreException e) { - RefactoringUtil.log(e); - } - } - - private boolean addXmlFileChanges(IFile file, CompositeChange changes, boolean isManifest) { - IModelManager modelManager = StructuredModelManager.getModelManager(); - IStructuredModel model = null; - try { - model = modelManager.getExistingModelForRead(file); - if (model == null) { - model = modelManager.getModelForRead(file); - } - if (model != null) { - IStructuredDocument document = model.getStructuredDocument(); - if (model instanceof IDOMModel) { - IDOMModel domModel = (IDOMModel) model; - Element root = domModel.getDocument().getDocumentElement(); - if (root != null) { - List<TextEdit> edits = new ArrayList<TextEdit>(); - if (isManifest) { - addManifestReplacements(edits, root, document); - } else { - addLayoutReplacements(edits, root, document); - } - if (!edits.isEmpty()) { - MultiTextEdit rootEdit = new MultiTextEdit(); - rootEdit.addChildren(edits.toArray(new TextEdit[edits.size()])); - TextFileChange change = new TextFileChange(file.getName(), file); - change.setTextType(EXT_XML); - change.setEdit(rootEdit); - changes.add(change); - } - } - } else { - return false; - } - } - - return true; - } catch (IOException e) { - AdtPlugin.log(e, null); - } catch (CoreException e) { - AdtPlugin.log(e, null); - } finally { - if (model != null) { - model.releaseFromRead(); - } - } - - return false; - } - - private boolean isInRenamedPackage(String fqcn) { - return fqcn.startsWith(mOldPackage) - && fqcn.length() > mOldPackage.length() - && fqcn.indexOf('.', mOldPackage.length() + 1) == -1; - } - - private void addLayoutReplacements( - @NonNull List<TextEdit> edits, - @NonNull Element element, - @NonNull IStructuredDocument document) { - String tag = element.getTagName(); - if (isInRenamedPackage(tag)) { - int start = RefactoringUtil.getTagNameRangeStart(element, document); - if (start != -1) { - int end = start + tag.length(); - edits.add(new ReplaceEdit(start, end - start, getNewClassName(tag))); - } - } else { - Attr classNode = null; - if (tag.equals(VIEW_TAG)) { - classNode = element.getAttributeNode(ATTR_CLASS); - } else if (tag.equals(VIEW_FRAGMENT)) { - classNode = element.getAttributeNode(ATTR_CLASS); - if (classNode == null) { - classNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME); - } - } else if (element.hasAttributeNS(TOOLS_URI, ATTR_CONTEXT)) { - classNode = element.getAttributeNodeNS(TOOLS_URI, ATTR_CONTEXT); - if (classNode != null && classNode.getValue().startsWith(".")) { //$NON-NLS-1$ - classNode = null; - } - } - if (classNode != null) { - String fqcn = classNode.getValue(); - if (isInRenamedPackage(fqcn)) { - int start = RefactoringUtil.getAttributeValueRangeStart(classNode, document); - if (start != -1) { - int end = start + fqcn.length(); - edits.add(new ReplaceEdit(start, end - start, getNewClassName(fqcn))); - } - } - } - } - - NodeList children = element.getChildNodes(); - for (int i = 0, n = children.getLength(); i < n; i++) { - Node child = children.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - addLayoutReplacements(edits, (Element) child, document); - } - } - } - - private void addManifestReplacements( - @NonNull List<TextEdit> edits, - @NonNull Element element, - @NonNull IStructuredDocument document) { - if (mRefactoringAppPackage && - element == element.getOwnerDocument().getDocumentElement()) { - // Update the app package declaration - Attr pkg = element.getAttributeNode(ATTR_PACKAGE); - if (pkg != null && pkg.getValue().equals(mOldPackage)) { - int start = RefactoringUtil.getAttributeValueRangeStart(pkg, document); - if (start != -1) { - int end = start + mOldPackage.length(); - edits.add(new ReplaceEdit(start, end - start, mNewPackage)); - } - } - } - - NamedNodeMap attributes = element.getAttributes(); - for (int i = 0, n = attributes.getLength(); i < n; i++) { - Attr attr = (Attr) attributes.item(i); - if (!RefactoringUtil.isManifestClassAttribute(attr)) { - continue; - } - - String value = attr.getValue(); - if (isInRenamedPackage(value)) { - int start = RefactoringUtil.getAttributeValueRangeStart(attr, document); - if (start != -1) { - int end = start + value.length(); - edits.add(new ReplaceEdit(start, end - start, getNewClassName(value))); - } - } else if (value.startsWith(".")) { - // If we're renaming the app package - String fqcn = mAppPackage + value; - if (isInRenamedPackage(fqcn)) { - int start = RefactoringUtil.getAttributeValueRangeStart(attr, document); - if (start != -1) { - int end = start + value.length(); - String newClassName = getNewClassName(fqcn); - if (mRefactoringAppPackage) { - newClassName = newClassName.substring(mNewPackage.length()); - } else if (newClassName.startsWith(mOldPackage) - && newClassName.charAt(mOldPackage.length()) == '.') { - newClassName = newClassName.substring(mOldPackage.length()); - } - - if (!newClassName.equals(value)) { - edits.add(new ReplaceEdit(start, end - start, newClassName)); - } - } - } - } - } - - NodeList children = element.getChildNodes(); - for (int i = 0, n = children.getLength(); i < n; i++) { - Node child = children.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - addManifestReplacements(edits, (Element) child, document); - } - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipant.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipant.java deleted file mode 100644 index 2146184c8..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipant.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.internal.refactorings.core; - -import static com.android.SdkConstants.ANDROID_URI; -import static com.android.SdkConstants.ATTR_CLASS; -import static com.android.SdkConstants.ATTR_CONTEXT; -import static com.android.SdkConstants.ATTR_NAME; -import static com.android.SdkConstants.DOT_XML; -import static com.android.SdkConstants.EXT_XML; -import static com.android.SdkConstants.TOOLS_URI; -import static com.android.SdkConstants.VIEW_FRAGMENT; -import static com.android.SdkConstants.VIEW_TAG; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.ide.common.xml.ManifestData; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper; -import com.android.ide.eclipse.adt.internal.sdk.ProjectState; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.resources.ResourceFolderType; -import com.android.utils.SdkUtils; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.OperationCanceledException; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IPackageFragment; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.ltk.core.refactoring.Change; -import org.eclipse.ltk.core.refactoring.CompositeChange; -import org.eclipse.ltk.core.refactoring.RefactoringStatus; -import org.eclipse.ltk.core.refactoring.TextFileChange; -import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; -import org.eclipse.ltk.core.refactoring.participants.MoveParticipant; -import org.eclipse.text.edits.MultiTextEdit; -import org.eclipse.text.edits.ReplaceEdit; -import org.eclipse.text.edits.TextEdit; -import org.eclipse.wst.sse.core.StructuredModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * A participant to participate in refactorings that move a type in an Android project. - * The class updates android manifest and the layout file - * The user can suppress refactoring by disabling the "Update references" checkbox - * <p> - * Rename participants are registered via the extension point <code> - * org.eclipse.ltk.core.refactoring.moveParticipants</code>. - * Extensions to this extension point must therefore extend <code>org.eclipse.ltk.core.refactoring.participants.MoveParticipant</code>. - * </p> - */ -@SuppressWarnings("restriction") -public class AndroidTypeMoveParticipant extends MoveParticipant { - - private IProject mProject; - protected IFile mManifestFile; - protected String mOldFqcn; - protected String mNewFqcn; - protected String mAppPackage; - - @Override - public String getName() { - return "Android Type Move"; - } - - @Override - public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) - throws OperationCanceledException { - return new RefactoringStatus(); - } - - @Override - protected boolean initialize(Object element) { - if (element instanceof IType) { - IType type = (IType) element; - IJavaProject javaProject = (IJavaProject) type.getAncestor(IJavaElement.JAVA_PROJECT); - mProject = javaProject.getProject(); - IResource manifestResource = mProject.findMember(AdtConstants.WS_SEP - + SdkConstants.FN_ANDROID_MANIFEST_XML); - - if (manifestResource == null || !manifestResource.exists() - || !(manifestResource instanceof IFile)) { - RefactoringUtil.logInfo("Invalid or missing the " - + SdkConstants.FN_ANDROID_MANIFEST_XML + " in the " + mProject.getName() - + " project."); - return false; - } - mManifestFile = (IFile) manifestResource; - ManifestData manifestData; - manifestData = AndroidManifestHelper.parseForData(mManifestFile); - if (manifestData == null) { - return false; - } - mAppPackage = manifestData.getPackage(); - mOldFqcn = type.getFullyQualifiedName(); - Object destination = getArguments().getDestination(); - if (destination instanceof IPackageFragment) { - IPackageFragment packageFragment = (IPackageFragment) destination; - mNewFqcn = packageFragment.getElementName() + "." + type.getElementName(); - } else if (destination instanceof IResource) { - try { - IPackageFragment[] fragments = javaProject.getPackageFragments(); - for (IPackageFragment fragment : fragments) { - IResource resource = fragment.getResource(); - if (resource.equals(destination)) { - mNewFqcn = fragment.getElementName() + '.' + type.getElementName(); - break; - } - } - } catch (JavaModelException e) { - // pass - } - } - return mOldFqcn != null && mNewFqcn != null; - } - - return false; - } - - @Override - public Change createChange(IProgressMonitor pm) throws CoreException, - OperationCanceledException { - if (pm.isCanceled()) { - return null; - } - if (!getArguments().getUpdateReferences()) { - return null; - } - CompositeChange result = new CompositeChange(getName()); - result.markAsSynthetic(); - - addManifestFileChanges(result); - - // Update layout files; we don't just need to react to custom view - // changes, we need to update fragment references and even tool:context activity - // references - addLayoutFileChanges(mProject, result); - - // Also update in dependent projects - ProjectState projectState = Sdk.getProjectState(mProject); - if (projectState != null) { - Collection<ProjectState> parentProjects = projectState.getFullParentProjects(); - for (ProjectState parentProject : parentProjects) { - IProject project = parentProject.getProject(); - addLayoutFileChanges(project, result); - } - } - - return (result.getChildren().length == 0) ? null : result; - } - - private void addManifestFileChanges(CompositeChange result) { - addXmlFileChanges(mManifestFile, result, true); - } - - private void addLayoutFileChanges(IProject project, CompositeChange result) { - try { - // Update references in XML resource files - IFolder resFolder = project.getFolder(SdkConstants.FD_RESOURCES); - - IResource[] folders = resFolder.members(); - for (IResource folder : folders) { - String folderName = folder.getName(); - ResourceFolderType folderType = ResourceFolderType.getFolderType(folderName); - if (folderType != ResourceFolderType.LAYOUT) { - continue; - } - if (!(folder instanceof IFolder)) { - continue; - } - IResource[] files = ((IFolder) folder).members(); - for (int i = 0; i < files.length; i++) { - IResource member = files[i]; - if ((member instanceof IFile) && member.exists()) { - IFile file = (IFile) member; - String fileName = member.getName(); - - if (SdkUtils.endsWith(fileName, DOT_XML)) { - addXmlFileChanges(file, result, false); - } - } - } - } - } catch (CoreException e) { - RefactoringUtil.log(e); - } - } - - private boolean addXmlFileChanges(IFile file, CompositeChange changes, boolean isManifest) { - IModelManager modelManager = StructuredModelManager.getModelManager(); - IStructuredModel model = null; - try { - model = modelManager.getExistingModelForRead(file); - if (model == null) { - model = modelManager.getModelForRead(file); - } - if (model != null) { - IStructuredDocument document = model.getStructuredDocument(); - if (model instanceof IDOMModel) { - IDOMModel domModel = (IDOMModel) model; - Element root = domModel.getDocument().getDocumentElement(); - if (root != null) { - List<TextEdit> edits = new ArrayList<TextEdit>(); - if (isManifest) { - addManifestReplacements(edits, root, document); - } else { - addLayoutReplacements(edits, root, document); - } - if (!edits.isEmpty()) { - MultiTextEdit rootEdit = new MultiTextEdit(); - rootEdit.addChildren(edits.toArray(new TextEdit[edits.size()])); - TextFileChange change = new TextFileChange(file.getName(), file); - change.setTextType(EXT_XML); - change.setEdit(rootEdit); - changes.add(change); - } - } - } else { - return false; - } - } - - return true; - } catch (IOException e) { - AdtPlugin.log(e, null); - } catch (CoreException e) { - AdtPlugin.log(e, null); - } finally { - if (model != null) { - model.releaseFromRead(); - } - } - - return false; - } - - private void addLayoutReplacements( - @NonNull List<TextEdit> edits, - @NonNull Element element, - @NonNull IStructuredDocument document) { - String tag = element.getTagName(); - if (tag.equals(mOldFqcn)) { - int start = RefactoringUtil.getTagNameRangeStart(element, document); - if (start != -1) { - int end = start + mOldFqcn.length(); - edits.add(new ReplaceEdit(start, end - start, mNewFqcn)); - } - } else if (tag.equals(VIEW_TAG)) { - Attr classNode = element.getAttributeNode(ATTR_CLASS); - if (classNode != null && classNode.getValue().equals(mOldFqcn)) { - int start = RefactoringUtil.getAttributeValueRangeStart(classNode, document); - if (start != -1) { - int end = start + mOldFqcn.length(); - edits.add(new ReplaceEdit(start, end - start, mNewFqcn)); - } - } - } else if (tag.equals(VIEW_FRAGMENT)) { - Attr classNode = element.getAttributeNode(ATTR_CLASS); - if (classNode == null) { - classNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME); - } - if (classNode != null && classNode.getValue().equals(mOldFqcn)) { - int start = RefactoringUtil.getAttributeValueRangeStart(classNode, document); - if (start != -1) { - int end = start + mOldFqcn.length(); - edits.add(new ReplaceEdit(start, end - start, mNewFqcn)); - } - } - } else if (element.hasAttributeNS(TOOLS_URI, ATTR_CONTEXT)) { - Attr classNode = element.getAttributeNodeNS(TOOLS_URI, ATTR_CONTEXT); - if (classNode != null && classNode.getValue().equals(mOldFqcn)) { - int start = RefactoringUtil.getAttributeValueRangeStart(classNode, document); - if (start != -1) { - int end = start + mOldFqcn.length(); - edits.add(new ReplaceEdit(start, end - start, mNewFqcn)); - } - } - } - - NodeList children = element.getChildNodes(); - for (int i = 0, n = children.getLength(); i < n; i++) { - Node child = children.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - addLayoutReplacements(edits, (Element) child, document); - } - } - } - - private void addManifestReplacements( - @NonNull List<TextEdit> edits, - @NonNull Element element, - @NonNull IStructuredDocument document) { - NamedNodeMap attributes = element.getAttributes(); - for (int i = 0, n = attributes.getLength(); i < n; i++) { - Attr attr = (Attr) attributes.item(i); - if (!RefactoringUtil.isManifestClassAttribute(attr)) { - continue; - } - - String value = attr.getValue(); - if (value.equals(mOldFqcn)) { - int start = RefactoringUtil.getAttributeValueRangeStart(attr, document); - if (start != -1) { - int end = start + mOldFqcn.length(); - edits.add(new ReplaceEdit(start, end - start, mNewFqcn)); - } - } else if (value.startsWith(".")) { //$NON-NLS-1$ - String fqcn = mAppPackage + value; - if (fqcn.equals(mOldFqcn)) { - int start = RefactoringUtil.getAttributeValueRangeStart(attr, document); - if (start != -1) { - int end = start + value.length(); - edits.add(new ReplaceEdit(start, end - start, mNewFqcn)); - } - } - } - } - - NodeList children = element.getChildNodes(); - for (int i = 0, n = children.getLength(); i < n; i++) { - Node child = children.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - addManifestReplacements(edits, (Element) child, document); - } - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipant.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipant.java deleted file mode 100644 index 7843ab3b4..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipant.java +++ /dev/null @@ -1,529 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.internal.refactorings.core; - -import static com.android.SdkConstants.ANDROID_MANIFEST_XML; -import static com.android.SdkConstants.ANDROID_URI; -import static com.android.SdkConstants.ATTR_CLASS; -import static com.android.SdkConstants.ATTR_CONTEXT; -import static com.android.SdkConstants.ATTR_NAME; -import static com.android.SdkConstants.CLASS_VIEW; -import static com.android.SdkConstants.DOT_XML; -import static com.android.SdkConstants.EXT_XML; -import static com.android.SdkConstants.R_CLASS; -import static com.android.SdkConstants.TOOLS_URI; -import static com.android.SdkConstants.VIEW_FRAGMENT; -import static com.android.SdkConstants.VIEW_TAG; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.ide.common.xml.ManifestData; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities; -import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo; -import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper; -import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; -import com.android.ide.eclipse.adt.internal.sdk.ProjectState; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.resources.ResourceFolderType; -import com.android.resources.ResourceType; -import com.android.utils.SdkUtils; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.OperationCanceledException; -import org.eclipse.jdt.core.IField; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.ITypeHierarchy; -import org.eclipse.jdt.internal.corext.refactoring.rename.RenameCompilationUnitProcessor; -import org.eclipse.jdt.internal.corext.refactoring.rename.RenameTypeProcessor; -import org.eclipse.ltk.core.refactoring.Change; -import org.eclipse.ltk.core.refactoring.CompositeChange; -import org.eclipse.ltk.core.refactoring.RefactoringStatus; -import org.eclipse.ltk.core.refactoring.TextFileChange; -import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; -import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor; -import org.eclipse.ltk.core.refactoring.participants.RenameParticipant; -import org.eclipse.ltk.core.refactoring.participants.RenameRefactoring; -import org.eclipse.text.edits.MultiTextEdit; -import org.eclipse.text.edits.ReplaceEdit; -import org.eclipse.text.edits.TextEdit; -import org.eclipse.wst.sse.core.StructuredModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * A participant to participate in refactorings that rename a type in an Android project. - * The class updates android manifest and the layout file - * The user can suppress refactoring by disabling the "Update references" checkbox. - * <p> - * Rename participants are registered via the extension point <code> - * org.eclipse.ltk.core.refactoring.renameParticipants</code>. - * Extensions to this extension point must therefore extend - * <code>org.eclipse.ltk.core.refactoring.participants.RenameParticipant</code>. - */ -@SuppressWarnings("restriction") -public class AndroidTypeRenameParticipant extends RenameParticipant { - private IProject mProject; - private IFile mManifestFile; - private String mOldFqcn; - private String mNewFqcn; - private String mOldSimpleName; - private String mNewSimpleName; - private String mOldDottedName; - private String mNewDottedName; - private boolean mIsCustomView; - - /** - * Set while we are creating an embedded Java refactoring. This could cause a recursive - * invocation of the XML renaming refactoring to react to the field, so this is flag - * during the call to the Java processor, and is used to ignore requests for adding in - * field reactions during that time. - */ - private static boolean sIgnore; - - @Override - public String getName() { - return "Android Type Rename"; - } - - @Override - public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) - throws OperationCanceledException { - return new RefactoringStatus(); - } - - @Override - protected boolean initialize(Object element) { - if (sIgnore) { - return false; - } - - if (element instanceof IType) { - IType type = (IType) element; - IJavaProject javaProject = (IJavaProject) type.getAncestor(IJavaElement.JAVA_PROJECT); - mProject = javaProject.getProject(); - IResource manifestResource = mProject.findMember(AdtConstants.WS_SEP - + SdkConstants.FN_ANDROID_MANIFEST_XML); - - if (manifestResource == null || !manifestResource.exists() - || !(manifestResource instanceof IFile)) { - RefactoringUtil.logInfo( - String.format("Invalid or missing file %1$s in project %2$s", - SdkConstants.FN_ANDROID_MANIFEST_XML, - mProject.getName())); - return false; - } - - try { - IType classView = javaProject.findType(CLASS_VIEW); - if (classView != null) { - ITypeHierarchy hierarchy = type.newSupertypeHierarchy(new NullProgressMonitor()); - if (hierarchy.contains(classView)) { - mIsCustomView = true; - } - } - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - - mManifestFile = (IFile) manifestResource; - ManifestData manifestData; - manifestData = AndroidManifestHelper.parseForData(mManifestFile); - if (manifestData == null) { - return false; - } - mOldSimpleName = type.getElementName(); - mOldDottedName = '.' + mOldSimpleName; - mOldFqcn = type.getFullyQualifiedName(); - String packageName = type.getPackageFragment().getElementName(); - mNewSimpleName = getArguments().getNewName(); - mNewDottedName = '.' + mNewSimpleName; - if (packageName != null) { - mNewFqcn = packageName + mNewDottedName; - } else { - mNewFqcn = mNewSimpleName; - } - if (mOldFqcn == null || mNewFqcn == null) { - return false; - } - if (!RefactoringUtil.isRefactorAppPackage() && mNewFqcn.indexOf('.') == -1) { - mNewFqcn = packageName + mNewDottedName; - } - return true; - } - return false; - } - - @Override - public Change createChange(IProgressMonitor pm) throws CoreException, - OperationCanceledException { - if (pm.isCanceled()) { - return null; - } - - // Only propose this refactoring if the "Update References" checkbox is set. - if (!getArguments().getUpdateReferences()) { - return null; - } - - RefactoringProcessor p = getProcessor(); - if (p instanceof RenameCompilationUnitProcessor) { - RenameTypeProcessor rtp = - ((RenameCompilationUnitProcessor) p).getRenameTypeProcessor(); - if (rtp != null) { - String pattern = rtp.getFilePatterns(); - boolean updQualf = rtp.getUpdateQualifiedNames(); - if (updQualf && pattern != null && pattern.contains("xml")) { //$NON-NLS-1$ - // Do not propose this refactoring if the - // "Update fully qualified names in non-Java files" option is - // checked and the file patterns mention XML. [c.f. SDK bug 21589] - return null; - } - } - } - - CompositeChange result = new CompositeChange(getName()); - - // Only show the children in the refactoring preview dialog - result.markAsSynthetic(); - - addManifestFileChanges(mManifestFile, result); - addLayoutFileChanges(mProject, result); - addJavaChanges(mProject, result, pm); - - // Also update in dependent projects - // TODO: Also do the Java elements, if they are in Jar files, since the library - // projects do this (and the JDT refactoring does not include them) - ProjectState projectState = Sdk.getProjectState(mProject); - if (projectState != null) { - Collection<ProjectState> parentProjects = projectState.getFullParentProjects(); - for (ProjectState parentProject : parentProjects) { - IProject project = parentProject.getProject(); - IResource manifestResource = project.findMember(AdtConstants.WS_SEP - + SdkConstants.FN_ANDROID_MANIFEST_XML); - if (manifestResource != null && manifestResource.exists() - && manifestResource instanceof IFile) { - addManifestFileChanges((IFile) manifestResource, result); - } - addLayoutFileChanges(project, result); - addJavaChanges(project, result, pm); - } - } - - // Look for the field change on the R.java class; it's a derived file - // and will generate file modified manually warnings. Disable it. - RenameResourceParticipant.disableRClassChanges(result); - - return (result.getChildren().length == 0) ? null : result; - } - - private void addJavaChanges(IProject project, CompositeChange result, IProgressMonitor monitor) { - if (!mIsCustomView) { - return; - } - - // Also rename styleables, if any - try { - // Find R class - IJavaProject javaProject = BaseProjectHelper.getJavaProject(project); - ManifestInfo info = ManifestInfo.get(project); - info.getPackage(); - String rFqcn = info.getPackage() + '.' + R_CLASS; - IType styleable = javaProject.findType(rFqcn + '.' + ResourceType.STYLEABLE.getName()); - if (styleable != null) { - IField[] fields = styleable.getFields(); - CompositeChange fieldChanges = null; - for (IField field : fields) { - String name = field.getElementName(); - if (name.equals(mOldSimpleName) || name.startsWith(mOldSimpleName) - && name.length() > mOldSimpleName.length() - && name.charAt(mOldSimpleName.length()) == '_') { - // Rename styleable fields - String newName = name.equals(mOldSimpleName) ? mNewSimpleName : - mNewSimpleName + name.substring(mOldSimpleName.length()); - RenameRefactoring refactoring = - RenameResourceParticipant.createFieldRefactoring(field, - newName, true); - - try { - sIgnore = true; - RefactoringStatus status = refactoring.checkAllConditions(monitor); - if (status != null && !status.hasError()) { - Change fieldChange = refactoring.createChange(monitor); - if (fieldChange != null) { - if (fieldChanges == null) { - fieldChanges = new CompositeChange( - "Update custom view styleable fields"); - // Disable these changes. They sometimes end up - // editing the wrong offsets. It looks like Eclipse - // doesn't ensure that after applying each change it - // also adjusts the other field offsets. I poked around - // and couldn't find a way to do this properly, but - // at least by listing the diffs here it shows what should - // be done. - fieldChanges.setEnabled(false); - } - // Disable change: see comment above. - fieldChange.setEnabled(false); - fieldChanges.add(fieldChange); - } - } - } catch (CoreException e) { - AdtPlugin.log(e, null); - } finally { - sIgnore = false; - } - } - } - if (fieldChanges != null) { - result.add(fieldChanges); - } - } - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - } - - private void addManifestFileChanges(IFile manifestFile, CompositeChange result) { - addXmlFileChanges(manifestFile, result, null); - } - - private void addLayoutFileChanges(IProject project, CompositeChange result) { - try { - // Update references in XML resource files - IFolder resFolder = project.getFolder(SdkConstants.FD_RESOURCES); - - IResource[] folders = resFolder.members(); - for (IResource folder : folders) { - String folderName = folder.getName(); - ResourceFolderType folderType = ResourceFolderType.getFolderType(folderName); - if (folderType != ResourceFolderType.LAYOUT && - folderType != ResourceFolderType.VALUES) { - continue; - } - if (!(folder instanceof IFolder)) { - continue; - } - IResource[] files = ((IFolder) folder).members(); - for (int i = 0; i < files.length; i++) { - IResource member = files[i]; - if ((member instanceof IFile) && member.exists()) { - IFile file = (IFile) member; - String fileName = member.getName(); - - if (SdkUtils.endsWith(fileName, DOT_XML)) { - addXmlFileChanges(file, result, folderType); - } - } - } - } - } catch (CoreException e) { - RefactoringUtil.log(e); - } - } - - private boolean addXmlFileChanges(IFile file, CompositeChange changes, - ResourceFolderType folderType) { - IModelManager modelManager = StructuredModelManager.getModelManager(); - IStructuredModel model = null; - try { - model = modelManager.getExistingModelForRead(file); - if (model == null) { - model = modelManager.getModelForRead(file); - } - if (model != null) { - IStructuredDocument document = model.getStructuredDocument(); - if (model instanceof IDOMModel) { - IDOMModel domModel = (IDOMModel) model; - Element root = domModel.getDocument().getDocumentElement(); - if (root != null) { - List<TextEdit> edits = new ArrayList<TextEdit>(); - if (folderType == null) { - assert file.getName().equals(ANDROID_MANIFEST_XML); - addManifestReplacements(edits, root, document); - } else if (folderType == ResourceFolderType.VALUES) { - addValueReplacements(edits, root, document); - } else { - assert folderType == ResourceFolderType.LAYOUT; - addLayoutReplacements(edits, root, document); - } - if (!edits.isEmpty()) { - MultiTextEdit rootEdit = new MultiTextEdit(); - rootEdit.addChildren(edits.toArray(new TextEdit[edits.size()])); - TextFileChange change = new TextFileChange(file.getName(), file); - change.setTextType(EXT_XML); - change.setEdit(rootEdit); - changes.add(change); - } - } - } else { - return false; - } - } - - return true; - } catch (IOException e) { - AdtPlugin.log(e, null); - } catch (CoreException e) { - AdtPlugin.log(e, null); - } finally { - if (model != null) { - model.releaseFromRead(); - } - } - - return false; - } - - private void addLayoutReplacements( - @NonNull List<TextEdit> edits, - @NonNull Element element, - @NonNull IStructuredDocument document) { - String tag = element.getTagName(); - if (tag.equals(mOldFqcn)) { - int start = RefactoringUtil.getTagNameRangeStart(element, document); - if (start != -1) { - int end = start + mOldFqcn.length(); - edits.add(new ReplaceEdit(start, end - start, mNewFqcn)); - } - } else if (tag.equals(VIEW_TAG)) { - // TODO: Handle inner classes ($ vs .) ? - Attr classNode = element.getAttributeNode(ATTR_CLASS); - if (classNode != null && classNode.getValue().equals(mOldFqcn)) { - int start = RefactoringUtil.getAttributeValueRangeStart(classNode, document); - if (start != -1) { - int end = start + mOldFqcn.length(); - edits.add(new ReplaceEdit(start, end - start, mNewFqcn)); - } - } - } else if (tag.equals(VIEW_FRAGMENT)) { - Attr classNode = element.getAttributeNode(ATTR_CLASS); - if (classNode == null) { - classNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME); - } - if (classNode != null && classNode.getValue().equals(mOldFqcn)) { - int start = RefactoringUtil.getAttributeValueRangeStart(classNode, document); - if (start != -1) { - int end = start + mOldFqcn.length(); - edits.add(new ReplaceEdit(start, end - start, mNewFqcn)); - } - } - } else if (element.hasAttributeNS(TOOLS_URI, ATTR_CONTEXT)) { - Attr classNode = element.getAttributeNodeNS(TOOLS_URI, ATTR_CONTEXT); - if (classNode != null && classNode.getValue().equals(mOldFqcn)) { - int start = RefactoringUtil.getAttributeValueRangeStart(classNode, document); - if (start != -1) { - int end = start + mOldFqcn.length(); - edits.add(new ReplaceEdit(start, end - start, mNewFqcn)); - } - } else if (classNode != null && classNode.getValue().equals(mOldDottedName)) { - int start = RefactoringUtil.getAttributeValueRangeStart(classNode, document); - if (start != -1) { - int end = start + mOldDottedName.length(); - edits.add(new ReplaceEdit(start, end - start, mNewDottedName)); - } - } - } - - NodeList children = element.getChildNodes(); - for (int i = 0, n = children.getLength(); i < n; i++) { - Node child = children.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - addLayoutReplacements(edits, (Element) child, document); - } - } - } - - private void addValueReplacements( - @NonNull List<TextEdit> edits, - @NonNull Element root, - @NonNull IStructuredDocument document) { - // Look for styleable renames for custom views - String declareStyleable = ResourceType.DECLARE_STYLEABLE.getName(); - List<Element> topLevel = DomUtilities.getChildren(root); - for (Element element : topLevel) { - String tag = element.getTagName(); - if (declareStyleable.equals(tag)) { - Attr nameNode = element.getAttributeNode(ATTR_NAME); - if (nameNode != null && mOldSimpleName.equals(nameNode.getValue())) { - int start = RefactoringUtil.getAttributeValueRangeStart(nameNode, document); - if (start != -1) { - int end = start + mOldSimpleName.length(); - edits.add(new ReplaceEdit(start, end - start, mNewSimpleName)); - } - } - } - } - } - - private void addManifestReplacements( - @NonNull List<TextEdit> edits, - @NonNull Element element, - @NonNull IStructuredDocument document) { - NamedNodeMap attributes = element.getAttributes(); - for (int i = 0, n = attributes.getLength(); i < n; i++) { - Attr attr = (Attr) attributes.item(i); - if (!RefactoringUtil.isManifestClassAttribute(attr)) { - continue; - } - - String value = attr.getValue(); - if (value.equals(mOldFqcn)) { - int start = RefactoringUtil.getAttributeValueRangeStart(attr, document); - if (start != -1) { - int end = start + mOldFqcn.length(); - edits.add(new ReplaceEdit(start, end - start, mNewFqcn)); - } - } else if (value.equals(mOldDottedName)) { - int start = RefactoringUtil.getAttributeValueRangeStart(attr, document); - if (start != -1) { - int end = start + mOldDottedName.length(); - edits.add(new ReplaceEdit(start, end - start, mNewDottedName)); - } - } - } - - NodeList children = element.getChildNodes(); - for (int i = 0, n = children.getLength(); i < n; i++) { - Node child = children.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - addManifestReplacements(edits, (Element) child, document); - } - } - } -}
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/FixImportsJob.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/FixImportsJob.java deleted file mode 100644 index 552e6a845..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/FixImportsJob.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.internal.refactorings.core; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IncrementalProjectBuilder; -import org.eclipse.core.resources.WorkspaceJob; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IPackageFragment; -import org.eclipse.jdt.core.ISourceRange; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.search.TypeNameMatch; -import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; -import org.eclipse.jdt.internal.corext.codemanipulation.OrganizeImportsOperation; -import org.eclipse.jdt.internal.corext.codemanipulation.OrganizeImportsOperation.IChooseImportQuery; -import org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter; -import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; -import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings; -import org.eclipse.jdt.ui.SharedASTProvider; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.progress.IProgressService; - -/** - * The helper class which fixes the import errors after refactoring - * - */ -@SuppressWarnings("restriction") -public class FixImportsJob extends WorkspaceJob { - - private IFile mAndroidManifest; - - private String mJavaPackage; - - /** - * Creates a new <code>FixImportsJob</code> - * - * @param name the job name - * @param androidManifest the android manifest file - * @param javaPackage the android java package - */ - public FixImportsJob(String name, IFile androidManifest, String javaPackage) { - super(name); - this.mAndroidManifest = androidManifest; - this.mJavaPackage = javaPackage; - } - - @Override - public IStatus runInWorkspace(final IProgressMonitor monitor) throws CoreException { - if (mJavaPackage == null || mAndroidManifest == null || !mAndroidManifest.exists()) { - return Status.CANCEL_STATUS; - } - IProject project = mAndroidManifest.getProject(); - IJavaProject javaProject = JavaCore.create(project); - if (javaProject == null || !javaProject.isOpen()) { - return Status.CANCEL_STATUS; - } - - project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor); - - IMarker[] markers = project.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); - for (int i = 0; i < markers.length; i++) { - IMarker marker = markers[i]; - IResource resource = marker.getResource(); - try { - IJavaElement element = JavaCore.create(resource); - if (element != null && (element instanceof ICompilationUnit)) { - final ICompilationUnit cu = (ICompilationUnit) element; - IPackageFragment packageFragment = (IPackageFragment) cu - .getAncestor(IJavaElement.PACKAGE_FRAGMENT); - if (packageFragment != null && packageFragment.exists()) { - String packageName = packageFragment.getElementName(); - if (packageName != null && packageName.startsWith(mJavaPackage)) { - CompilationUnit astRoot = SharedASTProvider.getAST(cu, - SharedASTProvider.WAIT_ACTIVE_ONLY, null); - CodeGenerationSettings settings = JavaPreferencesSettings - .getCodeGenerationSettings(cu.getJavaProject()); - final boolean hasAmbiguity[] = new boolean[] { - false - }; - IChooseImportQuery query = new IChooseImportQuery() { - @Override - public TypeNameMatch[] chooseImports(TypeNameMatch[][] openChoices, - ISourceRange[] ranges) { - hasAmbiguity[0] = true; - return new TypeNameMatch[0]; - } - }; - final OrganizeImportsOperation op = new OrganizeImportsOperation(cu, - astRoot, settings.importIgnoreLowercase, !cu.isWorkingCopy(), - true, query); - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - try { - IProgressService progressService = PlatformUI - .getWorkbench().getProgressService(); - progressService.run( - true, - true, - new WorkbenchRunnableAdapter(op, op - .getScheduleRule())); - IEditorPart openEditor = EditorUtility.isOpenInEditor(cu); - if (openEditor != null) { - openEditor.doSave(monitor); - } - } catch (Throwable e) { - RefactoringUtil.log(e); - } - } - }); - - } - } - } - } catch (Throwable e) { - RefactoringUtil.log(e); - } - } - return Status.OK_STATUS; - } -}
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringUtil.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringUtil.java deleted file mode 100644 index 04ebcfa26..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringUtil.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.internal.refactorings.core; - -import static com.android.SdkConstants.ANDROID_URI; -import static com.android.SdkConstants.ATTR_NAME; -import static com.android.xml.AndroidManifest.ATTRIBUTE_BACKUP_AGENT; -import static com.android.xml.AndroidManifest.ATTRIBUTE_MANAGE_SPACE_ACTIVITY; -import static com.android.xml.AndroidManifest.ATTRIBUTE_PARENT_ACTIVITY_NAME; -import static com.android.xml.AndroidManifest.ATTRIBUTE_TARGET_ACTIVITY; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.xml.AndroidManifest; - -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.IDocument; -import org.eclipse.wst.sse.core.StructuredModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; - -/** - * The utility class for android refactoring - * - */ -@SuppressWarnings("restriction") -public class RefactoringUtil { - - private static boolean sRefactorAppPackage = false; - - /** - * Releases SSE read model; saves SSE model if exists edit model - * Called in dispose method of refactoring change classes - * - * @param model the SSE model - * @param document the document - */ - public static void fixModel(IStructuredModel model, IDocument document) { - if (model != null) { - model.releaseFromRead(); - } - model = null; - if (document == null) { - return; - } - try { - model = StructuredModelManager.getModelManager().getExistingModelForEdit(document); - if (model != null) { - model.save(); - } - } catch (UnsupportedEncodingException e1) { - // ignore - } catch (IOException e1) { - // ignore - } catch (CoreException e1) { - // ignore - } finally { - if (model != null) { - model.releaseFromEdit(); - } - } - } - - /** - * Logs the info message - * - * @param message the message - */ - public static void logInfo(String message) { - AdtPlugin.log(IStatus.INFO, AdtPlugin.PLUGIN_ID, message); - } - - /** - * Logs the the exception - * - * @param e the exception - */ - public static void log(Throwable e) { - AdtPlugin.log(e, e.getMessage()); - } - - /** - * @return true if Rename/Move package needs to change the application package - * default is false - * - */ - public static boolean isRefactorAppPackage() { - return sRefactorAppPackage; - } - - /** - * @param refactorAppPackage true if Rename/Move package needs to change the application package - */ - public static void setRefactorAppPackage(boolean refactorAppPackage) { - RefactoringUtil.sRefactorAppPackage = refactorAppPackage; - } - - /** - * Returns the range of the attribute value in the given document - * - * @param attr the attribute to look up - * @param document the document containing the attribute - * @return the range of the value text, not including quotes, in the document - */ - public static int getAttributeValueRangeStart( - @NonNull Attr attr, - @NonNull IDocument document) { - IndexedRegion region = (IndexedRegion) attr; - int potentialStart = attr.getName().length() + 2; // + 2: add =" - String text; - try { - text = document.get(region.getStartOffset(), - region.getEndOffset() - region.getStartOffset()); - } catch (BadLocationException e) { - return -1; - } - String value = attr.getValue(); - int index = text.indexOf(value, potentialStart); - if (index != -1) { - return region.getStartOffset() + index; - } else { - return -1; - } - } - - /** - * Returns the start of the tag name of the given element - * - * @param element the element to look up - * @param document the document containing the attribute - * @return the index of the start tag in the document - */ - public static int getTagNameRangeStart( - @NonNull Element element, - @NonNull IDocument document) { - IndexedRegion region = (IndexedRegion) element; - int potentialStart = 1; // add '<' - String text; - try { - text = document.get(region.getStartOffset(), - region.getEndOffset() - region.getStartOffset()); - } catch (BadLocationException e) { - return -1; - } - int index = text.indexOf(element.getTagName(), potentialStart); - if (index != -1) { - return region.getStartOffset() + index; - } else { - return -1; - } - } - - /** - * Returns whether the given manifest attribute should be considered to describe - * a class name. These will be eligible for refactoring when classes are renamed - * or moved. - * - * @param attribute the manifest attribute - * @return true if this attribute can describe a class - */ - public static boolean isManifestClassAttribute(@NonNull Attr attribute) { - return isManifestClassAttribute( - attribute.getOwnerElement().getTagName(), - attribute.getNamespaceURI(), - attribute.getLocalName()); - } - - /** - * Returns whether the given manifest attribute should be considered to describe - * a class name. These will be eligible for refactoring when classes are renamed - * or moved. - * - * @param tag the tag, if known - * @param uri the attribute namespace, if any - * @param name the attribute local name, if any - * @return true if this attribute can describe a class - */ - public static boolean isManifestClassAttribute( - @Nullable String tag, - @Nullable String uri, - @Nullable String name) { - if (name == null) { - return false; - } - - if ((name.equals(ATTR_NAME) - && (AndroidManifest.NODE_ACTIVITY.equals(tag) - || AndroidManifest.NODE_APPLICATION.equals(tag) - || AndroidManifest.NODE_INSTRUMENTATION.equals(tag) - || AndroidManifest.NODE_PROVIDER.equals(tag) - || AndroidManifest.NODE_SERVICE.equals(tag) - || AndroidManifest.NODE_RECEIVER.equals(tag))) - || name.equals(ATTRIBUTE_TARGET_ACTIVITY) - || name.equals(ATTRIBUTE_MANAGE_SPACE_ACTIVITY) - || name.equals(ATTRIBUTE_BACKUP_AGENT) - || name.equals(ATTRIBUTE_PARENT_ACTIVITY_NAME)) { - return ANDROID_URI.equals(uri); - } - - return false; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourcePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourcePage.java deleted file mode 100644 index 6779fd322..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourcePage.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.ide.eclipse.adt.internal.refactorings.core; - -import static com.android.SdkConstants.PREFIX_RESOURCE_REF; -import static com.android.SdkConstants.R_CLASS; - -import com.android.ide.eclipse.adt.internal.resources.ResourceNameValidator; -import com.android.resources.ResourceType; - -import org.eclipse.jdt.internal.ui.refactoring.TextInputWizardPage; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.ltk.core.refactoring.RefactoringStatus; -import org.eclipse.ltk.core.refactoring.participants.RenameRefactoring; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -import java.util.Set; - -@SuppressWarnings("restriction") // JDT refactoring UI -class RenameResourcePage extends TextInputWizardPage implements SelectionListener { - private Label mXmlLabel; - private Label mJavaLabel; - private Button mUpdateReferences; - private boolean mCanClear; - private ResourceType mType; - private ResourceNameValidator mValidator; - - /** - * Create the wizard. - * @param type the type of the resource to be renamed - * @param initial initial renamed value - * @param canClear whether the dialog should allow clearing the field - */ - public RenameResourcePage(ResourceType type, String initial, boolean canClear) { - super(type.getName(), true, initial); - mType = type; - mCanClear = canClear; - - mValidator = ResourceNameValidator.create(false /*allowXmlExtension*/, - (Set<String>) null, mType); - } - - @SuppressWarnings("unused") // SWT constructors aren't really unused, they have side effects - @Override - public void createControl(Composite parent) { - Composite container = new Composite(parent, SWT.NULL); - setControl(container); - initializeDialogUnits(container); - container.setLayout(new GridLayout(2, false)); - Label nameLabel = new Label(container, SWT.NONE); - nameLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); - nameLabel.setText("New Name:"); - Text text = super.createTextInputField(container); - text.selectAll(); - text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); - Label xmlLabel = new Label(container, SWT.NONE); - xmlLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); - xmlLabel.setText("XML:"); - mXmlLabel = new Label(container, SWT.NONE); - mXmlLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); - Label javaLabel = new Label(container, SWT.NONE); - javaLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); - javaLabel.setText("Java:"); - mJavaLabel = new Label(container, SWT.NONE); - mJavaLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); - new Label(container, SWT.NONE); - new Label(container, SWT.NONE); - mUpdateReferences = new Button(container, SWT.CHECK); - mUpdateReferences.setSelection(true); - mUpdateReferences.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1)); - mUpdateReferences.setText("Update References"); - mUpdateReferences.addSelectionListener(this); - - Dialog.applyDialogFont(container); - } - - @Override - public void setVisible(boolean visible) { - if (visible) { - RenameResourceProcessor processor = getProcessor(); - String newName = processor.getNewName(); - if (newName != null && newName.length() > 0 - && !newName.equals(getInitialValue())) { - Text textField = getTextField(); - textField.setText(newName); - textField.setSelection(0, newName.length()); - } - } - - super.setVisible(visible); - } - - @Override - protected RefactoringStatus validateTextField(String newName) { - if (newName.isEmpty() && isEmptyInputValid()) { - getProcessor().setNewName(""); - return RefactoringStatus.createWarningStatus( - "The resource definition will be deleted"); - } - - String error = mValidator.isValid(newName); - if (error != null) { - return RefactoringStatus.createErrorStatus(error); - } - - RenameResourceProcessor processor = getProcessor(); - processor.setNewName(newName); - return processor.checkNewName(newName); - } - - private RenameResourceProcessor getProcessor() { - RenameRefactoring refactoring = (RenameRefactoring) getRefactoring(); - return (RenameResourceProcessor) refactoring.getProcessor(); - } - - @Override - protected boolean isEmptyInputValid() { - return mCanClear; - } - - @Override - protected boolean isInitialInputValid() { - RenameResourceProcessor processor = getProcessor(); - return processor.getNewName() != null - && !processor.getNewName().equals(processor.getCurrentName()); - } - - @Override - protected void textModified(String text) { - super.textModified(text); - if (mXmlLabel != null && mJavaLabel != null) { - String xml = PREFIX_RESOURCE_REF + mType.getName() + '/' + text; - String java = R_CLASS + '.' + mType.getName() + '.' + text; - if (text.isEmpty()) { - xml = java = ""; - } - mXmlLabel.setText(xml); - mJavaLabel.setText(java); - } - } - - // ---- Implements SelectionListener ---- - - @Override - public void widgetSelected(SelectionEvent e) { - if (e.getSource() == mUpdateReferences) { - RenameResourceProcessor processor = getProcessor(); - boolean update = mUpdateReferences.getSelection(); - processor.setUpdateReferences(update); - } - } - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipant.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipant.java deleted file mode 100644 index 438e82223..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipant.java +++ /dev/null @@ -1,752 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.internal.refactorings.core; - -import static com.android.SdkConstants.ANDROID_PREFIX; -import static com.android.SdkConstants.ANDROID_URI; -import static com.android.SdkConstants.ATTR_ID; -import static com.android.SdkConstants.ATTR_NAME; -import static com.android.SdkConstants.ATTR_TYPE; -import static com.android.SdkConstants.DOT_XML; -import static com.android.SdkConstants.EXT_XML; -import static com.android.SdkConstants.FD_RES; -import static com.android.SdkConstants.FN_RESOURCE_CLASS; -import static com.android.SdkConstants.NEW_ID_PREFIX; -import static com.android.SdkConstants.PREFIX_RESOURCE_REF; -import static com.android.SdkConstants.PREFIX_THEME_REF; -import static com.android.SdkConstants.R_CLASS; -import static com.android.SdkConstants.TAG_ITEM; -import static com.android.SdkConstants.TOOLS_URI; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.AdtUtils; -import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo; -import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; -import com.android.ide.eclipse.adt.internal.resources.ResourceNameValidator; -import com.android.ide.eclipse.adt.internal.sdk.ProjectState; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.resources.ResourceFolderType; -import com.android.resources.ResourceType; -import com.android.utils.SdkUtils; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.OperationCanceledException; -import org.eclipse.jdt.core.IField; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.internal.corext.refactoring.rename.RenameFieldProcessor; -import org.eclipse.ltk.core.refactoring.Change; -import org.eclipse.ltk.core.refactoring.CompositeChange; -import org.eclipse.ltk.core.refactoring.RefactoringStatus; -import org.eclipse.ltk.core.refactoring.TextChange; -import org.eclipse.ltk.core.refactoring.TextFileChange; -import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; -import org.eclipse.ltk.core.refactoring.participants.RenameParticipant; -import org.eclipse.ltk.core.refactoring.participants.RenameRefactoring; -import org.eclipse.ltk.core.refactoring.resource.RenameResourceChange; -import org.eclipse.text.edits.MultiTextEdit; -import org.eclipse.text.edits.ReplaceEdit; -import org.eclipse.text.edits.TextEdit; -import org.eclipse.wst.sse.core.StructuredModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * A rename participant handling renames of resources (such as R.id.foo and R.layout.bar). - * This reacts to refactorings of fields in the R inner classes (such as R.id), and updates - * the XML files as appropriate; renaming .xml files, updating XML attributes, resource - * references in style declarations, and so on. - */ -@SuppressWarnings("restriction") // WTP API -public class RenameResourceParticipant extends RenameParticipant { - /** The project we're refactoring in */ - private @NonNull IProject mProject; - - /** The type of the resource we're refactoring, such as {@link ResourceType#ID} */ - private @NonNull ResourceType mType; - /** - * The type of the resource folder we're refactoring in, such as - * {@link ResourceFolderType#VALUES}. When refactoring non value files, we need to - * rename the files as well. - */ - private @NonNull ResourceFolderType mFolderType; - - /** The previous name of the resource */ - private @NonNull String mOldName; - - /** The new name of the resource */ - private @NonNull String mNewName; - - /** Whether references to the resource should be updated */ - private boolean mUpdateReferences; - - /** A match pattern to look for in XML, such as {@code @attr/foo} */ - private @NonNull String mXmlMatch1; - - /** A match pattern to look for in XML, such as {@code ?attr/foo} */ - private @Nullable String mXmlMatch2; - - /** A match pattern to look for in XML, such as {@code ?foo} */ - private @Nullable String mXmlMatch3; - - /** The value to replace a reference to {@link #mXmlMatch1} with, such as {@code @attr/bar} */ - private @NonNull String mXmlNewValue1; - - /** The value to replace a reference to {@link #mXmlMatch2} with, such as {@code ?attr/bar} */ - private @Nullable String mXmlNewValue2; - - /** The value to replace a reference to {@link #mXmlMatch3} with, such as {@code ?bar} */ - private @Nullable String mXmlNewValue3; - - /** - * If non null, this refactoring was initiated as a file rename of an XML file (and if - * null, we are just reacting to a Java field rename) - */ - private IFile mRenamedFile; - - /** - * If renaming a field, we need to create an embedded field refactoring to update the - * Java sources referring to the corresponding R class field. This is stored as an - * instance such that we can have it participate in both the condition check methods - * as well as the {@link #createChange(IProgressMonitor)} refactoring operation. - */ - private RenameRefactoring mFieldRefactoring; - - /** - * Set while we are creating an embedded Java refactoring. This could cause a recursive - * invocation of the XML renaming refactoring to react to the field, so this is flag - * during the call to the Java processor, and is used to ignore requests for adding in - * field reactions during that time. - */ - private static boolean sIgnore; - - /** - * Creates a new {@linkplain RenameResourceParticipant} - */ - public RenameResourceParticipant() { - } - - @Override - public String getName() { - return "Android Rename Field Participant"; - } - - @Override - protected boolean initialize(Object element) { - if (sIgnore) { - return false; - } - - if (element instanceof IField) { - IField field = (IField) element; - IType declaringType = field.getDeclaringType(); - if (declaringType != null) { - if (R_CLASS.equals(declaringType.getParent().getElementName())) { - String typeName = declaringType.getElementName(); - mType = ResourceType.getEnum(typeName); - if (mType != null) { - mUpdateReferences = getArguments().getUpdateReferences(); - mFolderType = AdtUtils.getFolderTypeFor(mType); - IJavaProject javaProject = (IJavaProject) field.getAncestor( - IJavaElement.JAVA_PROJECT); - mProject = javaProject.getProject(); - mOldName = field.getElementName(); - mNewName = getArguments().getNewName(); - mFieldRefactoring = null; - mRenamedFile = null; - createXmlSearchPatterns(); - return true; - } - } - } - - return false; - } else if (element instanceof IFile) { - IFile file = (IFile) element; - mProject = file.getProject(); - if (BaseProjectHelper.isAndroidProject(mProject)) { - IPath path = file.getFullPath(); - int segments = path.segmentCount(); - if (segments == 4 && path.segment(1).equals(FD_RES)) { - String parentName = file.getParent().getName(); - mFolderType = ResourceFolderType.getFolderType(parentName); - if (mFolderType != null && mFolderType != ResourceFolderType.VALUES) { - mType = AdtUtils.getResourceTypeFor(mFolderType); - if (mType != null) { - mUpdateReferences = getArguments().getUpdateReferences(); - mProject = file.getProject(); - mOldName = AdtUtils.stripAllExtensions(file.getName()); - mNewName = AdtUtils.stripAllExtensions(getArguments().getNewName()); - mRenamedFile = file; - createXmlSearchPatterns(); - - mFieldRefactoring = null; - IField field = getResourceField(mProject, mType, mOldName); - if (field != null) { - mFieldRefactoring = createFieldRefactoring(field); - } else { - // no corresponding field; aapt has not run yet. Perhaps user has - // turned off auto build. - mFieldRefactoring = null; - } - - return true; - } - } - } - } - } else if (element instanceof String) { - String uri = (String) element; - if (uri.startsWith(PREFIX_RESOURCE_REF) && !uri.startsWith(ANDROID_PREFIX)) { - RenameResourceProcessor processor = (RenameResourceProcessor) getProcessor(); - mProject = processor.getProject(); - mType = processor.getType(); - mFolderType = AdtUtils.getFolderTypeFor(mType); - mOldName = processor.getCurrentName(); - mNewName = processor.getNewName(); - assert uri.endsWith(mOldName) && uri.contains(mType.getName()) : uri; - mUpdateReferences = getArguments().getUpdateReferences(); - if (mNewName.isEmpty()) { - mUpdateReferences = false; - } - mRenamedFile = null; - createXmlSearchPatterns(); - mFieldRefactoring = null; - if (!mNewName.isEmpty()) { - IField field = getResourceField(mProject, mType, mOldName); - if (field != null) { - mFieldRefactoring = createFieldRefactoring(field); - } - } - - return true; - } - } - - return false; - } - - /** Create nested Java refactoring which updates the R field references, if applicable */ - private RenameRefactoring createFieldRefactoring(IField field) { - return createFieldRefactoring(field, mNewName, mUpdateReferences); - } - - /** - * Create nested Java refactoring which updates the R field references, if - * applicable - * - * @param field the field to be refactored - * @param newName the new name - * @param updateReferences whether references should be updated - * @return a new rename refactoring - */ - public static RenameRefactoring createFieldRefactoring( - @NonNull IField field, - @NonNull String newName, - boolean updateReferences) { - RenameFieldProcessor processor = new RenameFieldProcessor(field); - processor.setRenameGetter(false); - processor.setRenameSetter(false); - RenameRefactoring refactoring = new RenameRefactoring(processor); - processor.setUpdateReferences(updateReferences); - processor.setUpdateTextualMatches(false); - processor.setNewElementName(newName); - try { - if (refactoring.isApplicable()) { - return refactoring; - } - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - - return null; - } - - private void createXmlSearchPatterns() { - // Set up search strings for the attribute iterator. This will - // identify string matches for mXmlMatch1, 2 and 3, and when matched, - // will add a replacement edit for mXmlNewValue1, 2, or 3. - mXmlMatch2 = null; - mXmlNewValue2 = null; - mXmlMatch3 = null; - mXmlNewValue3 = null; - - String typeName = mType.getName(); - if (mUpdateReferences) { - mXmlMatch1 = PREFIX_RESOURCE_REF + typeName + '/' + mOldName; - mXmlNewValue1 = PREFIX_RESOURCE_REF + typeName + '/' + mNewName; - if (mType == ResourceType.ID) { - mXmlMatch2 = NEW_ID_PREFIX + mOldName; - mXmlNewValue2 = NEW_ID_PREFIX + mNewName; - } else if (mType == ResourceType.ATTR) { - // When renaming @attr/foo, also edit ?attr/foo - mXmlMatch2 = PREFIX_THEME_REF + typeName + '/' + mOldName; - mXmlNewValue2 = PREFIX_THEME_REF + typeName + '/' + mNewName; - // as well as ?foo - mXmlMatch3 = PREFIX_THEME_REF + mOldName; - mXmlNewValue3 = PREFIX_THEME_REF + mNewName; - } - } else if (mType == ResourceType.ID) { - mXmlMatch1 = NEW_ID_PREFIX + mOldName; - mXmlNewValue1 = NEW_ID_PREFIX + mNewName; - } - } - - @Override - public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) - throws OperationCanceledException { - if (mRenamedFile != null && getArguments().getNewName().indexOf('.') == -1 - && mRenamedFile.getName().indexOf('.') != -1) { - return RefactoringStatus.createErrorStatus( - String.format("You must include the file extension (%1$s?)", - mRenamedFile.getName().substring(mRenamedFile.getName().indexOf('.')))); - } - - // Ensure that the new name is valid - if (mNewName != null && !mNewName.isEmpty()) { - ResourceNameValidator validator = ResourceNameValidator.create(false, mProject, mType); - String error = validator.isValid(mNewName); - if (error != null) { - return RefactoringStatus.createErrorStatus(error); - } - } - - if (mFieldRefactoring != null) { - try { - sIgnore = true; - return mFieldRefactoring.checkAllConditions(pm); - } catch (CoreException e) { - AdtPlugin.log(e, null); - } finally { - sIgnore = false; - } - } - - return new RefactoringStatus(); - } - - @Override - public Change createChange(IProgressMonitor monitor) throws CoreException, - OperationCanceledException { - if (monitor.isCanceled()) { - return null; - } - - CompositeChange result = new CompositeChange("Update resource references"); - - // Only show the children in the refactoring preview dialog - result.markAsSynthetic(); - - addResourceFileChanges(result, mProject, monitor); - - // If renaming resources in a library project, also offer to rename references - // in including projects - if (mUpdateReferences) { - ProjectState projectState = Sdk.getProjectState(mProject); - if (projectState != null && projectState.isLibrary()) { - List<ProjectState> parentProjects = projectState.getParentProjects(); - for (ProjectState state : parentProjects) { - IProject project = state.getProject(); - CompositeChange nested = new CompositeChange( - String.format("Update references in %1$s", project.getName())); - addResourceFileChanges(nested, project, monitor); - if (nested.getChildren().length > 0) { - result.add(nested); - } - } - } - } - - if (mFieldRefactoring != null) { - // We have to add in Java field refactoring - try { - sIgnore = true; - addJavaChanges(result, monitor); - } finally { - sIgnore = false; - } - } else { - // Disable field refactoring added by the default Java field rename handler - disableExistingResourceFileChange(); - } - - return (result.getChildren().length == 0) ? null : result; - } - - /** - * Adds all changes to resource files (typically XML but also renaming drawable files - * - * @param project the Android project - * @param className the layout classes - */ - private void addResourceFileChanges( - CompositeChange change, - IProject project, - IProgressMonitor monitor) - throws OperationCanceledException { - if (monitor.isCanceled()) { - return; - } - - try { - // Update resource references in the manifest - IFile manifest = project.getFile(SdkConstants.ANDROID_MANIFEST_XML); - if (manifest != null) { - addResourceXmlChanges(manifest, change, null); - } - - // Update references in XML resource files - IFolder resFolder = project.getFolder(SdkConstants.FD_RESOURCES); - - IResource[] folders = resFolder.members(); - for (IResource folder : folders) { - if (!(folder instanceof IFolder)) { - continue; - } - String folderName = folder.getName(); - ResourceFolderType folderType = ResourceFolderType.getFolderType(folderName); - IResource[] files = ((IFolder) folder).members(); - for (int i = 0; i < files.length; i++) { - IResource member = files[i]; - if ((member instanceof IFile) && member.exists()) { - IFile file = (IFile) member; - String fileName = member.getName(); - - if (SdkUtils.endsWith(fileName, DOT_XML)) { - addResourceXmlChanges(file, change, folderType); - } - - if ((mRenamedFile == null || !mRenamedFile.equals(file)) - && fileName.startsWith(mOldName) - && fileName.length() > mOldName.length() - && fileName.charAt(mOldName.length()) == '.' - && mFolderType != ResourceFolderType.VALUES - && mFolderType == folderType) { - // Rename this file - String newFile = mNewName + fileName.substring(mOldName.length()); - IPath path = file.getFullPath(); - change.add(new RenameResourceChange(path, newFile)); - } - } - } - } - } catch (CoreException e) { - RefactoringUtil.log(e); - } - } - - private void addJavaChanges(CompositeChange result, IProgressMonitor monitor) - throws CoreException, OperationCanceledException { - if (monitor.isCanceled()) { - return; - } - - RefactoringStatus status = mFieldRefactoring.checkAllConditions(monitor); - if (status != null && !status.hasError()) { - Change fieldChanges = mFieldRefactoring.createChange(monitor); - if (fieldChanges != null) { - result.add(fieldChanges); - - // Look for the field change on the R.java class; it's a derived file - // and will generate file modified manually warnings. Disable it. - disableRClassChanges(fieldChanges); - } - } - } - - private boolean addResourceXmlChanges( - IFile file, - CompositeChange changes, - ResourceFolderType folderType) { - IModelManager modelManager = StructuredModelManager.getModelManager(); - IStructuredModel model = null; - try { - model = modelManager.getExistingModelForRead(file); - if (model == null) { - model = modelManager.getModelForRead(file); - } - if (model != null) { - IStructuredDocument document = model.getStructuredDocument(); - if (model instanceof IDOMModel) { - IDOMModel domModel = (IDOMModel) model; - Element root = domModel.getDocument().getDocumentElement(); - if (root != null) { - List<TextEdit> edits = new ArrayList<TextEdit>(); - addReplacements(edits, root, document, folderType); - if (!edits.isEmpty()) { - MultiTextEdit rootEdit = new MultiTextEdit(); - rootEdit.addChildren(edits.toArray(new TextEdit[edits.size()])); - TextFileChange change = new TextFileChange(file.getName(), file); - change.setTextType(EXT_XML); - change.setEdit(rootEdit); - changes.add(change); - } - } - } else { - return false; - } - } - - return true; - } catch (IOException e) { - AdtPlugin.log(e, null); - } catch (CoreException e) { - AdtPlugin.log(e, null); - } finally { - if (model != null) { - model.releaseFromRead(); - } - } - - return false; - } - - private void addReplacements( - @NonNull List<TextEdit> edits, - @NonNull Element element, - @NonNull IStructuredDocument document, - @Nullable ResourceFolderType folderType) { - String tag = element.getTagName(); - if (folderType == ResourceFolderType.VALUES) { - // Look for - // <item name="main_layout" type="layout">...</item> - // <item name="myid" type="id"/> - // <string name="mystring">...</string> - // etc - if (tag.equals(mType.getName()) - || (tag.equals(TAG_ITEM) - && (mType == ResourceType.ID - || mType.getName().equals(element.getAttribute(ATTR_TYPE))))) { - Attr nameNode = element.getAttributeNode(ATTR_NAME); - if (nameNode != null && nameNode.getValue().equals(mOldName)) { - int start = RefactoringUtil.getAttributeValueRangeStart(nameNode, document); - if (start != -1) { - int end = start + mOldName.length(); - edits.add(new ReplaceEdit(start, end - start, mNewName)); - } - } - } - } - - NamedNodeMap attributes = element.getAttributes(); - for (int i = 0, n = attributes.getLength(); i < n; i++) { - Attr attr = (Attr) attributes.item(i); - String value = attr.getValue(); - - // If not updating references, only update XML matches that define the id - if (!mUpdateReferences && (!ATTR_ID.equals(attr.getLocalName()) || - !ANDROID_URI.equals(attr.getNamespaceURI()))) { - - if (TOOLS_URI.equals(attr.getNamespaceURI()) && value.equals(mXmlMatch1)) { - int start = RefactoringUtil.getAttributeValueRangeStart(attr, document); - if (start != -1) { - int end = start + mXmlMatch1.length(); - edits.add(new ReplaceEdit(start, end - start, mXmlNewValue1)); - } - } - - continue; - } - - // Replace XML attribute reference, such as - // android:id="@+id/oldName" => android:id="+id/newName" - - String match = null; - String matchedValue = null; - - if (value.equals(mXmlMatch1)) { - match = mXmlMatch1; - matchedValue = mXmlNewValue1; - } else if (value.equals(mXmlMatch2)) { - match = mXmlMatch2; - matchedValue = mXmlNewValue2; - } else if (value.equals(mXmlMatch3)) { - match = mXmlMatch3; - matchedValue = mXmlNewValue3; - } else { - continue; - } - - if (match != null) { - if (mNewName.isEmpty() && ATTR_ID.equals(attr.getLocalName()) && - ANDROID_URI.equals(attr.getNamespaceURI())) { - // Delete attribute - IndexedRegion region = (IndexedRegion) attr; - int start = region.getStartOffset(); - int end = region.getEndOffset(); - edits.add(new ReplaceEdit(start, end - start, "")); - } else { - int start = RefactoringUtil.getAttributeValueRangeStart(attr, document); - if (start != -1) { - int end = start + match.length(); - edits.add(new ReplaceEdit(start, end - start, matchedValue)); - } - } - } - } - - NodeList children = element.getChildNodes(); - for (int i = 0, n = children.getLength(); i < n; i++) { - Node child = children.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - addReplacements(edits, (Element) child, document, folderType); - } else if (child.getNodeType() == Node.TEXT_NODE && mUpdateReferences) { - // Replace XML text, such as @color/custom_theme_color in - // <item name="android:windowBackground">@color/custom_theme_color</item> - // - String text = child.getNodeValue(); - int index = getFirstNonBlankIndex(text); - if (index != -1) { - String match = null; - String matchedValue = null; - if (mXmlMatch1 != null - && text.startsWith(mXmlMatch1) && text.trim().equals(mXmlMatch1)) { - match = mXmlMatch1; - matchedValue = mXmlNewValue1; - } else if (mXmlMatch2 != null - && text.startsWith(mXmlMatch2) && text.trim().equals(mXmlMatch2)) { - match = mXmlMatch2; - matchedValue = mXmlNewValue2; - } else if (mXmlMatch3 != null - && text.startsWith(mXmlMatch3) && text.trim().equals(mXmlMatch3)) { - match = mXmlMatch3; - matchedValue = mXmlNewValue3; - } - if (match != null) { - IndexedRegion region = (IndexedRegion) child; - int start = region.getStartOffset() + index; - int end = start + match.length(); - edits.add(new ReplaceEdit(start, end - start, matchedValue)); - } - } - } - } - } - - /** - * Returns the index of the first non-space character in the string, or -1 - * if the string is empty or has only whitespace - * - * @param s the string to check - * @return the index of the first non whitespace character - */ - private int getFirstNonBlankIndex(String s) { - for (int i = 0, n = s.length(); i < n; i++) { - if (!Character.isWhitespace(s.charAt(i))) { - return i; - } - } - - return -1; - } - - /** - * Initiates a renaming of a resource item - * - * @param project the project containing the resource references - * @param type the type of resource - * @param name the name of the resource - * @return false if initiating the rename failed - */ - @Nullable - private static IField getResourceField( - @NonNull IProject project, - @NonNull ResourceType type, - @NonNull String name) { - try { - IJavaProject javaProject = BaseProjectHelper.getJavaProject(project); - if (javaProject == null) { - return null; - } - - String pkg = ManifestInfo.get(project).getPackage(); - // TODO: Rename in all libraries too? - IType t = javaProject.findType(pkg + '.' + R_CLASS + '.' + type.getName()); - if (t == null) { - return null; - } - - return t.getField(name); - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - - return null; - } - - /** - * Searches for existing changes in the refactoring which modifies the R - * field to rename it. it's derived so performing this change will generate - * a "generated code was modified manually" warning - */ - private void disableExistingResourceFileChange() { - IFolder genFolder = mProject.getFolder(SdkConstants.FD_GEN_SOURCES); - if (genFolder != null && genFolder.exists()) { - ManifestInfo manifestInfo = ManifestInfo.get(mProject); - String pkg = manifestInfo.getPackage(); - if (pkg != null) { - IFile rFile = genFolder.getFile(pkg.replace('.', '/') + '/' + FN_RESOURCE_CLASS); - TextChange change = getTextChange(rFile); - if (change != null) { - change.setEnabled(false); - } - } - } - } - - /** - * Searches for existing changes in the refactoring which modifies the R - * field to rename it. it's derived so performing this change will generate - * a "generated code was modified manually" warning - * - * @param change the change to disable R file changes in - */ - public static void disableRClassChanges(Change change) { - if (change.getName().equals(FN_RESOURCE_CLASS)) { - change.setEnabled(false); - } - // Look for the field change on the R.java class; it's a derived file - // and will generate file modified manually warnings. Disable it. - if (change instanceof CompositeChange) { - for (Change outer : ((CompositeChange) change).getChildren()) { - disableRClassChanges(outer); - } - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceProcessor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceProcessor.java deleted file mode 100644 index 5ea99411c..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceProcessor.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.ide.eclipse.adt.internal.refactorings.core; - -import static com.android.SdkConstants.PREFIX_RESOURCE_REF; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.internal.resources.ResourceNameValidator; -import com.android.resources.ResourceType; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.ltk.core.refactoring.Change; -import org.eclipse.ltk.core.refactoring.RefactoringStatus; -import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; -import org.eclipse.ltk.core.refactoring.participants.ParticipantManager; -import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant; -import org.eclipse.ltk.core.refactoring.participants.RenameArguments; -import org.eclipse.ltk.core.refactoring.participants.RenameProcessor; -import org.eclipse.ltk.core.refactoring.participants.SharableParticipants; - -/** - * A rename processor for Android resources. - */ -public class RenameResourceProcessor extends RenameProcessor { - private IProject mProject; - private ResourceType mType; - private String mCurrentName; - private String mNewName; - private boolean mUpdateReferences = true; - private ResourceNameValidator mValidator; - private RenameArguments mRenameArguments; - - /** - * Creates a new rename resource processor. - * - * @param project the project containing the renamed resource - * @param type the type of the resource - * @param currentName the current name of the resource - * @param newName the new name of the resource, or null if not known - */ - public RenameResourceProcessor( - @NonNull IProject project, - @NonNull ResourceType type, - @NonNull String currentName, - @Nullable String newName) { - mProject = project; - mType = type; - mCurrentName = currentName; - mNewName = newName != null ? newName : currentName; - mUpdateReferences= true; - mValidator = ResourceNameValidator.create(false, mProject, mType); - } - - /** - * Returns the project containing the renamed resource - * - * @return the project containing the renamed resource - */ - @NonNull - public IProject getProject() { - return mProject; - } - - /** - * Returns the new resource name - * - * @return the new resource name - */ - @NonNull - public String getNewName() { - return mNewName; - } - - /** - * Returns the current name of the resource - * - * @return the current name of the resource - */ - public String getCurrentName() { - return mCurrentName; - } - - /** - * Returns the type of the resource - * - * @return the type of the resource - */ - @NonNull - public ResourceType getType() { - return mType; - } - - /** - * Sets the new name - * - * @param newName the new name - */ - public void setNewName(@NonNull String newName) { - mNewName = newName; - } - - /** - * Returns {@code true} if the refactoring processor also updates references - * - * @return {@code true} if the refactoring processor also updates references - */ - public boolean isUpdateReferences() { - return mUpdateReferences; - } - - /** - * Specifies if the refactoring processor also updates references. The - * default behavior is to update references. - * - * @param updateReferences {@code true} if the refactoring processor should - * also updates references - */ - public void setUpdateReferences(boolean updateReferences) { - mUpdateReferences = updateReferences; - } - - /** - * Checks the given new potential name and returns a {@link RefactoringStatus} indicating - * whether the potential new name is valid - * - * @param name the name to check - * @return a {@link RefactoringStatus} with the validation result - */ - public RefactoringStatus checkNewName(String name) { - String error = mValidator.isValid(name); - if (error != null) { - return RefactoringStatus.createFatalErrorStatus(error); - } - - return new RefactoringStatus(); - } - - @Override - public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException { - return new RefactoringStatus(); - } - - @Override - public RefactoringStatus checkFinalConditions(IProgressMonitor pm, - CheckConditionsContext context) throws CoreException { - pm.beginTask("", 1); - try { - mRenameArguments = new RenameArguments(getNewName(), isUpdateReferences()); - return new RefactoringStatus(); - } finally { - pm.done(); - } - } - - @Override - public Change createChange(IProgressMonitor pm) throws CoreException { - pm.beginTask("", 1); - try { - // Added by {@link RenameResourceParticipant} - return null; - } finally { - pm.done(); - } - } - - @Override - public Object[] getElements() { - return new Object[0]; - } - - @Override - public String getIdentifier() { - return "com.android.ide.renameResourceProcessor"; //$NON-NLS-1$ - } - - @Override - public String getProcessorName() { - return "Rename Android Resource"; - } - - @Override - public boolean isApplicable() { - return true; - } - - @Override - public RefactoringParticipant[] loadParticipants(RefactoringStatus status, - SharableParticipants shared) throws CoreException { - String[] affectedNatures = new String[] { AdtConstants.NATURE_DEFAULT }; - String url = PREFIX_RESOURCE_REF + mType.getName() + '/' + mCurrentName; - return ParticipantManager.loadRenameParticipants(status, this, url, mRenameArguments, - null, affectedNatures, shared); - } -}
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceWizard.java deleted file mode 100644 index 6ffe25d22..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceWizard.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.internal.refactorings.core; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.resources.ResourceType; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.jdt.internal.ui.IJavaHelpContextIds; -import org.eclipse.jdt.internal.ui.JavaPluginImages; -import org.eclipse.jdt.internal.ui.refactoring.reorg.RenameRefactoringWizard; -import org.eclipse.jdt.ui.refactoring.RefactoringSaveHelper; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.ltk.core.refactoring.RefactoringStatus; -import org.eclipse.ltk.core.refactoring.participants.RenameRefactoring; -import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; -import org.eclipse.swt.widgets.Shell; - -/** - * Rename refactoring wizard for Android resources such as {@code @id/foo} - */ -@SuppressWarnings("restriction") // JDT refactoring UI -public class RenameResourceWizard extends RenameRefactoringWizard { - private ResourceType mType; - private boolean mCanClear; - - /** - * Constructs a new {@linkplain RenameResourceWizard} - * - * @param refactoring the refactoring - * @param type the type of resource being renamed - * @param canClear whether the user can clear the value - */ - public RenameResourceWizard( - @NonNull RenameRefactoring refactoring, - @NonNull ResourceType type, - boolean canClear) { - super(refactoring, - "Rename Resource", - "Enter the new name for this resource", - JavaPluginImages.DESC_WIZBAN_REFACTOR_FIELD, - IJavaHelpContextIds.RENAME_FIELD_WIZARD_PAGE); - mType = type; - mCanClear = canClear; - } - - @Override - protected void addUserInputPages() { - RenameRefactoring refactoring = (RenameRefactoring) getRefactoring(); - RenameResourceProcessor processor = (RenameResourceProcessor) refactoring.getProcessor(); - String name = processor.getNewName(); - addPage(new RenameResourcePage(mType, name, mCanClear)); - } - - /** - * Initiates a renaming of a resource item - * - * @param shell the shell to parent the dialog to - * @param project the project containing the resource references - * @param type the type of resource - * @param currentName the name of the resource - * @param newName the new name, or null if not known - * @param canClear whether the name is allowed to be cleared - * @return false if initiating the rename failed - */ - public static RenameResult renameResource( - @NonNull Shell shell, - @NonNull IProject project, - @NonNull ResourceType type, - @NonNull String currentName, - @Nullable String newName, - boolean canClear) { - try { - RenameResourceProcessor processor = new RenameResourceProcessor(project, type, - currentName, newName); - RenameRefactoring refactoring = new RenameRefactoring(processor); - if (!refactoring.isApplicable()) { - return RenameResult.unavailable(); - } - - if (!show(refactoring, processor, shell, type, canClear)) { - return RenameResult.canceled(); - } - return RenameResult.name(processor.getNewName()); - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - - return RenameResult.unavailable(); - } - - /** - * Show a refactoring dialog for the given resource refactoring operation - * - * @param refactoring the rename refactoring - * @param processor the field processor - * @param parent the parent shell - * @param type the resource type - * @param canClear whether the user is allowed to clear/reset the name to - * nothing - * @return true if the refactoring was performed, and false if it was - * canceled - * @throws CoreException if an unexpected error occurs - */ - private static boolean show( - @NonNull RenameRefactoring refactoring, - @NonNull RenameResourceProcessor processor, - @NonNull Shell parent, - @NonNull ResourceType type, - boolean canClear) throws CoreException { - RefactoringSaveHelper saveHelper = new RefactoringSaveHelper( - RefactoringSaveHelper.SAVE_REFACTORING); - if (!saveHelper.saveEditors(parent)) { - return false; - } - - try { - RenameResourceWizard wizard = new RenameResourceWizard(refactoring, type, canClear); - RefactoringWizardOpenOperation operation = new RefactoringWizardOpenOperation(wizard); - String dialogTitle = wizard.getDefaultPageTitle(); - int result = operation.run(parent, dialogTitle == null ? "" : dialogTitle); - RefactoringStatus status = operation.getInitialConditionCheckingStatus(); - if (status.hasFatalError()) { - return false; - } - if (result == RefactoringWizardOpenOperation.INITIAL_CONDITION_CHECKING_FAILED - || result == IDialogConstants.CANCEL_ID) { - saveHelper.triggerIncrementalBuild(); - return false; - } - - // Save modified resources; need to trigger R file regeneration - saveHelper.saveEditors(parent); - - return true; - } catch (InterruptedException e) { - return false; // Canceled - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextAction.java deleted file mode 100644 index 8ecb08836..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextAction.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.internal.refactorings.core; - -import static com.android.SdkConstants.ANDROID_MANIFEST_XML; -import static com.android.SdkConstants.ANDROID_PREFIX; -import static com.android.SdkConstants.ANDROID_THEME_PREFIX; -import static com.android.SdkConstants.ATTR_NAME; -import static com.android.SdkConstants.ATTR_TYPE; -import static com.android.SdkConstants.TAG_ITEM; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.common.resources.ResourceUrl; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities; -import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo; -import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; -import com.android.ide.eclipse.adt.internal.sdk.ProjectState; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.resources.ResourceType; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.internal.corext.refactoring.rename.RenameTypeProcessor; -import org.eclipse.jdt.internal.ui.refactoring.reorg.RenameTypeWizard; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.ITextSelection; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionProvider; -import org.eclipse.ltk.core.refactoring.participants.RenameRefactoring; -import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IFileEditorInput; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.texteditor.IDocumentProvider; -import org.eclipse.ui.texteditor.ITextEditor; -import org.eclipse.ui.texteditor.ITextEditorExtension; -import org.eclipse.ui.texteditor.ITextEditorExtension2; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import java.util.List; - -/** - * Text action for XML files to invoke renaming - * <p> - * TODO: Handle other types of renaming: invoking class renaming when editing - * class names in layout files and manifest files, renaming attribute names when - * editing a styleable attribute, etc. - */ -@SuppressWarnings("restriction") // Java rename refactoring -public final class RenameResourceXmlTextAction extends Action { - private final ITextEditor mEditor; - - /** - * Creates a new {@linkplain RenameResourceXmlTextAction} - * - * @param editor the associated editor - */ - public RenameResourceXmlTextAction(@NonNull ITextEditor editor) { - super("Rename"); - mEditor = editor; - } - - @Override - public void run() { - if (!validateEditorInputState()) { - return; - } - IFile file = getFile(); - if (file == null) { - return; - } - IProject project = file.getProject(); - if (project == null) { - return; - } - IDocument document = getDocument(); - if (document == null) { - return; - } - ITextSelection selection = getSelection(); - if (selection == null) { - return; - } - - ResourceUrl resource = findResource(document, selection.getOffset()); - - if (resource == null) { - resource = findItemDefinition(document, selection.getOffset()); - } - - if (resource != null) { - ResourceType type = resource.type; - String name = resource.name; - Shell shell = mEditor.getSite().getShell(); - boolean canClear = false; - - RenameResourceWizard.renameResource(shell, project, type, name, null, canClear); - return; - } - - String className = findClassName(document, file, selection.getOffset()); - if (className != null) { - assert className.equals(className.trim()); - IType type = findType(className, project); - if (type != null) { - RenameTypeProcessor processor = new RenameTypeProcessor(type); - //processor.setNewElementName(className); - processor.setUpdateQualifiedNames(true); - processor.setUpdateSimilarDeclarations(false); - //processor.setMatchStrategy(?); - //processor.setFilePatterns(patterns); - processor.setUpdateReferences(true); - - RenameRefactoring refactoring = new RenameRefactoring(processor); - RenameTypeWizard wizard = new RenameTypeWizard(refactoring); - RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard); - try { - IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - op.run(window.getShell(), wizard.getDefaultPageTitle()); - } catch (InterruptedException e) { - } - } - - return; - } - - // Fallback: tell user the cursor isn't in the right place - MessageDialog.openInformation(mEditor.getSite().getShell(), - "Rename", - "Operation unavailable on the current selection.\n" - + "Select an Android resource name or class."); - } - - private boolean validateEditorInputState() { - if (mEditor instanceof ITextEditorExtension2) - return ((ITextEditorExtension2) mEditor).validateEditorInputState(); - else if (mEditor instanceof ITextEditorExtension) - return !((ITextEditorExtension) mEditor).isEditorInputReadOnly(); - else if (mEditor != null) - return mEditor.isEditable(); - else - return false; - } - - /** - * Searches for a resource URL around the caret, such as {@code @string/foo} - * - * @param document the document to search in - * @param offset the offset to search at - * @return a resource pair, or null if not found - */ - @Nullable - public static ResourceUrl findResource(@NonNull IDocument document, int offset) { - try { - int max = document.getLength(); - if (offset >= max) { - offset = max - 1; - } else if (offset < 0) { - offset = 0; - } else if (offset > 0) { - // If the caret is right after a resource name (meaning getChar(offset) points - // to the following character), back up - char c = document.getChar(offset); - if (!isValidResourceNameChar(c)) { - offset--; - } - } - - int start = offset; - boolean valid = true; - for (; start >= 0; start--) { - char c = document.getChar(start); - if (c == '@' || c == '?') { - break; - } else if (!isValidResourceNameChar(c)) { - valid = false; - break; - } - } - if (valid) { - // Search forwards for the end - int end = start + 1; - for (; end < max; end++) { - char c = document.getChar(end); - if (!isValidResourceNameChar(c)) { - break; - } - } - if (end > start + 1) { - String url = document.get(start, end - start); - - // Don't allow renaming framework resources -- @android:string/ok etc - if (url.startsWith(ANDROID_PREFIX) || url.startsWith(ANDROID_THEME_PREFIX)) { - return null; - } - - return ResourceUrl.parse(url); - } - } - } catch (BadLocationException e) { - AdtPlugin.log(e, null); - } - - return null; - } - - private static boolean isValidResourceNameChar(char c) { - return c == '@' || c == '?' || c == '/' || c == '+' || Character.isJavaIdentifierPart(c); - } - - /** - * Searches for an item definition around the caret, such as - * {@code <string name="foo">My String</string>} - */ - private ResourceUrl findItemDefinition(IDocument document, int offset) { - Node node = DomUtilities.getNode(document, offset); - if (node == null) { - return null; - } - if (node.getNodeType() == Node.TEXT_NODE) { - node = node.getParentNode(); - } - if (node == null || node.getNodeType() != Node.ELEMENT_NODE) { - return null; - } - - Element element = (Element) node; - String name = element.getAttribute(ATTR_NAME); - if (name == null || name.isEmpty()) { - return null; - } - String typeString = element.getTagName(); - if (TAG_ITEM.equals(typeString)) { - typeString = element.getAttribute(ATTR_TYPE); - if (typeString == null || typeString.isEmpty()) { - return null; - } - } - ResourceType type = ResourceType.getEnum(typeString); - if (type != null) { - return ResourceUrl.create(type, name, false, false); - } - - return null; - } - - /** - * Searches for a fully qualified class name around the caret, such as {@code foo.bar.MyClass} - * - * @param document the document to search in - * @param file the file, if known - * @param offset the offset to search at - * @return a resource pair, or null if not found - */ - @Nullable - public static String findClassName( - @NonNull IDocument document, - @Nullable IFile file, - int offset) { - try { - int max = document.getLength(); - if (offset >= max) { - offset = max - 1; - } else if (offset < 0) { - offset = 0; - } else if (offset > 0) { - // If the caret is right after a resource name (meaning getChar(offset) points - // to the following character), back up - char c = document.getChar(offset); - if (Character.isJavaIdentifierPart(c)) { - offset--; - } - } - - int start = offset; - for (; start >= 0; start--) { - char c = document.getChar(start); - if (c == '"' || c == '<' || c == '/') { - start++; - break; - } else if (c != '.' && !Character.isJavaIdentifierPart(c)) { - return null; - } - } - // Search forwards for the end - int end = start + 1; - for (; end < max; end++) { - char c = document.getChar(end); - if (c != '.' && !Character.isJavaIdentifierPart(c)) { - if (c != '"' && c != '>' && !Character.isWhitespace(c)) { - return null; - } - break; - } - } - if (end > start + 1) { - String fqcn = document.get(start, end - start); - int dot = fqcn.indexOf('.'); - if (dot == -1) { // Only support fully qualified names - return null; - } - if (dot == 0) { // Special case for manifests: prepend package - if (file != null && file.getName().equals(ANDROID_MANIFEST_XML)) { - ManifestInfo info = ManifestInfo.get(file.getProject()); - return info.getPackage() + fqcn; - } - return null; - } - - return fqcn; - } - } catch (BadLocationException e) { - AdtPlugin.log(e, null); - } - - return null; - } - - @Nullable - private IType findType(@NonNull String className, @NonNull IProject project) { - IType type = null; - try { - IJavaProject javaProject = BaseProjectHelper.getJavaProject(project); - type = javaProject.findType(className); - if (type == null || !type.exists()) { - return null; - } - if (!type.isBinary()) { - return type; - } - // See if this class is coming through a library project jar file and - // if so locate the real class - ProjectState projectState = Sdk.getProjectState(project); - if (projectState != null) { - List<IProject> libraries = projectState.getFullLibraryProjects(); - for (IProject library : libraries) { - javaProject = BaseProjectHelper.getJavaProject(library); - type = javaProject.findType(className); - if (type != null && type.exists() && !type.isBinary()) { - return type; - } - } - } - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - - return null; - } - - private ITextSelection getSelection() { - ISelectionProvider selectionProvider = mEditor.getSelectionProvider(); - if (selectionProvider == null) { - return null; - } - ISelection selection = selectionProvider.getSelection(); - if (!(selection instanceof ITextSelection)) { - return null; - } - return (ITextSelection) selection; - } - - private IDocument getDocument() { - IDocumentProvider documentProvider = mEditor.getDocumentProvider(); - if (documentProvider == null) { - return null; - } - IDocument document = documentProvider.getDocument(mEditor.getEditorInput()); - if (document == null) { - return null; - } - return document; - } - - @Nullable - private IFile getFile() { - IEditorInput input = mEditor.getEditorInput(); - if (input instanceof IFileEditorInput) { - IFileEditorInput fileInput = (IFileEditorInput) input; - return fileInput.getFile(); - } - - return null; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResult.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResult.java deleted file mode 100644 index ade346fa9..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResult.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.ide.eclipse.adt.internal.refactorings.core; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; - -/** - * A result from a renaming operation - */ -public class RenameResult { - private boolean mCanceled; - private boolean mUnavailable; - private @Nullable String mName; - private boolean mClear; - - /** - * Constructs a new rename result - */ - private RenameResult() { - } - - /** - * Creates a new blank {@linkplain RenameResult} - * @return a new result - */ - @NonNull - public static RenameResult create() { - return new RenameResult(); - } - - /** - * Creates a new {@linkplain RenameResult} for a user canceled renaming operation - * @return a canceled operation - */ - @NonNull - public static RenameResult canceled() { - return new RenameResult().setCanceled(true); - } - - /** - * Creates a {@linkplain RenameResult} for a renaming operation that was - * not available (for example because the field attempted to be renamed - * does not yet exist (or does not exist any more) - * - * @return a new result - */ - @NonNull - public static RenameResult unavailable() { - return new RenameResult().setUnavailable(true); - } - - /** - * Creates a new {@linkplain RenameResult} for a successful renaming - * operation to the given name - * - * @param name the new name - * @return a new result - */ - @NonNull - public static RenameResult name(@Nullable String name) { - return new RenameResult().setName(name); - } - - /** - * Marks this result as canceled - * - * @param canceled whether the result was canceled - * @return this, for constructor chaining - */ - @NonNull - public RenameResult setCanceled(boolean canceled) { - mCanceled = canceled; - return this; - } - - /** - * Marks this result as unavailable - * - * @param unavailable whether this result was unavailable - * @return this, for constructor chaining - */ - @NonNull - public RenameResult setUnavailable(boolean unavailable) { - mUnavailable = unavailable; - return this; - } - - /** - * Sets the new name of the renaming operation - * - * @param name the new name - * @return this, for constructor chaining - */ - @NonNull - public RenameResult setName(@Nullable String name) { - mName = name; - return this; - } - - /** - * Marks this result as clearing the name (reverting it back to the default) - * - * @param clear whether the name was cleared - * @return this, for constructor chaining - */ - @NonNull - public RenameResult setCleared(boolean clear) { - mClear = clear; - return this; - } - - /** - * Returns whether this result represents a canceled renaming operation - * - * @return true if the operation was canceled - */ - public boolean isCanceled() { - return mCanceled; - } - - /** - * Returns whether this result represents an unavailable renaming operation - * - * @return true if the operation was not available - */ - public boolean isUnavailable() { - return mUnavailable; - } - - /** - * Returns whether this result represents a renaming back to the default (possibly - * clear) name. In this case, {@link #getName()} will return {@code null}. - * - * @return true if the name should be reset - */ - public boolean isCleared() { - return mClear; - } - - /** - * Returns the new name. - * - * @return the new name - */ - @Nullable - public String getName() { - return mName; - } -}
\ No newline at end of file |