aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-12-03 10:03:07 -0800
committerTor Norbye <tnorbye@google.com>2012-12-03 10:27:54 -0800
commit32654dfbd134559fbf6bec4542d6a4a8105897c9 (patch)
treefc8563ab428eef9d9759421283cb88643dce05b9
parent6c7924f6fea737bf5c87c1a6b845d690b8c46099 (diff)
downloadsdk-32654dfbd134559fbf6bec4542d6a4a8105897c9.tar.gz
Fix rename type, rename package and move type refactorings
This CL updates the various refactorings to properly handle layout refactoring such that it not only updates custom views, but also updates fragment references, tool:context references etc. It also fixes missing manifest updates (such as replacing the parentActivityName attributes). Most importantly, it also fixes bugs where the wrong elements in the manifest could get updated. There are a lot of diffs in this CL because I basically replaced the old refactoring code (which had a lot of custom text change and document manipulation code) with code based on the new resource refactoring, where there is a single iteration of the XML documents. This also improves the emitted refactoring elements such that it only lists each file once. Also updated the unit tests to check additional scenarios; adding a second activity with the same prefix as the first is what revealed the broken document handling in the old code. Change-Id: I7c5959ca6b046ce3dab566663988cdd0389b0e5b
-rw-r--r--common/src/com/android/xml/AndroidManifest.java86
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutMetadata.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidDocumentChange.java309
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidLayoutChange.java297
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidLayoutChangeDescription.java122
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidLayoutFileChanges.java61
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidPackageRenameChange.java135
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidTypeMoveChange.java45
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidTypeRenameChange.java120
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipant.java666
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidRenameParticipant.java86
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipant.java483
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipant.java503
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringUtil.java133
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipant.java34
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipantTest.java31
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringTestBase.java70
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipantTest.java19
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipantTest.java35
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipantTest.java72
21 files changed, 1072 insertions, 2242 deletions
diff --git a/common/src/com/android/xml/AndroidManifest.java b/common/src/com/android/xml/AndroidManifest.java
index d0f212621..306471e2e 100644
--- a/common/src/com/android/xml/AndroidManifest.java
+++ b/common/src/com/android/xml/AndroidManifest.java
@@ -34,49 +34,51 @@ import javax.xml.xpath.XPathExpressionException;
*/
public final class AndroidManifest {
- public final static String NODE_MANIFEST = "manifest";
- public final static String NODE_APPLICATION = "application";
- public final static String NODE_ACTIVITY = "activity";
- public final static String NODE_ACTIVITY_ALIAS = "activity-alias";
- public final static String NODE_SERVICE = "service";
- public final static String NODE_RECEIVER = "receiver";
- public final static String NODE_PROVIDER = "provider";
- public final static String NODE_INTENT = "intent-filter";
- public final static String NODE_ACTION = "action";
- public final static String NODE_CATEGORY = "category";
- public final static String NODE_USES_SDK = "uses-sdk";
- public final static String NODE_INSTRUMENTATION = "instrumentation";
- public final static String NODE_USES_LIBRARY = "uses-library";
- public final static String NODE_SUPPORTS_SCREENS = "supports-screens";
- public final static String NODE_USES_CONFIGURATION = "uses-configuration";
- public final static String NODE_USES_FEATURE = "uses-feature";
-
- public final static String ATTRIBUTE_PACKAGE = "package";
- public final static String ATTRIBUTE_VERSIONCODE = "versionCode";
- public final static String ATTRIBUTE_NAME = "name";
- public final static String ATTRIBUTE_REQUIRED = "required";
- public final static String ATTRIBUTE_GLESVERSION = "glEsVersion";
- public final static String ATTRIBUTE_PROCESS = "process";
- public final static String ATTRIBUTE_DEBUGGABLE = "debuggable";
- public final static String ATTRIBUTE_LABEL = "label";
- public final static String ATTRIBUTE_ICON = "icon";
- public final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion";
- public final static String ATTRIBUTE_TARGET_SDK_VERSION = "targetSdkVersion";
- public final static String ATTRIBUTE_TARGET_PACKAGE = "targetPackage";
- public final static String ATTRIBUTE_TARGET_ACTIVITY = "targetActivity";
- public final static String ATTRIBUTE_MANAGE_SPACE_ACTIVITY = "manageSpaceActivity";
- public final static String ATTRIBUTE_EXPORTED = "exported";
- public final static String ATTRIBUTE_RESIZEABLE = "resizeable";
- public final static String ATTRIBUTE_ANYDENSITY = "anyDensity";
- public final static String ATTRIBUTE_SMALLSCREENS = "smallScreens";
- public final static String ATTRIBUTE_NORMALSCREENS = "normalScreens";
- public final static String ATTRIBUTE_LARGESCREENS = "largeScreens";
- public final static String ATTRIBUTE_REQ_5WAYNAV = "reqFiveWayNav";
- public final static String ATTRIBUTE_REQ_NAVIGATION = "reqNavigation";
- public final static String ATTRIBUTE_REQ_HARDKEYBOARD = "reqHardKeyboard";
- public final static String ATTRIBUTE_REQ_KEYBOARDTYPE = "reqKeyboardType";
- public final static String ATTRIBUTE_REQ_TOUCHSCREEN = "reqTouchScreen";
+ public static final String NODE_MANIFEST = "manifest";
+ public static final String NODE_APPLICATION = "application";
+ public static final String NODE_ACTIVITY = "activity";
+ public static final String NODE_ACTIVITY_ALIAS = "activity-alias";
+ public static final String NODE_SERVICE = "service";
+ public static final String NODE_RECEIVER = "receiver";
+ public static final String NODE_PROVIDER = "provider";
+ public static final String NODE_INTENT = "intent-filter";
+ public static final String NODE_ACTION = "action";
+ public static final String NODE_CATEGORY = "category";
+ public static final String NODE_USES_SDK = "uses-sdk";
+ public static final String NODE_INSTRUMENTATION = "instrumentation";
+ public static final String NODE_USES_LIBRARY = "uses-library";
+ public static final String NODE_SUPPORTS_SCREENS = "supports-screens";
+ public static final String NODE_USES_CONFIGURATION = "uses-configuration";
+ public static final String NODE_USES_FEATURE = "uses-feature";
+
+ public static final String ATTRIBUTE_PACKAGE = "package";
+ public static final String ATTRIBUTE_VERSIONCODE = "versionCode";
+ public static final String ATTRIBUTE_NAME = "name";
+ public static final String ATTRIBUTE_REQUIRED = "required";
+ public static final String ATTRIBUTE_GLESVERSION = "glEsVersion";
+ public static final String ATTRIBUTE_PROCESS = "process";
+ public static final String ATTRIBUTE_DEBUGGABLE = "debuggable";
+ public static final String ATTRIBUTE_LABEL = "label";
+ public static final String ATTRIBUTE_ICON = "icon";
+ public static final String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion";
+ public static final String ATTRIBUTE_TARGET_SDK_VERSION = "targetSdkVersion";
+ public static final String ATTRIBUTE_TARGET_PACKAGE = "targetPackage";
+ public static final String ATTRIBUTE_TARGET_ACTIVITY = "targetActivity";
+ public static final String ATTRIBUTE_MANAGE_SPACE_ACTIVITY = "manageSpaceActivity";
+ public static final String ATTRIBUTE_EXPORTED = "exported";
+ public static final String ATTRIBUTE_RESIZEABLE = "resizeable";
+ public static final String ATTRIBUTE_ANYDENSITY = "anyDensity";
+ public static final String ATTRIBUTE_SMALLSCREENS = "smallScreens";
+ public static final String ATTRIBUTE_NORMALSCREENS = "normalScreens";
+ public static final String ATTRIBUTE_LARGESCREENS = "largeScreens";
+ public static final String ATTRIBUTE_REQ_5WAYNAV = "reqFiveWayNav";
+ public static final String ATTRIBUTE_REQ_NAVIGATION = "reqNavigation";
+ public static final String ATTRIBUTE_REQ_HARDKEYBOARD = "reqHardKeyboard";
+ public static final String ATTRIBUTE_REQ_KEYBOARDTYPE = "reqKeyboardType";
+ public static final String ATTRIBUTE_REQ_TOUCHSCREEN = "reqTouchScreen";
public static final String ATTRIBUTE_THEME = "theme";
+ public static final String ATTRIBUTE_BACKUP_AGENT = "backupAgent";
+ public static final String ATTRIBUTE_PARENT_ACTIVITY_NAME = "parentActivityName";
/**
* Returns an {@link IAbstractFile} object representing the manifest for the given project.
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
index 3745613af..67bd705f0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
@@ -104,7 +104,6 @@ Export-Package: com.android.assetstudiolib;x-friends:="com.android.ide.eclipse.t
com.android.ide.eclipse.adt.internal.preferences;x-friends:="com.android.ide.eclipse.tests",
com.android.ide.eclipse.adt.internal.project;x-friends:="com.android.ide.eclipse.tests",
com.android.ide.eclipse.adt.internal.properties;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.adt.internal.refactorings.changes;x-friends:="com.android.ide.eclipse.tests",
com.android.ide.eclipse.adt.internal.refactorings.core;x-friends:="com.android.ide.eclipse.tests",
com.android.ide.eclipse.adt.internal.refactorings.extractstring;x-friends:="com.android.ide.eclipse.tests",
com.android.ide.eclipse.adt.internal.refactorings.renamepackage;x-friends:="com.android.ide.eclipse.tests",
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutMetadata.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutMetadata.java
index 94bd05809..b79e3b0a1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutMetadata.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutMetadata.java
@@ -56,7 +56,6 @@ import java.util.Map;
/**
* Design-time metadata lookup for layouts, such as fragment and AdapterView bindings.
*/
-@SuppressWarnings("restriction") // XML DOM model
public class LayoutMetadata {
/** The default layout to use for list items in expandable list views */
public static final String DEFAULT_EXPANDABLE_LIST_ITEM = "simple_expandable_list_item_2"; //$NON-NLS-1$
@@ -75,6 +74,8 @@ public class LayoutMetadata {
public static final String KEY_LV_FOOTER = "listfooter"; //$NON-NLS-1$
/** The property key, included in comments, which references a fragment layout to show */
public static final String KEY_FRAGMENT_LAYOUT = "layout"; //$NON-NLS-1$
+ // NOTE: If you add additional keys related to resources, make sure you update the
+ // ResourceRenameParticipant
/** Utility class, do not create instances */
private LayoutMetadata() {
@@ -191,9 +192,6 @@ public class LayoutMetadata {
return;
}
Display display = AdtPlugin.getDisplay();
- if (display == null) {
- return;
- }
WorkbenchJob job = new WorkbenchJob(display, "Update alternate views") {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidDocumentChange.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidDocumentChange.java
deleted file mode 100644
index eb8ccc772..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidDocumentChange.java
+++ /dev/null
@@ -1,309 +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.changes;
-
-import com.android.SdkConstants;
-import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper;
-import com.android.ide.eclipse.adt.internal.project.XmlErrorHandler.BasicXmlErrorListener;
-import com.android.ide.eclipse.adt.internal.refactorings.core.RefactoringUtil;
-import com.android.xml.AndroidManifest;
-
-import org.eclipse.core.filebuffers.ITextFileBufferManager;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.ltk.core.refactoring.DocumentChange;
-import org.eclipse.ltk.core.refactoring.RefactoringStatus;
-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.IStructuredModel;
-import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
-import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
-import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
-import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
-import org.w3c.dom.Attr;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import java.util.Map;
-
-/**
- * A text change that operates on android manifest using WTP SSE model.
- * It is base class for Rename Package and Rename Type changes
-*/
-@SuppressWarnings("restriction")
-public class AndroidDocumentChange extends DocumentChange {
-
- protected IFile mAndroidManifest;
-
- protected String mAppPackage;
-
- protected IStructuredModel mModel;
-
- protected IDocument mDocument;
-
- protected Map<String, String> mElements;
-
- protected String mNewName;
-
- protected String mOldName;
-
- protected ITextFileBufferManager mManager;
-
- /**
- * Creates a new <code>AndroidDocumentChange</code> for the given
- * {@link IDocument}.
- *
- * @param document the document this change is working on
- */
- public AndroidDocumentChange(IDocument document) {
- super(SdkConstants.FN_ANDROID_MANIFEST_XML, document);
- }
-
- /**
- * Returns the manifest file
- *
- * @return the manifest
- */
- public IFile getManifest() {
- return mAndroidManifest;
- }
-
- @Override
- public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException,
- OperationCanceledException {
- RefactoringStatus status = super.isValid(pm);
- if (mModel == null) {
- status.addFatalError("File " + SdkConstants.FN_ANDROID_MANIFEST_XML + " is invalid.");
- } else {
- mAppPackage = getAppPackage();
- if (mAppPackage == null) {
- status.addFatalError("Invalid package in the "
- + SdkConstants.FN_ANDROID_MANIFEST_XML + " file.");
- }
- }
- BasicXmlErrorListener errorListener = new BasicXmlErrorListener();
- AndroidManifestHelper.parseForError(mAndroidManifest, errorListener);
-
- if (errorListener.mHasXmlError == true) {
- status.addFatalError("File " + SdkConstants.FN_ANDROID_MANIFEST_XML + " is invalid.");
- }
- return status;
- }
-
- /**
- * Finds the attribute with values oldName
- *
- * @param xmlDoc the document
- * @param element the element
- * @param attributeName the attribute
- * @param oldName the value
- *
- * @return the attribute
- */
- private Attr findAttribute(IDOMDocument xmlDoc, String element, String attributeName,
- String oldName) {
- NodeList nodes = xmlDoc.getElementsByTagName(element);
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- NamedNodeMap attributes = node.getAttributes();
- if (attributes != null) {
- Attr attribute = RefactoringUtil.findAndroidAttributes(attributes, attributeName);
- if (attribute != null) {
- String value = attribute.getValue();
- if (value != null) {
- String fullName = AndroidManifest.combinePackageAndClassName(
- getAppPackage(), value);
- if (fullName != null && fullName.equals(oldName)) {
- return attribute;
- }
- }
- }
- }
- }
- return null;
- }
-
- /**
- * Returns the attribute value
- *
- * @param xmlDoc the document
- * @param element the element
- * @param attributeName the attribute
- *
- * @return the attribute value
- */
- protected String getElementAttribute(IDOMDocument xmlDoc, String element,
- String attributeName, boolean useNamespace) {
- NodeList nodes = xmlDoc.getElementsByTagName(element);
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- NamedNodeMap attributes = node.getAttributes();
- if (attributes != null) {
- Attr attribute;
- if (useNamespace) {
- attribute = RefactoringUtil.findAndroidAttributes(attributes, attributeName);
- } else {
- attribute = (Attr) attributes.getNamedItem(attributeName);
- }
- if (attribute != null) {
- return attribute.getValue();
- }
- }
- }
- return null;
- }
-
- /**
- * Returns the SSE model for a document
- *
- * @param document the document
- * @return the model
- *
- */
- protected IStructuredModel getModel(IDocument document) {
- if (mModel != null) {
- return mModel;
- }
- IStructuredModel model;
- model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
- if (model == null) {
- if (document instanceof IStructuredDocument) {
- IStructuredDocument structuredDocument = (IStructuredDocument) document;
- model = StructuredModelManager.getModelManager()
- .getModelForRead(structuredDocument);
- }
- }
- return model;
- }
-
- @Override
- public void setTextType(String type) {
- super.setTextType(mAndroidManifest.getFileExtension());
- }
-
- /**
- * Returns the SSE DOM document
- *
- * @return the attribute value
- */
- protected IDOMDocument getDOMDocument() {
- IDOMModel xmlModel = (IDOMModel) mModel;
- IDOMDocument xmlDoc = xmlModel.getDocument();
- return xmlDoc;
- }
-
- /**
- * Returns the application package
- *
- * @return the package name
- */
- protected String getAppPackage() {
- if (mAppPackage == null) {
- IDOMDocument xmlDoc = getDOMDocument();
- mAppPackage = getElementAttribute(xmlDoc, AndroidManifest.NODE_MANIFEST,
- AndroidManifest.ATTRIBUTE_PACKAGE, false);
- }
- return mAppPackage;
- }
-
- /**
- * Returns the text change that set new value of attribute
- *
- * @param attribute the attribute
- * @param newValue the new value
- *
- * @return the text change
- */
- protected TextEdit createTextEdit(Attr attribute, String newValue) {
- if (attribute == null)
- return null;
-
- if (attribute instanceof IDOMAttr) {
- IDOMAttr domAttr = (IDOMAttr) attribute;
- // Get the current "region" (the current attribute, including its quotes.)
- String region = domAttr.getValueRegionText();
- int offset = domAttr.getValueRegionStartOffset();
- if (region != null && region.length() >= 2) {
- // Skip the quotes when replacing.
- ReplaceEdit edit = new ReplaceEdit(offset + 1, region.length() - 2, newValue);
- return edit;
- }
- }
- return null;
- }
-
- /**
- * Returns the text change that change the value of attribute from oldValue to newValue
- * and combine package
- *
- * @param elementName the element name
- * @param attributeName the attribute name
- * @param oldValue the old value
- * @param newValue the new value
- *
- * @return the text change
- */
- protected TextEdit createTextEdit(String elementName, String attributeName, String oldValue,
- String newValue) {
- return createTextEdit(elementName, attributeName, oldValue, newValue, true);
- }
-
- /**
- * Returns the text change that change the value of attribute from oldValue to newValue
- *
- * @param elementName the element name
- * @param attributeName the attribute name
- * @param oldName the old value
- * @param newName the new value
- * @param combinePackage combine package ?
- *
- * @return the text change
- */
- protected TextEdit createTextEdit(String elementName, String attributeName, String oldName,
- String newName, boolean combinePackage) {
- IDOMDocument xmlDoc = getDOMDocument();
- String name = null;
- Attr attr = findAttribute(xmlDoc, elementName, attributeName, oldName);
- if (attr != null) {
- name = attr.getValue();
- }
- if (name != null) {
- String newValue = newName;
- if (combinePackage) {
- String pkg = getAppPackage();
- if (oldName.startsWith(pkg) && newName.startsWith(pkg)) {
- // Heuristic: if the old value is a fully qualified name, then
- // assume that's how the user wants it in the manifest and
- // do *not* shorten the new value. Keep it fully qualified too.
- } else {
- newValue = AndroidManifest.extractActivityName(newName, pkg);
- }
- }
- if (newValue != null) {
- TextEdit edit = createTextEdit(attr, newValue);
- return edit;
- }
- }
- return null;
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidLayoutChange.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidLayoutChange.java
deleted file mode 100644
index 7bac6d75a..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidLayoutChange.java
+++ /dev/null
@@ -1,297 +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.changes;
-
-import com.android.SdkConstants;
-import com.android.ide.eclipse.adt.internal.refactorings.core.RefactoringUtil;
-
-import org.eclipse.core.filebuffers.ITextFileBufferManager;
-import org.eclipse.core.filebuffers.LocationKind;
-import org.eclipse.core.resources.IFile;
-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.jface.text.IDocument;
-import org.eclipse.ltk.core.refactoring.DocumentChange;
-import org.eclipse.ltk.core.refactoring.RefactoringStatus;
-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.sse.core.internal.provisional.text.IStructuredDocumentRegion;
-import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
-import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
-import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
-import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
-import org.w3c.dom.Attr;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * A text change that operates on android layout using WTP SSE model.
- * It is base class for Rename Package and Rename Type changes
-*/
-@SuppressWarnings("restriction")
-public class AndroidLayoutChange extends DocumentChange {
-
- private IDocument mDocument;
-
- private ITextFileBufferManager mManager;
-
- private IFile mFile;
-
- private IStructuredModel mModel;
-
- private Set<AndroidLayoutChangeDescription> mChanges;
-
- /**
- * Creates a new <code>AndroidLayoutChange</code>
- *
- * @param file the layout file
- * @param document the document
- * @param manager the buffer manager
- * @param changes the list of changes
- */
- public AndroidLayoutChange(IFile file, IDocument document, ITextFileBufferManager manager,
- Set<AndroidLayoutChangeDescription> changes) {
- super("", document); //$NON-NLS-1$
- mFile = file;
- mDocument = document;
- mManager = manager;
- mChanges = changes;
- try {
- this.mModel = getModel(document);
- } catch (Exception ignore) {
- }
- if (mModel != null) {
- addEdits();
- }
- }
-
- public IFile getFile() {
- return mFile;
- }
-
- @Override
- public String getName() {
- return mFile.getName();
- }
-
- @Override
- public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException,
- OperationCanceledException {
- RefactoringStatus status = super.isValid(pm);
- if (mModel == null) {
- status.addFatalError("Invalid the " + getName() + " file.");
- }
- return status;
- }
-
- @Override
- public void setTextType(String type) {
- super.setTextType(mFile.getFileExtension());
- }
-
- @Override
- public void dispose() {
- super.dispose();
- RefactoringUtil.fixModel(mModel, mDocument);
-
- if (mManager != null) {
- try {
- mManager.disconnect(mFile.getFullPath(), LocationKind.NORMALIZE,
- new NullProgressMonitor());
- } catch (CoreException e) {
- RefactoringUtil.log(e);
- }
- }
- }
-
- // ----
-
- /**
- * Adds text edits for this change
- */
- private void addEdits() {
- MultiTextEdit multiEdit = new MultiTextEdit();
- for (AndroidLayoutChangeDescription change : mChanges) {
- if (!change.isStandalone()) {
- TextEdit edit = createTextEdit(SdkConstants.VIEW,
- SdkConstants.ATTR_CLASS,
- change.getClassName(),
- change.getNewName());
- if (edit != null) {
- multiEdit.addChild(edit);
- }
- } else {
- List<TextEdit> edits = createElementTextEdit(change.getClassName(),
- change.getNewName());
- for (TextEdit edit : edits) {
- multiEdit.addChild(edit);
- }
- }
- }
- setEdit(multiEdit);
- }
-
- /**
- * Returns the text changes which change class (custom layout viewer) in layout file
- *
- * @param className the class name
- * @param newName the new class name
- *
- * @return list of text changes
- */
- private List<TextEdit> createElementTextEdit(String className, String newName) {
- IDOMDocument xmlDoc = getDOMDocument();
- List<TextEdit> edits = new ArrayList<TextEdit>();
- NodeList nodes = xmlDoc.getElementsByTagName(className);
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- if (node instanceof IDOMElement) {
- IDOMElement domNode = (IDOMElement) node;
- IStructuredDocumentRegion firstRegion = domNode.getFirstStructuredDocumentRegion();
- if (firstRegion != null) {
- int offset = firstRegion.getStartOffset();
- edits.add(new ReplaceEdit(offset + 1, className.length(), newName));
- }
- IStructuredDocumentRegion endRegion = domNode.getEndStructuredDocumentRegion();
- if (endRegion != null) {
- int offset = endRegion.getStartOffset();
- edits.add(new ReplaceEdit(offset + 2, className.length(), newName));
- }
- }
-
- }
- return edits;
- }
-
- /**
- * Returns the SSE DOM document
- *
- * @return the attribute value
- */
- private IDOMDocument getDOMDocument() {
- IDOMModel xmlModel = (IDOMModel) mModel;
- IDOMDocument xmlDoc = xmlModel.getDocument();
- return xmlDoc;
- }
-
- /**
- * Returns the text change that set new value of attribute
- *
- * @param attribute the attribute
- * @param newValue the new value
- *
- * @return the text change
- */
- private TextEdit createTextEdit(Attr attribute, String newValue) {
- if (attribute == null)
- return null;
-
- if (attribute instanceof IDOMAttr) {
- IDOMAttr domAttr = (IDOMAttr) attribute;
- String region = domAttr.getValueRegionText();
- int offset = domAttr.getValueRegionStartOffset();
- if (region != null && region.length() >= 2) {
- return new ReplaceEdit(offset + 1, region.length() - 2, newValue);
- }
- }
- return null;
- }
-
-
- /**
- * Returns the text change that change the value of attribute from oldValue to newValue
- *
- * @param elementName the element name
- * @param argumentName the attribute name
- * @param oldName the old value
- * @param newName the new value
- *
- * @return the text change
- */
- private TextEdit createTextEdit(String elementName, String argumentName, String oldName,
- String newName) {
- IDOMDocument xmlDoc = getDOMDocument();
- String name = null;
- Attr attr = findAttribute(xmlDoc, elementName, argumentName, oldName);
- if (attr != null) {
- name = attr.getValue();
- }
- if (name != null && newName != null) {
- TextEdit edit = createTextEdit(attr, newName);
- return edit;
- }
- return null;
- }
-
- /**
- * Finds the attribute with values oldName
- *
- * @param xmlDoc the document
- * @param element the element
- * @param attributeName the attribute
- * @param oldValue the value
- *
- * @return the attribute
- */
- private Attr findAttribute(IDOMDocument xmlDoc, String element, String attributeName,
- String oldValue) {
- NodeList nodes = xmlDoc.getElementsByTagName(element);
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- NamedNodeMap attributes = node.getAttributes();
- if (attributes != null) {
- Attr attribute = RefactoringUtil.findAndroidAttributes(attributes, attributeName);
- if (attribute != null) {
- String value = attribute.getValue();
- if (value != null && value.equals(oldValue)) {
- return attribute;
- }
- }
- }
- }
- return null;
- }
-
- /**
- * Returns the SSE model for a document
- *
- * @param document the document
- * @return the model
- */
- private IStructuredModel getModel(IDocument document) {
-
- IModelManager manager = StructuredModelManager.getModelManager();
- IStructuredModel model = manager.getExistingModelForRead(document);
- if (model == null && document instanceof IStructuredDocument) {
- model = manager.getModelForRead((IStructuredDocument) document);
- }
-
- return model;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidLayoutChangeDescription.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidLayoutChangeDescription.java
deleted file mode 100644
index 2ddaac0c1..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidLayoutChangeDescription.java
+++ /dev/null
@@ -1,122 +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.changes;
-
-/**
- * This class describes the text changes of android layout files
- *
- */
-public class AndroidLayoutChangeDescription {
-
- private String mClassName;
-
- private String mNewName;
-
- private int mType;
-
- /**
- * the view layout
- */
- public static final int VIEW_TYPE = 0;
-
- /**
- * the standalone layout
- */
- public static final int STANDALONE_TYPE = 1;
-
- /**
- * Creates a new <code>AndroidDocumentChange</code>
- *
- * @param className the old layout class name
- * @param newName the new layout class name
- * @param type the layout type; valid value are VIEW_TYPE and STANDALONE_TYPE
- */
- public AndroidLayoutChangeDescription(String className, String newName, int type) {
- this.mClassName = className;
- this.mNewName = newName;
- this.mType = type;
- }
-
- /**
- * @return the old class name
- */
- public String getClassName() {
- return mClassName;
- }
-
- /**
- * @return the new class name
- */
- public String getNewName() {
- return mNewName;
- }
-
- /**
- * @return the layout type
- */
- public int getType() {
- return mType;
- }
-
- /**
- * @return true if the layout is standalone
- */
- public boolean isStandalone() {
- return mType == STANDALONE_TYPE;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((mClassName == null) ? 0 : mClassName.hashCode());
- result = prime * result + ((mNewName == null) ? 0 : mNewName.hashCode());
- result = prime * result + mType;
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- AndroidLayoutChangeDescription other = (AndroidLayoutChangeDescription) obj;
- if (mClassName == null) {
- if (other.mClassName != null)
- return false;
- } else if (!mClassName.equals(other.mClassName))
- return false;
- if (mNewName == null) {
- if (other.mNewName != null)
- return false;
- } else if (!mNewName.equals(other.mNewName))
- return false;
- if (mType != other.mType)
- return false;
- return true;
- }
-
- @Override
- public String toString() {
- return "AndroidLayoutChangeDescription [className=" + mClassName + ", newName=" + mNewName
- + ", type=" + mType + "]";
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidLayoutFileChanges.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidLayoutFileChanges.java
deleted file mode 100644
index 1d4a7410e..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidLayoutFileChanges.java
+++ /dev/null
@@ -1,61 +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.changes;
-
-import org.eclipse.core.resources.IFile;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Set of layout files with required text changes
- *
- */
-public class AndroidLayoutFileChanges {
- private IFile mFile;
-
- private Set<AndroidLayoutChangeDescription> mChanges =
- new HashSet<AndroidLayoutChangeDescription>();
-
- /**
- * Creates a new <code>AndroidLayoutFileChanges</code>
- *
- * @param file the layout file
- */
- public AndroidLayoutFileChanges(IFile file) {
- this.mFile = file;
- }
-
- /**
- * Return the layout file
- *
- * @return the file
- */
- public IFile getFile() {
- return mFile;
- }
-
- /**
- * Return the text changes
- *
- * @return the set of changes
- */
- public Set<AndroidLayoutChangeDescription> getChanges() {
- return mChanges;
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidPackageRenameChange.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidPackageRenameChange.java
deleted file mode 100644
index 08e4f01e3..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidPackageRenameChange.java
+++ /dev/null
@@ -1,135 +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.changes;
-
-import com.android.ide.eclipse.adt.internal.refactorings.core.FixImportsJob;
-import com.android.ide.eclipse.adt.internal.refactorings.core.RefactoringUtil;
-import com.android.xml.AndroidManifest;
-
-import org.eclipse.core.filebuffers.ITextFileBufferManager;
-import org.eclipse.core.filebuffers.LocationKind;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.ltk.core.refactoring.Change;
-import org.eclipse.text.edits.MultiTextEdit;
-import org.eclipse.text.edits.TextEdit;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A text change that operates on android manifest when execute Java Rename package refactoring
-*/
-public class AndroidPackageRenameChange extends AndroidDocumentChange {
-
- private boolean mIsPackage;
-
- /**
- * Creates a new <code>AndroidPackageRenameChange</code>
- *
- * @param androidManifest the android manifest file
- * @param manager the text buffer manager
- * @param document the document
- * @param elements the elements
- * @param newName the new name
- * @param oldName the old name
- * @param isPackage is the application package
- */
- public AndroidPackageRenameChange(IFile androidManifest, ITextFileBufferManager manager,
- IDocument document, Map<String, String> elements, String oldName, String newName,
- boolean isPackage) {
- super(document);
- this.mDocument = document;
- this.mIsPackage = isPackage;
- this.mElements = elements;
- this.mNewName = newName;
- this.mOldName = oldName;
- this.mManager = manager;
- this.mAndroidManifest = androidManifest;
- try {
- this.mModel = getModel(document);
- } catch (Exception ignore) {
- }
- if (mModel != null) {
- this.mAppPackage = getAppPackage();
- addEdits();
- }
- }
-
- /**
- * Adds text edits for this change
- */
- private void addEdits() {
- MultiTextEdit multiEdit = new MultiTextEdit();
-
- if (mIsPackage) {
- TextEdit edit = createTextEdit(AndroidManifest.NODE_MANIFEST,
- AndroidManifest.ATTRIBUTE_PACKAGE, mOldName, mNewName, false);
- if (edit != null) {
- multiEdit.addChild(edit);
- }
- }
- Set<String> keys = mElements.keySet();
- for (String key : keys) {
- String value = mElements.get(key);
- String oldValue = AndroidManifest.combinePackageAndClassName(mAppPackage, value);
- String newValue = oldValue.replaceFirst(mOldName, mNewName);
- TextEdit edit = createTextEdit(key, AndroidManifest.ATTRIBUTE_NAME, oldValue,
- newValue);
- if (edit != null) {
- multiEdit.addChild(edit);
- }
- if (AndroidManifest.NODE_ACTIVITY.equals(key)) {
- TextEdit alias = createTextEdit(AndroidManifest.NODE_ACTIVITY_ALIAS,
- AndroidManifest.ATTRIBUTE_TARGET_ACTIVITY, oldValue, newValue);
- if (alias != null) {
- multiEdit.addChild(alias);
- }
- }
- }
- setEdit(multiEdit);
- }
-
- @Override
- public Change perform(IProgressMonitor pm) throws CoreException {
- super.perform(pm);
- return new AndroidPackageRenameChange(mAndroidManifest, mManager, mDocument, mElements,
- mOldName, mNewName, mIsPackage);
- }
-
- @Override
- public void dispose() {
- super.dispose();
- RefactoringUtil.fixModel(mModel, mDocument);
-
- if (mManager != null) {
- try {
- mManager.disconnect(mAndroidManifest.getFullPath(), LocationKind.NORMALIZE,
- new NullProgressMonitor());
- } catch (CoreException e) {
- RefactoringUtil.log(e);
- }
- }
- if (mIsPackage) {
- new FixImportsJob("Fix Rename Package", mAndroidManifest, mNewName).schedule(500);
- }
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidTypeMoveChange.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidTypeMoveChange.java
deleted file mode 100644
index 618500d4b..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidTypeMoveChange.java
+++ /dev/null
@@ -1,45 +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.changes;
-
-import org.eclipse.core.filebuffers.ITextFileBufferManager;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.jface.text.IDocument;
-
-import java.util.Map;
-
-/**
- * A text change that operates on android manifest when execute Java Move type refactoring
-*/
-public class AndroidTypeMoveChange extends AndroidTypeRenameChange {
-
- /**
- * Creates a new <code>AndroidTypeMoveChange</code>
- *
- * @param androidManifest the android manifest file
- * @param manager the text buffer manager
- * @param document the document
- * @param elements the elements
- * @param newName the new name
- * @param oldName the old name
- */
- public AndroidTypeMoveChange(IFile androidManifest, ITextFileBufferManager manager,
- IDocument document, Map<String, String> elements, String oldName, String newName) {
- super(androidManifest, manager, document, elements, oldName, newName);
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidTypeRenameChange.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidTypeRenameChange.java
deleted file mode 100644
index 275d41282..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/changes/AndroidTypeRenameChange.java
+++ /dev/null
@@ -1,120 +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.changes;
-
-import com.android.ide.eclipse.adt.internal.refactorings.core.RefactoringUtil;
-import com.android.xml.AndroidManifest;
-
-import org.eclipse.core.filebuffers.ITextFileBufferManager;
-import org.eclipse.core.filebuffers.LocationKind;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.ltk.core.refactoring.Change;
-import org.eclipse.text.edits.MultiTextEdit;
-import org.eclipse.text.edits.TextEdit;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A text change that operates on android manifest when execute Java Rename type refactoring
-*/
-public class AndroidTypeRenameChange extends AndroidDocumentChange {
-
- /**
- * * Creates a new <code>AndroidTypeRenameChange</code>
- *
- * @param androidManifest the android manifest file
- * @param manager the text buffer manager
- * @param document the document
- * @param elements the elements
- * @param newName the new name
- * @param oldName the old name
- */
- public AndroidTypeRenameChange(IFile androidManifest, ITextFileBufferManager manager,
- IDocument document, Map<String, String> elements, String oldName, String newName) {
- super(document);
- this.mDocument = document;
- this.mElements = elements;
- this.mOldName = oldName;
- this.mNewName = newName;
- this.mManager = manager;
- this.mAndroidManifest = androidManifest;
- try {
- this.mModel = getModel(document);
- } catch (Exception ignore) {
- }
- if (mModel != null) {
- addEdits();
- }
- }
-
- /**
- * Adds text edits for this change
- */
- private void addEdits() {
- MultiTextEdit multiEdit = new MultiTextEdit();
- Set<String> keys = mElements.keySet();
- for (String key : keys) {
- TextEdit edit = createTextEdit(key, AndroidManifest.ATTRIBUTE_NAME, mOldName,
- mNewName);
- if (edit != null) {
- multiEdit.addChild(edit);
- }
- if (AndroidManifest.NODE_ACTIVITY.equals(key)) {
- TextEdit alias = createTextEdit(AndroidManifest.NODE_ACTIVITY_ALIAS,
- AndroidManifest.ATTRIBUTE_TARGET_ACTIVITY, mOldName, mNewName);
- if (alias != null) {
- multiEdit.addChild(alias);
- }
- TextEdit manageSpaceActivity = createTextEdit(
- AndroidManifest.NODE_APPLICATION,
- AndroidManifest.ATTRIBUTE_MANAGE_SPACE_ACTIVITY, mOldName, mNewName);
- if (manageSpaceActivity != null) {
- multiEdit.addChild(manageSpaceActivity);
- }
- }
- }
- setEdit(multiEdit);
- }
-
- @Override
- public Change perform(IProgressMonitor pm) throws CoreException {
- super.perform(pm);
- return new AndroidTypeRenameChange(mAndroidManifest, mManager, mDocument, mElements,
- mOldName, mNewName);
- }
-
- @Override
- public void dispose() {
- super.dispose();
- RefactoringUtil.fixModel(mModel, mDocument);
-
- if (mManager != null) {
- try {
- mManager.disconnect(mAndroidManifest.getFullPath(), LocationKind.NORMALIZE,
- new NullProgressMonitor());
- } catch (CoreException e) {
- RefactoringUtil.log(e);
- }
- }
- }
-
-}
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
index bd3224dc7..67f7d44ff 100644
--- 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
@@ -16,20 +16,26 @@
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.project.AndroidManifestHelper;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidLayoutChange;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidLayoutChangeDescription;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidLayoutFileChanges;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidPackageRenameChange;
-import com.android.xml.AndroidManifest;
-
-import org.eclipse.core.filebuffers.FileBuffers;
-import org.eclipse.core.filebuffers.ITextFileBuffer;
-import org.eclipse.core.filebuffers.ITextFileBufferManager;
-import org.eclipse.core.filebuffers.LocationKind;
+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;
@@ -37,34 +43,39 @@ 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.NullProgressMonitor;
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.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.corext.refactoring.changes.RenamePackageChange;
-import org.eclipse.jface.text.IDocument;
+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.NullChange;
+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.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.IDOMDocument;
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.HashMap;
-import java.util.HashSet;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
/**
* A participant to participate in refactorings that rename a package in an Android project.
@@ -78,13 +89,81 @@ import java.util.Set;
* </p>
*/
@SuppressWarnings("restriction")
-public class AndroidPackageRenameParticipant extends AndroidRenameParticipant {
+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;
- private boolean mIsPackage;
+ @Override
+ public String getName() {
+ return "Android Package Rename";
+ }
+
+ @Override
+ public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context)
+ throws OperationCanceledException {
+ 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;
+ }
- private Set<AndroidLayoutFileChanges> mFileChanges = new HashSet<AndroidLayoutFileChanges>();
@Override
public Change createChange(IProgressMonitor pm) throws CoreException,
@@ -92,50 +171,61 @@ public class AndroidPackageRenameParticipant extends AndroidRenameParticipant {
if (pm.isCanceled()) {
return null;
}
- if (!getArguments().getUpdateReferences())
+ 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();
- IJavaProject javaProject = (IJavaProject) mPackageFragment
- .getAncestor(IJavaElement.JAVA_PROJECT);
- IProject project = javaProject.getProject();
- IPath genPath = project.getFullPath().append(SdkConstants.FD_GEN_SOURCES);
+ 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();
- if (mAndroidManifest.exists()) {
- if (mAndroidElements.size() > 0 || mIsPackage) {
- getManifestDocument();
- Change change = new AndroidPackageRenameChange(mAndroidManifest, mManager,
- mDocument, mAndroidElements, mOldName, mNewName, mIsPackage);
- if (change != null) {
- result.add(change);
- }
- }
- if (mIsPackage) {
- Change genChange = getGenPackageChange(pm);
- if (genChange != null) {
- result.add(genChange);
- }
+
+ 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(result);
+
+ if (mRefactoringAppPackage) {
+ Change genChange = getGenPackageChange(pm);
+ if (genChange != null) {
+ result.add(genChange);
}
- // add layoutChange
- for (AndroidLayoutFileChanges fileChange : mFileChanges) {
- IFile file = fileChange.getFile();
- ITextFileBufferManager lManager = FileBuffers.getTextFileBufferManager();
- lManager.connect(file.getFullPath(), LocationKind.NORMALIZE,
- new NullProgressMonitor());
- ITextFileBuffer buffer = lManager.getTextFileBuffer(file.getFullPath(),
- LocationKind.NORMALIZE);
- IDocument lDocument = buffer.getDocument();
- Change layoutChange = new AndroidLayoutChange(file, lDocument, lManager,
- fileChange.getChanges());
- if (layoutChange != null) {
- result.add(layoutChange);
+
+ 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;
}
@@ -145,15 +235,15 @@ public class AndroidPackageRenameParticipant extends AndroidRenameParticipant {
* @param pm the progress monitor
*
* @return Android gen package text change
- * @throws CoreException
- * @throws OperationCanceledException
+ * @throws CoreException if an error happens
+ * @throws OperationCanceledException if the operation is canceled
*/
public Change getGenPackageChange(IProgressMonitor pm) throws CoreException,
OperationCanceledException {
- if (mIsPackage) {
+ if (mRefactoringAppPackage) {
IPackageFragment genJavaPackageFragment = getGenPackageFragment();
if (genJavaPackageFragment != null && genJavaPackageFragment.exists()) {
- return new RenamePackageChange(genJavaPackageFragment, mNewName, true);
+ return new RenamePackageChange(genJavaPackageFragment, mNewPackage, true);
}
}
return null;
@@ -161,7 +251,6 @@ public class AndroidPackageRenameParticipant extends AndroidRenameParticipant {
/**
* Return the gen package fragment
- *
*/
private IPackageFragment getGenPackageFragment() throws JavaModelException {
IJavaProject javaProject = (IJavaProject) mPackageFragment
@@ -170,7 +259,7 @@ public class AndroidPackageRenameParticipant extends AndroidRenameParticipant {
IProject project = javaProject.getProject();
IFolder genFolder = project.getFolder(SdkConstants.FD_GEN_SOURCES);
if (genFolder.exists()) {
- String javaPackagePath = mAppPackage.replace(".", "/");
+ String javaPackagePath = mAppPackage.replace('.', '/');
IPath genJavaPackagePath = genFolder.getFullPath().append(javaPackagePath);
IPackageFragment genPackageFragment = javaProject
.findPackageFragment(genJavaPackagePath);
@@ -180,123 +269,53 @@ public class AndroidPackageRenameParticipant extends AndroidRenameParticipant {
return null;
}
- @Override
- public String getName() {
- return "Android Package Rename";
+ /**
+ * 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;
}
- @Override
- protected boolean initialize(final Object element) {
- mIsPackage = false;
+ private void addManifestFileChanges(CompositeChange result) {
+ addXmlFileChanges(mManifestFile, result, true);
+ }
+
+ private void addLayoutFileChanges(CompositeChange result) {
try {
- if (element instanceof IPackageFragment) {
- mPackageFragment = (IPackageFragment) element;
- if (!mPackageFragment.containsJavaResources())
- return false;
- IJavaProject javaProject = (IJavaProject) mPackageFragment
- .getAncestor(IJavaElement.JAVA_PROJECT);
- IProject project = javaProject.getProject();
- IResource manifestResource = project.findMember(AdtConstants.WS_SEP
- + SdkConstants.FN_ANDROID_MANIFEST_XML);
+ // Update references in XML resource files
+ IFolder resFolder = mProject.getFolder(SdkConstants.FD_RESOURCES);
- if (manifestResource == null || !manifestResource.exists()
- || !(manifestResource instanceof IFile)) {
- RefactoringUtil.logInfo("Invalid or missing the "
- + SdkConstants.FN_ANDROID_MANIFEST_XML + " in the " + project.getName()
- + " project.");
- return false;
+ IResource[] folders = resFolder.members();
+ for (IResource folder : folders) {
+ String folderName = folder.getName();
+ ResourceFolderType folderType = ResourceFolderType.getFolderType(folderName);
+ if (folderType != ResourceFolderType.LAYOUT) {
+ continue;
}
- mAndroidManifest = (IFile) manifestResource;
- String packageName = mPackageFragment.getElementName();
- ManifestData manifestData;
- manifestData = AndroidManifestHelper.parseForData(mAndroidManifest);
- if (manifestData == null) {
- return false;
- }
- mAppPackage = manifestData.getPackage();
- mOldName = packageName;
- mNewName = getArguments().getNewName();
- if (mOldName == null || mNewName == null) {
- return false;
+ 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 (RefactoringUtil.isRefactorAppPackage()
- && mAppPackage != null
- && mAppPackage.equals(packageName)) {
- mIsPackage = true;
- }
- mAndroidElements = addAndroidElements();
-
- try {
- final IType type = javaProject.findType(SdkConstants.CLASS_VIEW);
- final HashSet<IType> elements = new HashSet<IType>();
- if (type != null) {
- ITypeHierarchy hierarchy = type.newTypeHierarchy(
- new NullProgressMonitor());
- IType[] allSubtypes = hierarchy.getAllSubtypes(type);
- for (IType subType : allSubtypes) {
- IResource resource = subType.getResource();
- // TODO: Handle library project downstream dependencies!
- if (resource != null && project.equals(resource.getProject())) {
- if (subType.getPackageFragment().equals(mPackageFragment)) {
- elements.add(subType);
- }
- }
+ if (SdkUtils.endsWith(fileName, DOT_XML)) {
+ addXmlFileChanges(file, result, false);
}
}
-
- List<String> views = new ArrayList<String>();
- for (IType elem : elements) {
- views.add(elem.getFullyQualifiedName());
- }
- if (views.size() > 0) {
- String[] classNames = views.toArray(new String[0]);
- addLayoutChanges(project, classNames);
- }
- } catch (CoreException e) {
- RefactoringUtil.log(e);
- }
-
- return mIsPackage || mAndroidElements.size() > 0 || mFileChanges.size() > 0;
- }
- } catch (JavaModelException ignore) {
- }
- return false;
- }
-
- /**
- * Adds layout changes for project
- *
- * @param project the Android project
- * @param classNames the layout classes
- */
- private void addLayoutChanges(IProject project, String[] classNames) {
- try {
- IFolder resFolder = project.getFolder(SdkConstants.FD_RESOURCES);
- IResource[] layoutMembers = resFolder.members();
- for (int j = 0; j < layoutMembers.length; j++) {
- IResource resource = layoutMembers[j];
- if (resource instanceof IFolder
- && resource.exists()
- && resource.getName().startsWith(SdkConstants.FD_RES_LAYOUT)) {
- IFolder layoutFolder = (IFolder) resource;
- IResource[] members = layoutFolder.members();
- for (int i = 0; i < members.length; i++) {
- IResource member = members[i];
- if ((member instanceof IFile)
- && member.exists()
- && member.getName().endsWith(".xml")) { //$NON-NLS-1$
- IFile file = (IFile) member;
- Set<AndroidLayoutChangeDescription> changes =
- parse(file, classNames);
- if (changes.size() > 0) {
- AndroidLayoutFileChanges fileChange =
- new AndroidLayoutFileChanges(file);
- fileChange.getChanges().addAll(changes);
- mFileChanges.add(fileChange);
- }
- }
- }
}
}
} catch (CoreException e) {
@@ -304,211 +323,164 @@ public class AndroidPackageRenameParticipant extends AndroidRenameParticipant {
}
}
- /**
- * Searches the layout file for classes
- *
- * @param file the Android layout file
- * @param classNames the layout classes
- */
- private Set<AndroidLayoutChangeDescription> parse(IFile file, String[] classNames) {
- Set<AndroidLayoutChangeDescription> changes =
- new HashSet<AndroidLayoutChangeDescription>();
- ITextFileBufferManager lManager = null;
+ private boolean addXmlFileChanges(IFile file, CompositeChange changes, boolean isManifest) {
+ IModelManager modelManager = StructuredModelManager.getModelManager();
+ IStructuredModel model = null;
try {
- lManager = FileBuffers.getTextFileBufferManager();
- lManager.connect(file.getFullPath(),
- LocationKind.NORMALIZE, new NullProgressMonitor());
- ITextFileBuffer buffer = lManager.getTextFileBuffer(file.getFullPath(),
- LocationKind.NORMALIZE);
- IDocument lDocument = buffer.getDocument();
- IStructuredModel model = null;
- try {
- model = StructuredModelManager.getModelManager().
- getExistingModelForRead(lDocument);
- if (model == null) {
- if (lDocument instanceof IStructuredDocument) {
- IStructuredDocument structuredDocument = (IStructuredDocument) lDocument;
- model = StructuredModelManager.getModelManager().getModelForRead(
- structuredDocument);
- }
- }
- if (model != null) {
- IDOMModel xmlModel = (IDOMModel) model;
- IDOMDocument xmlDoc = xmlModel.getDocument();
- NodeList nodes = xmlDoc.getElementsByTagName(SdkConstants.VIEW);
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- NamedNodeMap attributes = node.getAttributes();
- if (attributes != null) {
- Node attributeNode = attributes
- .getNamedItem(SdkConstants.ATTR_CLASS);
- if (attributeNode instanceof Attr) {
- Attr attribute = (Attr) attributeNode;
- String value = attribute.getValue();
- if (value != null) {
- for (int j = 0; j < classNames.length; j++) {
- String className = classNames[j];
- if (value.equals(className)) {
- String newClassName = getNewClassName(className);
- AndroidLayoutChangeDescription layoutChange =
- new AndroidLayoutChangeDescription(
- className, newClassName,
- AndroidLayoutChangeDescription.VIEW_TYPE);
- changes.add(layoutChange);
- }
- }
- }
- }
+ 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);
}
- }
- for (int j = 0; j < classNames.length; j++) {
- String className = classNames[j];
- nodes = xmlDoc.getElementsByTagName(className);
- for (int i = 0; i < nodes.getLength(); i++) {
- String newClassName = getNewClassName(className);
- AndroidLayoutChangeDescription layoutChange =
- new AndroidLayoutChangeDescription(
- className, newClassName,
- AndroidLayoutChangeDescription.STANDALONE_TYPE);
- changes.add(layoutChange);
+ 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);
}
}
- }
- } finally {
- if (model != null) {
- model.releaseFromRead();
+ } else {
+ return false;
}
}
- } catch (CoreException ignore) {
+ return true;
+ } catch (IOException e) {
+ AdtPlugin.log(e, null);
+ } catch (CoreException e) {
+ AdtPlugin.log(e, null);
} finally {
- if (lManager != null) {
- try {
- lManager.disconnect(file.getFullPath(), LocationKind.NORMALIZE,
- new NullProgressMonitor());
- } catch (CoreException ignore) {
- }
+ if (model != null) {
+ model.releaseFromRead();
}
}
- return changes;
- }
- /**
- * Returns the new class name
- *
- * @param className the class name
- * @return the new class name
- */
- private String getNewClassName(String className) {
- int lastDot = className.lastIndexOf("."); //$NON-NLS-1$
- if (lastDot < 0) {
- return mNewName;
- }
- String name = className.substring(lastDot, className.length());
- String newClassName = mNewName + name;
- return newClassName;
+ return false;
}
- /**
- * Returns the elements (activity, receiver, service ...)
- * which have to be renamed
- *
- * @return the android elements
- */
- private Map<String, String> addAndroidElements() {
- Map<String, String> androidElements = new HashMap<String, String>();
+ private boolean isInRenamedPackage(String fqcn) {
+ return fqcn.startsWith(mOldPackage)
+ && fqcn.length() > mOldPackage.length()
+ && fqcn.indexOf('.', mOldPackage.length() + 1) == -1;
+ }
- IDocument document;
- try {
- document = getManifestDocument();
- } catch (CoreException e) {
- RefactoringUtil.log(e);
- if (mManager != null) {
- try {
- mManager.disconnect(mAndroidManifest.getFullPath(), LocationKind.NORMALIZE,
- new NullProgressMonitor());
- } catch (CoreException e1) {
- RefactoringUtil.log(e1);
+ 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.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;
}
}
- document = null;
- return androidElements;
- }
-
- IStructuredModel model = null;
- try {
- model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
- if (model == null) {
- if (document instanceof IStructuredDocument) {
- IStructuredDocument structuredDocument = (IStructuredDocument) document;
- model = StructuredModelManager.getModelManager().getModelForRead(
- structuredDocument);
+ 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)));
+ }
}
}
- if (model != null) {
- IDOMModel xmlModel = (IDOMModel) model;
- IDOMDocument xmlDoc = xmlModel.getDocument();
- add(xmlDoc, androidElements, AndroidManifest.NODE_ACTIVITY,
- AndroidManifest.ATTRIBUTE_NAME);
- add(xmlDoc, androidElements, AndroidManifest.NODE_APPLICATION,
- AndroidManifest.ATTRIBUTE_NAME);
- add(xmlDoc, androidElements, AndroidManifest.NODE_PROVIDER,
- AndroidManifest.ATTRIBUTE_NAME);
- add(xmlDoc, androidElements, AndroidManifest.NODE_RECEIVER,
- AndroidManifest.ATTRIBUTE_NAME);
- add(xmlDoc, androidElements, AndroidManifest.NODE_SERVICE,
- AndroidManifest.ATTRIBUTE_NAME);
+ }
+
+ 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);
}
- } finally {
- if (model != null) {
- model.releaseFromRead();
+ }
+ }
+
+ 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));
+ }
}
}
- return androidElements;
- }
+ 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;
+ }
- /**
- * Adds the element (activity, receiver, service ...) to the map
- *
- * @param xmlDoc the document
- * @param androidElements the map
- * @param element the element
- */
- private void add(IDOMDocument xmlDoc, Map<String, String> androidElements, String element,
- String argument) {
- NodeList nodes = xmlDoc.getElementsByTagName(element);
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- NamedNodeMap attributes = node.getAttributes();
- if (attributes != null) {
- Attr attribute = RefactoringUtil.findAndroidAttributes(attributes, argument);
- if (attribute != null) {
- String value = attribute.getValue();
- if (value != null) {
- String fullName = AndroidManifest.combinePackageAndClassName(mAppPackage,
- value);
- if (RefactoringUtil.isRefactorAppPackage()) {
- if (fullName != null && fullName.startsWith(mAppPackage)) {
- boolean startWithDot = (value.charAt(0) == '.');
- boolean hasDot = (value.indexOf('.') != -1);
- if (!startWithDot && hasDot) {
- androidElements.put(element, value);
- }
- }
- } else {
- if (fullName != null) {
- String currentPackage = mPackageFragment.getElementName();
- if (fullName.lastIndexOf('.') == currentPackage.length()
- && fullName.startsWith(currentPackage)) {
- androidElements.put(element, value);
- }
- }
+ 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/AndroidRenameParticipant.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidRenameParticipant.java
deleted file mode 100644
index dca43a110..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidRenameParticipant.java
+++ /dev/null
@@ -1,86 +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.filebuffers.FileBuffers;
-import org.eclipse.core.filebuffers.ITextFileBuffer;
-import org.eclipse.core.filebuffers.ITextFileBufferManager;
-import org.eclipse.core.filebuffers.LocationKind;
-import org.eclipse.core.resources.IFile;
-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.jface.text.IDocument;
-import org.eclipse.ltk.core.refactoring.RefactoringStatus;
-import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
-import org.eclipse.ltk.core.refactoring.participants.RenameParticipant;
-
-import java.util.Map;
-
-/**
- * The abstract class for Rename Package and Rename type participants
- *
- */
-public abstract class AndroidRenameParticipant extends RenameParticipant {
-
- protected IFile mAndroidManifest;
-
- protected ITextFileBufferManager mManager;
-
- protected String mOldName;
-
- protected String mNewName;
-
- protected IDocument mDocument;
-
- protected String mAppPackage;
-
- protected Map<String, String> mAndroidElements;
-
- @Override
- public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context)
- throws OperationCanceledException {
- return new RefactoringStatus();
- }
-
- /**
- * @return the document for the {@link #mAndroidManifest}
- * @throws CoreException
- */
- public IDocument getManifestDocument() throws CoreException {
- if (mDocument == null) {
- mManager = FileBuffers.getTextFileBufferManager();
- mManager.connect(mAndroidManifest.getFullPath(),
- LocationKind.NORMALIZE,
- new NullProgressMonitor());
- ITextFileBuffer buffer = mManager.getTextFileBuffer(
- mAndroidManifest.getFullPath(),
- LocationKind.NORMALIZE);
- mDocument = buffer.getDocument();
- }
- return mDocument;
- }
-
- /**
- * @return the android manifest file
- */
- public IFile getAndroidManifest() {
- return mAndroidManifest;
- }
-
-}
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
index 287139a81..26ae8d0f3 100644
--- 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
@@ -16,55 +16,60 @@
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.refactorings.changes.AndroidLayoutChange;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidLayoutChangeDescription;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidLayoutFileChanges;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidTypeMoveChange;
import com.android.resources.ResourceFolderType;
-import com.android.xml.AndroidManifest;
+import com.android.utils.SdkUtils;
-import org.eclipse.core.filebuffers.FileBuffers;
-import org.eclipse.core.filebuffers.ITextFileBuffer;
-import org.eclipse.core.filebuffers.ITextFileBufferManager;
-import org.eclipse.core.filebuffers.LocationKind;
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.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jface.text.IDocument;
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.IDOMDocument;
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.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
/**
* A participant to participate in refactorings that move a type in an Android project.
@@ -79,21 +84,16 @@ import java.util.Set;
@SuppressWarnings("restriction")
public class AndroidTypeMoveParticipant extends MoveParticipant {
- protected IFile mAndroidManifest;
-
- protected ITextFileBufferManager mManager;
-
- protected String mOldName;
-
- protected String mNewName;
-
- protected IDocument mDocument;
-
- protected String mJavaPackage;
-
- protected Map<String, String> mAndroidElements;
+ private IProject mProject;
+ protected IFile mManifestFile;
+ protected String mOldFqcn;
+ protected String mNewFqcn;
+ protected String mAppPackage;
- private Set<AndroidLayoutFileChanges> mFileChanges = new HashSet<AndroidLayoutFileChanges>();
+ @Override
+ public String getName() {
+ return "Android Type Move";
+ }
@Override
public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context)
@@ -102,107 +102,40 @@ public class AndroidTypeMoveParticipant extends MoveParticipant {
}
@Override
- public Change createChange(IProgressMonitor pm) throws CoreException,
- OperationCanceledException {
- if (pm.isCanceled()) {
- return null;
- }
- if (!getArguments().getUpdateReferences())
- return null;
- CompositeChange result = new CompositeChange(getName());
- if (mAndroidManifest.exists()) {
- if (mAndroidElements.size() > 0) {
- getDocument();
- Change change = new AndroidTypeMoveChange(mAndroidManifest, mManager, mDocument,
- mAndroidElements, mNewName, mOldName);
- if (change != null) {
- result.add(change);
- }
- }
-
- for (AndroidLayoutFileChanges fileChange : mFileChanges) {
- IFile file = fileChange.getFile();
- ITextFileBufferManager lManager = FileBuffers.getTextFileBufferManager();
- lManager.connect(file.getFullPath(), LocationKind.NORMALIZE,
- new NullProgressMonitor());
- ITextFileBuffer buffer = lManager.getTextFileBuffer(file.getFullPath(),
- LocationKind.NORMALIZE);
- IDocument lDocument = buffer.getDocument();
- Change layoutChange = new AndroidLayoutChange(file, lDocument, lManager,
- fileChange.getChanges());
- if (layoutChange != null) {
- result.add(layoutChange);
- }
- }
- }
- return (result.getChildren().length == 0) ? null : result;
-
- }
-
- /**
- * @return the document
- * @throws CoreException
- */
- public IDocument getDocument() throws CoreException {
- if (mDocument == null) {
- mManager = FileBuffers.getTextFileBufferManager();
- mManager.connect(mAndroidManifest.getFullPath(), LocationKind.NORMALIZE,
- new NullProgressMonitor());
- ITextFileBuffer buffer = mManager.getTextFileBuffer(mAndroidManifest.getFullPath(),
- LocationKind.NORMALIZE);
- mDocument = buffer.getDocument();
- }
- return mDocument;
- }
-
- /**
- * @return the android manifest file
- */
- public IFile getAndroidManifest() {
- return mAndroidManifest;
- }
-
- @Override
- public String getName() {
- return "Android Type Move";
- }
-
- @Override
protected boolean initialize(Object element) {
-
if (element instanceof IType) {
IType type = (IType) element;
IJavaProject javaProject = (IJavaProject) type.getAncestor(IJavaElement.JAVA_PROJECT);
- IProject project = javaProject.getProject();
- IResource manifestResource = project.findMember(AdtConstants.WS_SEP
+ 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 " + project.getName()
+ + SdkConstants.FN_ANDROID_MANIFEST_XML + " in the " + mProject.getName()
+ " project.");
return false;
}
- mAndroidManifest = (IFile) manifestResource;
+ mManifestFile = (IFile) manifestResource;
ManifestData manifestData;
- manifestData = AndroidManifestHelper.parseForData(mAndroidManifest);
+ manifestData = AndroidManifestHelper.parseForData(mManifestFile);
if (manifestData == null) {
return false;
}
- mJavaPackage = manifestData.getPackage();
- mOldName = type.getFullyQualifiedName();
+ mAppPackage = manifestData.getPackage();
+ mOldFqcn = type.getFullyQualifiedName();
Object destination = getArguments().getDestination();
if (destination instanceof IPackageFragment) {
IPackageFragment packageFragment = (IPackageFragment) destination;
- mNewName = packageFragment.getElementName() + "." + type.getElementName();
+ 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)) {
- mNewName = fragment.getElementName() + "." + type.getElementName();
+ mNewFqcn = fragment.getElementName() + '.' + type.getElementName();
break;
}
}
@@ -210,60 +143,62 @@ public class AndroidTypeMoveParticipant extends MoveParticipant {
// pass
}
}
- if (mOldName == null || mNewName == null) {
- return false;
- }
- mAndroidElements = addAndroidElements();
- try {
- ITypeHierarchy typeHierarchy = type.newSupertypeHierarchy(null);
- if (typeHierarchy == null) {
- return false;
- }
- IType[] superTypes = typeHierarchy.getAllSuperclasses(type);
- for (int i = 0; i < superTypes.length; i++) {
- IType superType = superTypes[i];
- String className = superType.getFullyQualifiedName();
- if (className.equals(SdkConstants.CLASS_VIEW)) {
- addLayoutChanges(project, type.getFullyQualifiedName());
- break;
- }
- }
- } catch (JavaModelException ignore) {
- }
- return mAndroidElements.size() > 0 || mFileChanges.size() > 0;
+ return mOldFqcn != null && mNewFqcn != null;
}
+
return false;
}
- /**
- * Adds layout changes for project
- *
- * @param project the Android project
- * @param className the layout classes
- *
- */
- private void addLayoutChanges(IProject project, String className) {
+ @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(result);
+
+ return (result.getChildren().length == 0) ? null : result;
+ }
+
+ private void addManifestFileChanges(CompositeChange result) {
+ addXmlFileChanges(mManifestFile, result, true);
+ }
+
+ private void addLayoutFileChanges(CompositeChange result) {
try {
- IFolder resFolder = project.getFolder(SdkConstants.FD_RESOURCES);
- for (IResource folder : resFolder.members()) {
- if (!(folder instanceof IFolder)) {
+ // Update references in XML resource files
+ IFolder resFolder = mProject.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;
}
- ResourceFolderType type = ResourceFolderType.getFolderType(folder.getName());
- if (type != ResourceFolderType.LAYOUT) {
+ if (!(folder instanceof IFolder)) {
continue;
}
- IFolder layoutFolder = (IFolder) folder;
- IResource[] members = layoutFolder.members();
- for (int i = 0; i < members.length; i++) {
- IResource member = members[i];
+ 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;
- Set<AndroidLayoutChangeDescription> changes = parse(file, className);
- if (changes.size() > 0) {
- AndroidLayoutFileChanges fileChange = new AndroidLayoutFileChanges(file);
- fileChange.getChanges().addAll(changes);
- mFileChanges.add(fileChange);
+ String fileName = member.getName();
+
+ if (SdkUtils.endsWith(fileName, DOT_XML)) {
+ addXmlFileChanges(file, result, false);
}
}
}
@@ -273,167 +208,139 @@ public class AndroidTypeMoveParticipant extends MoveParticipant {
}
}
- /**
- * Searches the layout file for classes
- *
- * @param file the Android layout file
- * @param className the layout classes
- *
- */
- private Set<AndroidLayoutChangeDescription> parse(IFile file, String className) {
- Set<AndroidLayoutChangeDescription> changes = new HashSet<AndroidLayoutChangeDescription>();
- ITextFileBufferManager lManager = null;
+ private boolean addXmlFileChanges(IFile file, CompositeChange changes, boolean isManifest) {
+ IModelManager modelManager = StructuredModelManager.getModelManager();
+ IStructuredModel model = null;
try {
- lManager = FileBuffers.getTextFileBufferManager();
- lManager.connect(file.getFullPath(), LocationKind.NORMALIZE, new NullProgressMonitor());
- ITextFileBuffer buffer = lManager.getTextFileBuffer(file.getFullPath(),
- LocationKind.NORMALIZE);
- IDocument lDocument = buffer.getDocument();
- IStructuredModel model = null;
- try {
- model = StructuredModelManager.getModelManager().getExistingModelForRead(lDocument);
- if (model == null) {
- if (lDocument instanceof IStructuredDocument) {
- IStructuredDocument structuredDocument = (IStructuredDocument) lDocument;
- model = StructuredModelManager.getModelManager().getModelForRead(
- structuredDocument);
- }
- }
- if (model != null) {
- IDOMModel xmlModel = (IDOMModel) model;
- IDOMDocument xmlDoc = xmlModel.getDocument();
- NodeList nodes = xmlDoc.getElementsByTagName(SdkConstants.VIEW);
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- NamedNodeMap attributes = node.getAttributes();
- if (attributes != null) {
- Node attributeNode =
- attributes.getNamedItem(SdkConstants.ATTR_CLASS);
- if (attributeNode instanceof Attr) {
- Attr attribute = (Attr) attributeNode;
- String value = attribute.getValue();
- if (value != null && value.equals(className)) {
- AndroidLayoutChangeDescription layoutChange =
- new AndroidLayoutChangeDescription(className, mNewName,
- AndroidLayoutChangeDescription.VIEW_TYPE);
- changes.add(layoutChange);
- }
- }
+ 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);
}
}
- nodes = xmlDoc.getElementsByTagName(className);
- for (int i = 0; i < nodes.getLength(); i++) {
- AndroidLayoutChangeDescription layoutChange =
- new AndroidLayoutChangeDescription(className, mNewName,
- AndroidLayoutChangeDescription.STANDALONE_TYPE);
- changes.add(layoutChange);
- }
- }
- } finally {
- if (model != null) {
- model.releaseFromRead();
+ } else {
+ return false;
}
}
- } catch (CoreException ignore) {
+ return true;
+ } catch (IOException e) {
+ AdtPlugin.log(e, null);
+ } catch (CoreException e) {
+ AdtPlugin.log(e, null);
} finally {
- if (lManager != null) {
- try {
- lManager.disconnect(file.getFullPath(), LocationKind.NORMALIZE,
- new NullProgressMonitor());
- } catch (CoreException ignore) {
- }
+ if (model != null) {
+ model.releaseFromRead();
}
}
- return changes;
- }
- /**
- * Returns the elements (activity, receiver, service ...)
- * which have to be renamed
- *
- * @return the android elements
- */
- private Map<String, String> addAndroidElements() {
- Map<String, String> androidElements = new HashMap<String, String>();
+ return false;
+ }
- IDocument document;
- try {
- document = getDocument();
- } catch (CoreException e) {
- RefactoringUtil.log(e);
- if (mManager != null) {
- try {
- mManager.disconnect(mAndroidManifest.getFullPath(), LocationKind.NORMALIZE,
- new NullProgressMonitor());
- } catch (CoreException e1) {
- RefactoringUtil.log(e1);
- }
+ 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));
}
- document = null;
- return androidElements;
- }
-
- IStructuredModel model = null;
- try {
- model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
- if (model == null) {
- if (document instanceof IStructuredDocument) {
- IStructuredDocument structuredDocument = (IStructuredDocument) document;
- model = StructuredModelManager.getModelManager().getModelForRead(
- structuredDocument);
+ } 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));
}
}
- if (model != null) {
- IDOMModel xmlModel = (IDOMModel) model;
- IDOMDocument xmlDoc = xmlModel.getDocument();
- add(xmlDoc, androidElements, AndroidManifest.NODE_ACTIVITY,
- AndroidManifest.ATTRIBUTE_NAME);
- add(xmlDoc, androidElements, AndroidManifest.NODE_APPLICATION,
- AndroidManifest.ATTRIBUTE_NAME);
- add(xmlDoc, androidElements, AndroidManifest.NODE_PROVIDER,
- AndroidManifest.ATTRIBUTE_NAME);
- add(xmlDoc, androidElements, AndroidManifest.NODE_RECEIVER,
- AndroidManifest.ATTRIBUTE_NAME);
- add(xmlDoc, androidElements, AndroidManifest.NODE_SERVICE,
- AndroidManifest.ATTRIBUTE_NAME);
+ } else if (tag.equals(VIEW_FRAGMENT)) {
+ Attr 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));
+ }
}
- } finally {
- if (model != null) {
- model.releaseFromRead();
+ } 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));
+ }
}
}
- return androidElements;
+ 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);
+ }
+ }
}
- /**
- * Adds the element (activity, receiver, service ...) to the map
- *
- * @param xmlDoc the document
- * @param androidElements the map
- * @param element the element
- */
- private void add(IDOMDocument xmlDoc, Map<String, String> androidElements, String element,
- String argument) {
- NodeList nodes = xmlDoc.getElementsByTagName(element);
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- NamedNodeMap attributes = node.getAttributes();
- if (attributes != null) {
- Attr attribute = RefactoringUtil.findAndroidAttributes(attributes, argument);
- if (attribute != null) {
- String value = attribute.getValue();
- if (value != null) {
- String fullName = AndroidManifest.combinePackageAndClassName(mJavaPackage,
- value);
- if (fullName != null && fullName.equals(mOldName)) {
- androidElements.put(element, value);
- }
+ 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
index 227266d0e..f454c685e 100644
--- 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
@@ -16,54 +16,61 @@
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.refactorings.changes.AndroidLayoutChange;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidLayoutChangeDescription;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidLayoutFileChanges;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidTypeRenameChange;
import com.android.resources.ResourceFolderType;
-import com.android.xml.AndroidManifest;
+import com.android.utils.SdkUtils;
-import org.eclipse.core.filebuffers.FileBuffers;
-import org.eclipse.core.filebuffers.ITextFileBuffer;
-import org.eclipse.core.filebuffers.ITextFileBufferManager;
-import org.eclipse.core.filebuffers.LocationKind;
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.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.ITypeHierarchy;
-import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.corext.refactoring.rename.RenameCompilationUnitProcessor;
import org.eclipse.jdt.internal.corext.refactoring.rename.RenameTypeProcessor;
-import org.eclipse.jface.text.IDocument;
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.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.IDOMDocument;
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.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
/**
* A participant to participate in refactorings that rename a type in an Android project.
@@ -76,81 +83,32 @@ import java.util.Set;
* <code>org.eclipse.ltk.core.refactoring.participants.RenameParticipant</code>.
*/
@SuppressWarnings("restriction")
-public class AndroidTypeRenameParticipant extends AndroidRenameParticipant {
-
- private Set<AndroidLayoutFileChanges> mFileChanges = new HashSet<AndroidLayoutFileChanges>();
-
- private String mLayoutNewName;
+public class AndroidTypeRenameParticipant extends RenameParticipant {
+ private IProject mProject;
+ private IFile mManifestFile;
+ private String mOldFqcn;
+ private String mNewFqcn;
+ private String mOldDottedName;
+ private String mNewDottedName;
@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());
- if (mAndroidManifest.exists()) {
- if (mAndroidElements.size() > 0) {
- getManifestDocument();
- Change change = new AndroidTypeRenameChange(mAndroidManifest, mManager, mDocument,
- mAndroidElements, mOldName, mNewName);
- if (change != null) {
- result.add(change);
- }
- }
- // add layoutChange
- for (AndroidLayoutFileChanges fileChange : mFileChanges) {
- IFile file = fileChange.getFile();
- ITextFileBufferManager lManager = FileBuffers.getTextFileBufferManager();
- lManager.connect(file.getFullPath(), LocationKind.NORMALIZE,
- new NullProgressMonitor());
- ITextFileBuffer buffer = lManager.getTextFileBuffer(file.getFullPath(),
- LocationKind.NORMALIZE);
- IDocument lDocument = buffer.getDocument();
- Change layoutChange = new AndroidLayoutChange(file, lDocument, lManager,
- fileChange.getChanges());
- if (layoutChange != null) {
- result.add(layoutChange);
- }
- }
- }
- return (result.getChildren().length == 0) ? null : result;
-
+ public String getName() {
+ return "Android Type Rename";
}
@Override
- public String getName() {
- return "Android Type Rename";
+ 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);
- IProject project = javaProject.getProject();
- IResource manifestResource = project.findMember(AdtConstants.WS_SEP
+ mProject = javaProject.getProject();
+ IResource manifestResource = mProject.findMember(AdtConstants.WS_SEP
+ SdkConstants.FN_ANDROID_MANIFEST_XML);
if (manifestResource == null || !manifestResource.exists()
@@ -158,82 +116,102 @@ public class AndroidTypeRenameParticipant extends AndroidRenameParticipant {
RefactoringUtil.logInfo(
String.format("Invalid or missing file %1$s in project %2$s",
SdkConstants.FN_ANDROID_MANIFEST_XML,
- project.getName()));
+ mProject.getName()));
return false;
}
- mAndroidManifest = (IFile) manifestResource;
+ mManifestFile = (IFile) manifestResource;
ManifestData manifestData;
- manifestData = AndroidManifestHelper.parseForData(mAndroidManifest);
+ manifestData = AndroidManifestHelper.parseForData(mManifestFile);
if (manifestData == null) {
return false;
}
- mAppPackage = manifestData.getPackage();
- mOldName = type.getFullyQualifiedName();
+ mOldDottedName = '.' + type.getElementName();
+ mOldFqcn = type.getFullyQualifiedName();
String packageName = type.getPackageFragment().getElementName();
- mNewName = getArguments().getNewName();
+ mNewDottedName = '.' + getArguments().getNewName();
if (packageName != null) {
- mLayoutNewName = packageName + "." + getArguments().getNewName(); //$NON-NLS-1$
+ mNewFqcn = packageName + mNewDottedName;
} else {
- mLayoutNewName = getArguments().getNewName();
+ mNewFqcn = getArguments().getNewName();
}
- if (mOldName == null || mNewName == null) {
+ if (mOldFqcn == null || mOldFqcn == null) {
return false;
}
- if (!RefactoringUtil.isRefactorAppPackage() && mNewName.indexOf(".") == -1) { //$NON-NLS-1$
- mNewName = packageName + "." + mNewName; //$NON-NLS-1$
+ if (!RefactoringUtil.isRefactorAppPackage() && mNewFqcn.indexOf('.') == -1) {
+ mNewFqcn = packageName + mNewDottedName;
}
- mAndroidElements = addAndroidElements();
- try {
- ITypeHierarchy typeHierarchy = type.newSupertypeHierarchy(null);
- if (typeHierarchy == null) {
- return false;
- }
- IType[] superTypes = typeHierarchy.getAllSuperclasses(type);
- for (int i = 0; i < superTypes.length; i++) {
- IType superType = superTypes[i];
- String className = superType.getFullyQualifiedName();
- if (className.equals(SdkConstants.CLASS_VIEW)) {
- addLayoutChanges(project, type.getFullyQualifiedName());
- break;
- }
+ 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;
}
- } catch (JavaModelException ignore) {
}
-
- return mAndroidElements.size() > 0 || mFileChanges.size() > 0;
}
- return false;
+
+ CompositeChange result = new CompositeChange(getName());
+
+ // Only show the children in the refactoring preview dialog
+ result.markAsSynthetic();
+
+ addManifestFileChanges(result);
+ addLayoutFileChanges(result);
+
+ return (result.getChildren().length == 0) ? null : result;
+ }
+
+ private void addManifestFileChanges(CompositeChange result) {
+ addXmlFileChanges(mManifestFile, result, true);
}
- /**
- * Adds layout changes for project
- *
- * @param project the Android project
- * @param className the layout classes
- *
- */
- private void addLayoutChanges(IProject project, String className) {
+ private void addLayoutFileChanges(CompositeChange result) {
try {
- IFolder resFolder = project.getFolder(SdkConstants.FD_RESOURCES);
- for (IResource folder : resFolder.members()) {
- if (!(folder instanceof IFolder)) {
+ // Update references in XML resource files
+ IFolder resFolder = mProject.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;
}
- ResourceFolderType type = ResourceFolderType.getFolderType(folder.getName());
- if (type != ResourceFolderType.LAYOUT) {
+ if (!(folder instanceof IFolder)) {
continue;
}
- IFolder layoutFolder = (IFolder) folder;
- IResource[] members = layoutFolder.members();
- for (int i = 0; i < members.length; i++) {
- IResource member = members[i];
+ 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;
- Set<AndroidLayoutChangeDescription> changes = parse(file, className);
- if (changes.size() > 0) {
- AndroidLayoutFileChanges fileChange = new AndroidLayoutFileChanges(file);
- fileChange.getChanges().addAll(changes);
- mFileChanges.add(fileChange);
+ String fileName = member.getName();
+
+ if (SdkUtils.endsWith(fileName, DOT_XML)) {
+ addXmlFileChanges(file, result, false);
}
}
}
@@ -243,172 +221,143 @@ public class AndroidTypeRenameParticipant extends AndroidRenameParticipant {
}
}
- /**
- * Searches the layout file for classes
- *
- * @param file the Android layout file
- * @param className the layout classes
- *
- */
- private Set<AndroidLayoutChangeDescription> parse(IFile file, String className) {
- Set<AndroidLayoutChangeDescription> changes = new HashSet<AndroidLayoutChangeDescription>();
- ITextFileBufferManager lManager = null;
+ private boolean addXmlFileChanges(IFile file, CompositeChange changes, boolean isManifest) {
+ IModelManager modelManager = StructuredModelManager.getModelManager();
+ IStructuredModel model = null;
try {
- lManager = FileBuffers.getTextFileBufferManager();
- lManager.connect(file.getFullPath(), LocationKind.NORMALIZE, new NullProgressMonitor());
- ITextFileBuffer buffer = lManager.getTextFileBuffer(file.getFullPath(),
- LocationKind.NORMALIZE);
- IDocument lDocument = buffer.getDocument();
- IStructuredModel model = null;
- try {
- model = StructuredModelManager.getModelManager().getExistingModelForRead(lDocument);
- if (model == null) {
- if (lDocument instanceof IStructuredDocument) {
- IStructuredDocument structuredDocument = (IStructuredDocument) lDocument;
- model = StructuredModelManager.getModelManager().getModelForRead(
- structuredDocument);
- }
- }
- if (model != null) {
- IDOMModel xmlModel = (IDOMModel) model;
- IDOMDocument xmlDoc = xmlModel.getDocument();
- NodeList nodes = xmlDoc.getElementsByTagName(SdkConstants.VIEW);
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- NamedNodeMap attributes = node.getAttributes();
- if (attributes != null) {
- Node attributeNode =
- attributes.getNamedItem(SdkConstants.ATTR_CLASS);
- if (attributeNode instanceof Attr) {
- Attr attribute = (Attr) attributeNode;
- String value = attribute.getValue();
- if (value != null && value.equals(className)) {
- AndroidLayoutChangeDescription layoutChange =
- new AndroidLayoutChangeDescription(className, mLayoutNewName,
- AndroidLayoutChangeDescription.VIEW_TYPE);
- changes.add(layoutChange);
- }
- }
+ 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);
}
}
- nodes = xmlDoc.getElementsByTagName(className);
- for (int i = 0; i < nodes.getLength(); i++) {
- AndroidLayoutChangeDescription layoutChange =
- new AndroidLayoutChangeDescription(className, mLayoutNewName,
- AndroidLayoutChangeDescription.STANDALONE_TYPE);
- changes.add(layoutChange);
- }
- }
- } finally {
- if (model != null) {
- model.releaseFromRead();
+ } else {
+ return false;
}
}
- } catch (CoreException ignore) {
+ return true;
+ } catch (IOException e) {
+ AdtPlugin.log(e, null);
+ } catch (CoreException e) {
+ AdtPlugin.log(e, null);
} finally {
- if (lManager != null) {
- try {
- lManager.disconnect(file.getFullPath(),
- LocationKind.NORMALIZE,
- new NullProgressMonitor());
- } catch (CoreException ignore) {
- }
+ if (model != null) {
+ model.releaseFromRead();
}
}
- return changes;
- }
- /**
- * Returns the elements (activity, receiver, service ...)
- * which have to be renamed
- *
- * @return the android elements
- *
- */
- private Map<String, String> addAndroidElements() {
- Map<String, String> androidElements = new HashMap<String, String>();
+ return false;
+ }
- IDocument document;
- try {
- document = getManifestDocument();
- } catch (CoreException e) {
- RefactoringUtil.log(e);
- if (mManager != null) {
- try {
- mManager.disconnect(mAndroidManifest.getFullPath(),
- LocationKind.NORMALIZE,
- new NullProgressMonitor());
- } catch (CoreException e1) {
- RefactoringUtil.log(e1);
- }
+ 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));
}
- document = null;
- return androidElements;
- }
-
- IStructuredModel model = null;
- try {
- model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
- if (model == null) {
- if (document instanceof IStructuredDocument) {
- IStructuredDocument structuredDocument = (IStructuredDocument) document;
- model = StructuredModelManager.getModelManager().getModelForRead(
- structuredDocument);
+ } 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));
}
}
- if (model != null) {
- IDOMModel xmlModel = (IDOMModel) model;
- IDOMDocument xmlDoc = xmlModel.getDocument();
- add(xmlDoc, androidElements, AndroidManifest.NODE_ACTIVITY,
- AndroidManifest.ATTRIBUTE_NAME);
- add(xmlDoc, androidElements, AndroidManifest.NODE_APPLICATION,
- AndroidManifest.ATTRIBUTE_NAME);
- add(xmlDoc, androidElements, AndroidManifest.NODE_PROVIDER,
- AndroidManifest.ATTRIBUTE_NAME);
- add(xmlDoc, androidElements, AndroidManifest.NODE_RECEIVER,
- AndroidManifest.ATTRIBUTE_NAME);
- add(xmlDoc, androidElements, AndroidManifest.NODE_SERVICE,
- AndroidManifest.ATTRIBUTE_NAME);
+ } else if (tag.equals(VIEW_FRAGMENT)) {
+ Attr 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));
+ }
}
- } finally {
- if (model != null) {
- model.releaseFromRead();
+ } 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));
+ }
}
}
- return androidElements;
- }
-
- /**
- * (non-Javadoc) Adds the element (activity, receiver, service ...) to the map
- *
- * @param xmlDoc the document
- * @param androidElements the map
- * @param element the element
- */
- private void add(IDOMDocument xmlDoc, Map<String, String> androidElements, String element,
- String argument) {
- NodeList nodes = xmlDoc.getElementsByTagName(element);
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- NamedNodeMap attributes = node.getAttributes();
- if (attributes != null) {
- Attr attribute = RefactoringUtil.findAndroidAttributes(attributes, argument);
- if (attribute != null) {
- String value = attribute.getValue();
- if (value != null) {
- String fullName = AndroidManifest.combinePackageAndClassName(mAppPackage,
- value);
- if (fullName != null && fullName.equals(mOldName)) {
- androidElements.put(element, value);
- }
- }
- }
+ 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.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/RefactoringUtil.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringUtil.java
index e48a6852a..41551a4a0 100644
--- 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
@@ -16,17 +16,25 @@
package com.android.ide.eclipse.adt.internal.refactorings.core;
-import com.android.SdkConstants;
+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.ide.eclipse.adt.AdtPlugin;
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.NamedNodeMap;
-import org.w3c.dom.Node;
+import org.w3c.dom.Element;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@@ -74,43 +82,6 @@ public class RefactoringUtil {
}
/**
- * Finds attribute by name in android namespace
- *
- * @param attributes the attributes collection
- * @param localName the local part of the qualified name
- *
- * @return the first attribute with this name in android namespace
- */
- public static Attr findAndroidAttributes(final NamedNodeMap attributes,
- final String localName) {
- Attr attribute = null;
- for (int j = 0; j < attributes.getLength(); j++) {
- Node attNode = attributes.item(j);
- if (attNode instanceof Attr) {
- Attr attr = (Attr) attNode;
- String name = attr.getLocalName();
- String namespace = attr.getNamespaceURI();
- if (SdkConstants.NS_RESOURCES.equals(namespace)
- && name != null
- && name.equals(localName)) {
- attribute = attr;
- break;
- }
- }
- }
- return attribute;
- }
-
- /**
- * Logs the error message
- *
- * @param message the message
- */
- public static void logError(String message) {
- AdtPlugin.log(IStatus.ERROR, AdtPlugin.PLUGIN_ID, message);
- }
-
- /**
* Logs the info message
*
* @param message the message
@@ -143,4 +114,86 @@ public class RefactoringUtil {
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.
+ * <p>
+ * TODO: Move to {@link RefactoringUtil}
+ *
+ * @param attribute the manifest attribute
+ * @return true if this attribute can describe a class
+ */
+ public static boolean isManifestClassAttribute(@NonNull Attr attribute) {
+ String name = attribute.getLocalName();
+ if (name == null) {
+ return false;
+ }
+
+ if (name.equals(ATTR_NAME)
+ || 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(attribute.getNamespaceURI());
+ }
+
+ return false;
+ }
}
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
index 2b0d5d7c7..8bd0e13aa 100644
--- 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
@@ -30,6 +30,7 @@ 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;
@@ -58,8 +59,6 @@ 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.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocument;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
@@ -522,24 +521,6 @@ public class RenameResourceParticipant extends RenameParticipant {
return false;
}
- private int getAttributeValueRangeStart(Attr attr, IDocument document) {
- IndexedRegion region = (IndexedRegion) attr;
- int potentialStart = attr.getName().length() + 2; // + 2: add ="
- String text;
- try {
- text = document.get(region.getStartOffset(), region.getLength());
- } 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;
- }
- }
-
private void addReplacements(
@NonNull List<TextEdit> edits,
@NonNull Element element,
@@ -558,7 +539,7 @@ public class RenameResourceParticipant extends RenameParticipant {
|| mType.getName().equals(element.getAttribute(ATTR_TYPE))))) {
Attr nameNode = element.getAttributeNode(ATTR_NAME);
if (nameNode != null && nameNode.getValue().equals(mOldName)) {
- int start = getAttributeValueRangeStart(nameNode, document);
+ int start = RefactoringUtil.getAttributeValueRangeStart(nameNode, document);
if (start != -1) {
int end = start + mOldName.length();
edits.add(new ReplaceEdit(start, end - start, mNewName));
@@ -575,6 +556,15 @@ public class RenameResourceParticipant extends RenameParticipant {
// 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;
}
@@ -606,7 +596,7 @@ public class RenameResourceParticipant extends RenameParticipant {
int end = region.getEndOffset();
edits.add(new ReplaceEdit(start, end - start, ""));
} else {
- int start = getAttributeValueRangeStart(attr, document);
+ int start = RefactoringUtil.getAttributeValueRangeStart(attr, document);
if (start != -1) {
int end = start + match.length();
edits.add(new ReplaceEdit(start, end - start, matchedValue));
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipantTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipantTest.java
index ec9d32409..a074146e4 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipantTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipantTest.java
@@ -49,10 +49,19 @@ public class AndroidPackageRenameParticipantTest extends RefactoringTestBase {
" +\n" +
"\n" +
"\n" +
+ "* activity_main.xml - /testRefactor1/res/layout/activity_main.xml\n" +
+ " @@ -33 +33\n" +
+ " - <fragment android:name=\"com.example.refactoringtest.MyFragment\"/>\n" +
+ " + <fragment android:name=\"my.pkg.name.MyFragment\"/>\n" +
+ "\n" +
+ "\n" +
"* AndroidManifest.xml - /testRefactor1/AndroidManifest.xml\n" +
" @@ -16 +16\n" +
" - android:name=\"com.example.refactoringtest.MainActivity\"\n" +
- " + android:name=\"my.pkg.name.MainActivity\"");
+ " + android:name=\"my.pkg.name.MainActivity\"\n" +
+ " @@ -25 +25\n" +
+ " - android:name=\".MainActivity2\"\n" +
+ " + android:name=\"my.pkg.name.MainActivity2\"");
}
public void testRefactor1_noreferences() throws Exception {
@@ -91,6 +100,12 @@ public class AndroidPackageRenameParticipantTest extends RefactoringTestBase {
" + <my.pkg.name.CustomView1\n" +
"\n" +
"\n" +
+ "* activity_main.xml - /testRefactor2/res/layout/activity_main.xml\n" +
+ " @@ -33 +33\n" +
+ " - <fragment android:name=\"com.example.refactoringtest.MyFragment\"/>\n" +
+ " + <fragment android:name=\"my.pkg.name.MyFragment\"/>\n" +
+ "\n" +
+ "\n" +
"* customviews.xml - /testRefactor2/res/layout-land/customviews.xml\n" +
" @@ -9 +9\n" +
" - <com.example.refactoringtest.CustomView1\n" +
@@ -100,7 +115,10 @@ public class AndroidPackageRenameParticipantTest extends RefactoringTestBase {
"* AndroidManifest.xml - /testRefactor2/AndroidManifest.xml\n" +
" @@ -16 +16\n" +
" - android:name=\"com.example.refactoringtest.MainActivity\"\n" +
- " + android:name=\"my.pkg.name.MainActivity\"");
+ " + android:name=\"my.pkg.name.MainActivity\"\n" +
+ " @@ -25 +25\n" +
+ " - android:name=\".MainActivity2\"\n" +
+ " + android:name=\"my.pkg.name.MainActivity2\"");
}
public void testRefactor2_renamesub() throws Exception {
@@ -127,6 +145,12 @@ public class AndroidPackageRenameParticipantTest extends RefactoringTestBase {
" + <my.pkg.name.CustomView1\n" +
"\n" +
"\n" +
+ "* activity_main.xml - /testRefactor2_renamesub/res/layout/activity_main.xml\n" +
+ " @@ -33 +33\n" +
+ " - <fragment android:name=\"com.example.refactoringtest.MyFragment\"/>\n" +
+ " + <fragment android:name=\"my.pkg.name.MyFragment\"/>\n" +
+ "\n" +
+ "\n" +
"* customviews.xml - /testRefactor2_renamesub/res/layout-land/customviews.xml\n" +
" @@ -9 +9\n" +
" - <com.example.refactoringtest.CustomView1\n" +
@@ -137,6 +161,9 @@ public class AndroidPackageRenameParticipantTest extends RefactoringTestBase {
" @@ -16 +16\n" +
" - android:name=\"com.example.refactoringtest.MainActivity\"\n" +
" + android:name=\"my.pkg.name.MainActivity\"\n" +
+ " @@ -25 +25\n" +
+ " - android:name=\".MainActivity2\"\n" +
+ " + android:name=\"my.pkg.name.MainActivity2\"\n" +
"\n" +
"\n" +
"* customviews.xml - /testRefactor2_renamesub/res/layout/customviews.xml\n" +
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringTestBase.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringTestBase.java
index 93c34890f..44fb52297 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringTestBase.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringTestBase.java
@@ -19,10 +19,6 @@ import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.eclipse.adt.AdtUtils;
import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.AdtProjectTest;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidDocumentChange;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidLayoutChange;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidPackageRenameChange;
-import com.android.ide.eclipse.adt.internal.refactorings.changes.AndroidTypeRenameChange;
import com.google.common.base.Charsets;
import com.google.common.base.Splitter;
import com.google.common.io.ByteStreams;
@@ -133,10 +129,7 @@ public abstract class RefactoringTestBase extends AdtProjectTest {
sb.append('\n');
}
- if (change instanceof TextFileChange
- || change instanceof AndroidPackageRenameChange
- || change instanceof AndroidTypeRenameChange
- || change instanceof AndroidLayoutChange) {
+ if (change instanceof TextFileChange) {
assertNotNull(file);
if (file != null) {
TextChange tc = (TextChange) change;
@@ -221,18 +214,6 @@ public abstract class RefactoringTestBase extends AdtProjectTest {
if (change instanceof TextFileChange) {
TextFileChange tfc = (TextFileChange) change;
return tfc.getFile();
- } else if (change instanceof AndroidPackageRenameChange) {
- AndroidPackageRenameChange aprc = (AndroidPackageRenameChange) change;
- return aprc.getManifest();
- } else if (change instanceof AndroidTypeRenameChange) {
- AndroidTypeRenameChange aprc = (AndroidTypeRenameChange) change;
- return aprc.getManifest();
- } else if (change instanceof AndroidLayoutChange) {
- AndroidLayoutChange alc = (AndroidLayoutChange) change;
- return alc.getFile();
- } else if (change instanceof AndroidDocumentChange) {
- AndroidDocumentChange atmc = (AndroidDocumentChange) change;
- return atmc.getManifest();
}
return null;
@@ -293,6 +274,10 @@ public abstract class RefactoringTestBase extends AdtProjectTest {
" <category android:name=\"android.intent.category.LAUNCHER\" />\n" +
" </intent-filter>\n" +
" </activity>\n" +
+ " <activity\n" +
+ " android:name=\".MainActivity2\"\n" +
+ " android:label=\"@string/app_name2\" >\n" +
+ " </activity>\n" +
" </application>\n" +
"\n" +
"</manifest>";
@@ -323,6 +308,31 @@ public abstract class RefactoringTestBase extends AdtProjectTest {
"\n" +
"}\n";
+ protected static final String SAMPLE_MAIN_ACTIVITY2 =
+ "package com.example.refactoringtest;\n" +
+ "\n" +
+ "import android.os.Bundle;\n" +
+ "import android.app.Activity;\n" +
+ "import android.view.Menu;\n" +
+ "import android.view.View;\n" +
+ "\n" +
+ "public class MainActivity2 extends Activity {\n" +
+ "\n" +
+ " @Override\n" +
+ " protected void onCreate(Bundle savedInstanceState) {\n" +
+ " super.onCreate(savedInstanceState);\n" +
+ " }\n" +
+ "\n" +
+ "}\n";
+
+ protected static final String MY_FRAGMENT =
+ "package com.example.refactoringtest;\n" +
+ "import android.support.v4.app.ListFragment;\n" +
+ "\n" +
+ "public class MyFragment extends ListFragment {\n" +
+ "\n" +
+ "}\n";
+
protected static final String SAMPLE_LAYOUT =
"<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" xmlns:tools=\"http://schemas.android.com/tools\"\n" +
@@ -356,6 +366,8 @@ public abstract class RefactoringTestBase extends AdtProjectTest {
" android:layout_alignParentTop=\"true\"\n" +
" android:text=\"Button\" />\n" +
"\n" +
+ " <fragment android:name=\"com.example.refactoringtest.MyFragment\"/>" +
+ "\n" +
"</RelativeLayout>";
protected static final String SAMPLE_LAYOUT_2 =
@@ -365,6 +377,18 @@ public abstract class RefactoringTestBase extends AdtProjectTest {
" android:layout_height=\"match_parent\"\n" +
" tools:context=\".MainActivity\" >\n" +
"\n" +
+ " <ListView\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " tools:listitem=\"@layout/preview\" >\n" +
+ " </ListView>\n" +
+ "\n" +
+ " <fragment\n" +
+ " android:name=\"android.support.v4.app.ListFragment\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " tools:layout=\"@layout/preview\" />\n" +
+ "\n" +
"\n" +
"</RelativeLayout>";
@@ -482,6 +506,9 @@ public abstract class RefactoringTestBase extends AdtProjectTest {
"src/com/example/refactoringtest/MainActivity.java",
SAMPLE_MAIN_ACTIVITY,
+ "src/com/example/refactoringtest/MainActivity2.java",
+ SAMPLE_MAIN_ACTIVITY2,
+
"gen/com/example/refactoringtest/R.java",
SAMPLE_R,
@@ -572,6 +599,9 @@ public abstract class RefactoringTestBase extends AdtProjectTest {
"src/com/example/refactoringtest/subpackage/CustomView2.java",
CUSTOM_VIEW_2,
+ "src/com/example/refactoringtest/MyFragment.java",
+ MY_FRAGMENT,
+
"gen/com/example/refactoringtest/R.java",
SAMPLE_R,
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipantTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipantTest.java
index b783f8d97..3a6859c23 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipantTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipantTest.java
@@ -311,6 +311,25 @@ public class RenameResourceParticipantTest extends RefactoringTestBase {
" + public static final int output=0x7f070000;");
}
+ public void testRefactor10() throws Exception {
+ // Check updating tools: attributes
+ renameResource(
+ TEST_PROJECT,
+ "@layout/preview",
+ true /*updateReferences*/,
+ "newlayout",
+
+ "CHANGES:\n" +
+ "-------\n" +
+ "* activity_main.xml - /testRefactor10/res/layout-land/activity_main.xml\n" +
+ " @@ -10 +10\n" +
+ " - tools:listitem=\"@layout/preview\" >\n" +
+ " + tools:listitem=\"@layout/newlayout\" >\n" +
+ " @@ -17 +17\n" +
+ " - tools:layout=\"@layout/preview\" />\n" +
+ " + tools:layout=\"@layout/newlayout\" />");
+ }
+
// ---- Test infrastructure ----
protected void renameResource(
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipantTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipantTest.java
index aeedf20ba..0fb8523dc 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipantTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipantTest.java
@@ -50,18 +50,35 @@ public class AndroidTypeMoveParticipantTest extends RefactoringTestBase {
"\n" +
"* Move resource 'testRefactor1/src/com/example/refactoringtest/CustomView1.java' to 'subpackage'\n" +
"\n" +
- "* Android Type Move\n" +
+ "* customviews.xml - /testRefactor1/res/layout/customviews.xml\n" +
+ " @@ -9 +9\n" +
+ " - <com.example.refactoringtest.CustomView1\n" +
+ " + <com.example.refactoringtest.subpackage.CustomView1\n" +
"\n" +
- " * customviews.xml - /testRefactor1/res/layout/customviews.xml\n" +
- " @@ -9 +9\n" +
- " - <com.example.refactoringtest.CustomView1\n" +
- " + <com.example.refactoringtest.subpackage.CustomView1\n" +
"\n" +
+ "* customviews.xml - /testRefactor1/res/layout-land/customviews.xml\n" +
+ " @@ -9 +9\n" +
+ " - <com.example.refactoringtest.CustomView1\n" +
+ " + <com.example.refactoringtest.subpackage.CustomView1");
+ }
+
+ public void testRefactorFragment() throws Exception {
+ moveType(
+ TEST_PROJECT2,
+ "com.example.refactoringtest.MyFragment",
+ "src/com/example/refactoringtest/subpackage",
+ true /*updateReferences*/,
+
+ "CHANGES:\n" +
+ "-------\n" +
+ "* Move resource 'testRefactorFragment/src/com/example/refactoringtest/MyFragment.java' to 'subpackage'\n" +
+ "\n" +
+ "* Move resource 'testRefactorFragment/src/com/example/refactoringtest/MyFragment.java' to 'subpackage'\n" +
"\n" +
- " * customviews.xml - /testRefactor1/res/layout-land/customviews.xml\n" +
- " @@ -9 +9\n" +
- " - <com.example.refactoringtest.CustomView1\n" +
- " + <com.example.refactoringtest.subpackage.CustomView1");
+ "* activity_main.xml - /testRefactorFragment/res/layout/activity_main.xml\n" +
+ " @@ -33 +33\n" +
+ " - <fragment android:name=\"com.example.refactoringtest.MyFragment\"/>\n" +
+ " + <fragment android:name=\"com.example.refactoringtest.subpackage.MyFragment\"/>");
}
public void testRefactor1_norefs() throws Exception {
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipantTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipantTest.java
index 8ab0a1146..f54a49aba 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipantTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipantTest.java
@@ -38,12 +38,39 @@ public class AndroidTypeRenameParticipantTest extends RefactoringTestBase {
"-------\n" +
"* Rename compilation unit 'MainActivity.java' to 'NewActivityName.java'\n" +
"\n" +
- "* Android Type Rename\n" +
+ "* activity_main.xml - /testRefactor1/res/layout/activity_main.xml\n" +
+ " @@ -5 +5\n" +
+ " - tools:context=\".MainActivity\" >\n" +
+ " + tools:context=\".NewActivityName\" >\n" +
"\n" +
- " * AndroidManifest.xml - /testRefactor1/AndroidManifest.xml\n" +
- " @@ -16 +16\n" +
- " - android:name=\"com.example.refactoringtest.MainActivity\"\n" +
- " + android:name=\"com.example.refactoringtest.NewActivityName\"");
+ "\n" +
+ "* activity_main.xml - /testRefactor1/res/layout-land/activity_main.xml\n" +
+ " @@ -5 +5\n" +
+ " - tools:context=\".MainActivity\" >\n" +
+ " + tools:context=\".NewActivityName\" >\n" +
+ "\n" +
+ "\n" +
+ "* AndroidManifest.xml - /testRefactor1/AndroidManifest.xml\n" +
+ " @@ -16 +16\n" +
+ " - android:name=\"com.example.refactoringtest.MainActivity\"\n" +
+ " + android:name=\"com.example.refactoringtest.NewActivityName\"");
+ }
+
+ public void testRefactor1b() throws Exception {
+ renameType(
+ TEST_PROJECT,
+ "com.example.refactoringtest.MainActivity2",
+ true /*updateReferences*/,
+ "NewActivityName",
+
+ "CHANGES:\n" +
+ "-------\n" +
+ "* Rename compilation unit 'MainActivity2.java' to 'NewActivityName.java'\n" +
+ "\n" +
+ "* AndroidManifest.xml - /testRefactor1b/AndroidManifest.xml\n" +
+ " @@ -25 +25\n" +
+ " - android:name=\".MainActivity2\"\n" +
+ " + android:name=\".NewActivityName\"");
}
public void testRefactor1_noreferences() throws Exception {
@@ -69,18 +96,33 @@ public class AndroidTypeRenameParticipantTest extends RefactoringTestBase {
"-------\n" +
"* Rename compilation unit 'CustomView1.java' to 'NewCustomViewName.java'\n" +
"\n" +
- "* Android Type Rename\n" +
- "\n" +
- " * customviews.xml - /testRefactor2/res/layout/customviews.xml\n" +
- " @@ -9 +9\n" +
- " - <com.example.refactoringtest.CustomView1\n" +
- " + <com.example.refactoringtest.NewCustomViewName\n" +
+ "* customviews.xml - /testRefactor2/res/layout/customviews.xml\n" +
+ " @@ -9 +9\n" +
+ " - <com.example.refactoringtest.CustomView1\n" +
+ " + <com.example.refactoringtest.NewCustomViewName\n" +
"\n" +
"\n" +
- " * customviews.xml - /testRefactor2/res/layout-land/customviews.xml\n" +
- " @@ -9 +9\n" +
- " - <com.example.refactoringtest.CustomView1\n" +
- " + <com.example.refactoringtest.NewCustomViewName");
+ "* customviews.xml - /testRefactor2/res/layout-land/customviews.xml\n" +
+ " @@ -9 +9\n" +
+ " - <com.example.refactoringtest.CustomView1\n" +
+ " + <com.example.refactoringtest.NewCustomViewName");
+ }
+
+ public void testRefactorFragment() throws Exception {
+ renameType(
+ TEST_PROJECT2,
+ "com.example.refactoringtest.MyFragment",
+ true /*updateReferences*/,
+ "NewFragmentName",
+
+ "CHANGES:\n" +
+ "-------\n" +
+ "* Rename compilation unit 'MyFragment.java' to 'NewFragmentName.java'\n" +
+ "\n" +
+ "* activity_main.xml - /testRefactorFragment/res/layout/activity_main.xml\n" +
+ " @@ -33 +33\n" +
+ " - <fragment android:name=\"com.example.refactoringtest.MyFragment\"/>\n" +
+ " + <fragment android:name=\"com.example.refactoringtest.NewFragmentName\"/>");
}
// ---- Test infrastructure ----