aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipant.java547
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipant.java362
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipant.java529
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/FixImportsJob.java148
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringUtil.java224
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourcePage.java177
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipant.java752
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceProcessor.java211
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceWizard.java157
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextAction.java410
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResult.java163
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