am ac50c3ae: ADT XML extract string IDs: display existing IDs of the selected file.
Merge commit 'ac50c3aedfd4e18a3770315708ac4de47906eec4' * commit 'ac50c3aedfd4e18a3770315708ac4de47906eec4': ADT XML extract string IDs: display existing IDs of the
This commit is contained in:
@@ -33,6 +33,8 @@ import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
|
|||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
import org.eclipse.swt.events.ModifyEvent;
|
import org.eclipse.swt.events.ModifyEvent;
|
||||||
import org.eclipse.swt.events.ModifyListener;
|
import org.eclipse.swt.events.ModifyListener;
|
||||||
|
import org.eclipse.swt.events.SelectionAdapter;
|
||||||
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
import org.eclipse.swt.layout.GridData;
|
import org.eclipse.swt.layout.GridData;
|
||||||
import org.eclipse.swt.layout.GridLayout;
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
import org.eclipse.swt.widgets.Combo;
|
import org.eclipse.swt.widgets.Combo;
|
||||||
@@ -42,6 +44,7 @@ import org.eclipse.swt.widgets.Label;
|
|||||||
import org.eclipse.swt.widgets.Text;
|
import org.eclipse.swt.widgets.Text;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@@ -59,7 +62,7 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
|||||||
private final IProject mProject;
|
private final IProject mProject;
|
||||||
|
|
||||||
/** Text field where the user enters the new ID to be generated or replaced with. */
|
/** Text field where the user enters the new ID to be generated or replaced with. */
|
||||||
private Text mStringIdField;
|
private Combo mStringIdCombo;
|
||||||
/** Text field where the user enters the new string value. */
|
/** Text field where the user enters the new string value. */
|
||||||
private Text mStringValueField;
|
private Text mStringValueField;
|
||||||
/** The configuration selector, to select the resource path of the XML file. */
|
/** The configuration selector, to select the resource path of the XML file. */
|
||||||
@@ -163,18 +166,24 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
|||||||
label.setText("ID &R.string.");
|
label.setText("ID &R.string.");
|
||||||
}
|
}
|
||||||
|
|
||||||
mStringIdField = new Text(group, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
|
mStringIdCombo = new Combo(group, SWT.SINGLE | SWT.LEFT | SWT.BORDER | SWT.DROP_DOWN);
|
||||||
mStringIdField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
mStringIdCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||||
mStringIdField.setText(guessId(selectedString));
|
mStringIdCombo.setText(guessId(selectedString));
|
||||||
mStringIdField.forceFocus();
|
mStringIdCombo.forceFocus();
|
||||||
|
|
||||||
ref.setNewStringId(mStringIdField.getText().trim());
|
ref.setNewStringId(mStringIdCombo.getText().trim());
|
||||||
|
|
||||||
mStringIdField.addModifyListener(new ModifyListener() {
|
mStringIdCombo.addModifyListener(new ModifyListener() {
|
||||||
public void modifyText(ModifyEvent e) {
|
public void modifyText(ModifyEvent e) {
|
||||||
validatePage();
|
validatePage();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
mStringIdCombo.addSelectionListener(new SelectionAdapter() {
|
||||||
|
@Override
|
||||||
|
public void widgetSelected(SelectionEvent e) {
|
||||||
|
validatePage();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -270,7 +279,7 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
|||||||
|
|
||||||
// Analyze fatal errors.
|
// Analyze fatal errors.
|
||||||
|
|
||||||
String text = mStringIdField.getText().trim();
|
String text = mStringIdCombo.getText().trim();
|
||||||
if (text == null || text.length() < 1) {
|
if (text == null || text.length() < 1) {
|
||||||
setErrorMessage("Please provide a resource ID.");
|
setErrorMessage("Please provide a resource ID.");
|
||||||
success = false;
|
success = false;
|
||||||
@@ -342,6 +351,23 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateStringValueCombo() {
|
||||||
|
String resFile = mResFileCombo.getText();
|
||||||
|
Set<String> ids = mXmlHelper.getResIdsForFile(mProject, resFile);
|
||||||
|
|
||||||
|
// get the current text from the combo, to make sure we don't change it
|
||||||
|
String currText = mStringIdCombo.getText();
|
||||||
|
|
||||||
|
// erase the choices and fill with the given ids
|
||||||
|
mStringIdCombo.removeAll();
|
||||||
|
mStringIdCombo.setItems(ids.toArray(new String[ids.size()]));
|
||||||
|
|
||||||
|
// set the current text to preserve it in case it changed
|
||||||
|
if (!currText.equals(mStringIdCombo.getText())) {
|
||||||
|
mStringIdCombo.setText(currText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class OnConfigSelectorUpdated implements Runnable, ModifyListener {
|
public class OnConfigSelectorUpdated implements Runnable, ModifyListener {
|
||||||
|
|
||||||
/** Regex pattern to parse a valid res path: it reads (/res/folder-name/)+(filename). */
|
/** Regex pattern to parse a valid res path: it reads (/res/folder-name/)+(filename). */
|
||||||
@@ -458,6 +484,7 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
|||||||
}
|
}
|
||||||
|
|
||||||
// finally validate the whole page
|
// finally validate the whole page
|
||||||
|
updateStringValueCombo();
|
||||||
validatePage();
|
validatePage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,6 +537,7 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateStringValueCombo();
|
||||||
validatePage();
|
validatePage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* Licensed under the Eclipse Public License, Version 1.0 (the "License");
|
* 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 not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.eclipse.org/org/documents/epl-v10.php
|
* http://www.eclipse.org/org/documents/epl-v10.php
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
@@ -26,68 +26,78 @@ import org.w3c.dom.NodeList;
|
|||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import javax.xml.xpath.XPath;
|
import javax.xml.xpath.XPath;
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
import javax.xml.xpath.XPathExpressionException;
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* An helper utility to get IDs out of an Android XML resource file.
|
||||||
*/
|
*/
|
||||||
class XmlStringFileHelper {
|
class XmlStringFileHelper {
|
||||||
|
|
||||||
/** A temporary cache of R.string IDs defined by a given xml file. The key is the
|
/** A temporary cache of R.string IDs defined by a given xml file. The key is the
|
||||||
* project path of the file, the data is a set of known string Ids for that file. */
|
* project path of the file, the data is a set of known string Ids for that file. */
|
||||||
private HashMap<String,HashSet<String>> mResIdCache;
|
private HashMap<String, Set<String>> mResIdCache = new HashMap<String, Set<String>>();
|
||||||
/** An instance of XPath, created lazily on demand. */
|
/** An instance of XPath, created lazily on demand. */
|
||||||
private XPath mXPath;
|
private XPath mXPath;
|
||||||
|
|
||||||
public XmlStringFileHelper() {
|
public XmlStringFileHelper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility method used by the wizard to check whether the given string ID is already
|
* Utility method used by the wizard to check whether the given string ID is already
|
||||||
* defined in the XML file which path is given.
|
* defined in the XML file which path is given.
|
||||||
*
|
*
|
||||||
* @param project The project contain the XML file.
|
* @param project The project contain the XML file.
|
||||||
* @param xmlFileWsPath The project path of the XML file, e.g. "/res/values/strings.xml".
|
* @param xmlFileWsPath The project path of the XML file, e.g. "/res/values/strings.xml".
|
||||||
* The given file may or may not exist.
|
* The given file may or may not exist.
|
||||||
* @param stringId The string ID to find.
|
* @param stringId The string ID to find.
|
||||||
* @return True if such a string ID is already defined.
|
* @return True if such a string ID is already defined.
|
||||||
*/
|
*/
|
||||||
public boolean isResIdDuplicate(IProject project, String xmlFileWsPath, String stringId) {
|
public boolean isResIdDuplicate(IProject project, String xmlFileWsPath, String stringId) {
|
||||||
// This is going to be called many times on the same file.
|
Set<String> cache = getResIdsForFile(project, xmlFileWsPath);
|
||||||
// Build a cache of the existing IDs for a given file.
|
|
||||||
if (mResIdCache == null) {
|
|
||||||
mResIdCache = new HashMap<String, HashSet<String>>();
|
|
||||||
}
|
|
||||||
HashSet<String> cache = mResIdCache.get(xmlFileWsPath);
|
|
||||||
if (cache == null) {
|
|
||||||
cache = getResIdsForFile(project, xmlFileWsPath);
|
|
||||||
mResIdCache.put(xmlFileWsPath, cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cache.contains(stringId);
|
return cache.contains(stringId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility method that retrieves all the *string* IDs defined in the given Android resource
|
||||||
|
* file. The instance maintains an internal cache so a given file is retrieved only once.
|
||||||
|
* Callers should consider the set to be read-only.
|
||||||
|
*
|
||||||
|
* @param project The project contain the XML file.
|
||||||
|
* @param xmlFileWsPath The project path of the XML file, e.g. "/res/values/strings.xml".
|
||||||
|
* The given file may or may not exist.
|
||||||
|
* @return The set of string IDs defined in the given file. Cached. Never null.
|
||||||
|
*/
|
||||||
|
public Set<String> getResIdsForFile(IProject project, String xmlFileWsPath) {
|
||||||
|
Set<String> cache = mResIdCache.get(xmlFileWsPath);
|
||||||
|
if (cache == null) {
|
||||||
|
cache = internalGetResIdsForFile(project, xmlFileWsPath);
|
||||||
|
mResIdCache.put(xmlFileWsPath, cache);
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract all the defined string IDs from a given file using XPath.
|
* Extract all the defined string IDs from a given file using XPath.
|
||||||
* @param project The project contain the XML file.
|
* @param project The project contain the XML file.
|
||||||
* @param xmlFileWsPath The project path of the file to parse. It may not exist.
|
* @param xmlFileWsPath The project path of the file to parse. It may not exist.
|
||||||
* @return The set of all string IDs defined in the file. The returned set is always non
|
* @return The set of all string IDs defined in the file. The returned set is always non
|
||||||
* null. It is empty if the file does not exist.
|
* null. It is empty if the file does not exist.
|
||||||
*/
|
*/
|
||||||
private HashSet<String> getResIdsForFile(IProject project, String xmlFileWsPath) {
|
private Set<String> internalGetResIdsForFile(IProject project, String xmlFileWsPath) {
|
||||||
HashSet<String> ids = new HashSet<String>();
|
TreeSet<String> ids = new TreeSet<String>();
|
||||||
|
|
||||||
if (mXPath == null) {
|
if (mXPath == null) {
|
||||||
mXPath = AndroidXPathFactory.newXPath();
|
mXPath = AndroidXPathFactory.newXPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Access the project that contains the resource that contains the compilation unit
|
// Access the project that contains the resource that contains the compilation unit
|
||||||
IResource resource = project.getFile(xmlFileWsPath);
|
IResource resource = project.getFile(xmlFileWsPath);
|
||||||
|
|
||||||
if (resource != null && resource.exists() && resource.getType() == IResource.FILE) {
|
if (resource != null && resource.exists() && resource.getType() == IResource.FILE) {
|
||||||
InputSource source;
|
InputSource source;
|
||||||
try {
|
try {
|
||||||
@@ -97,9 +107,9 @@ class XmlStringFileHelper {
|
|||||||
// <resources>
|
// <resources>
|
||||||
// <string name="ID">something</string>
|
// <string name="ID">something</string>
|
||||||
// </resources>
|
// </resources>
|
||||||
|
|
||||||
String xpathExpr = "/resources/string/@name"; //$NON-NLS-1$
|
String xpathExpr = "/resources/string/@name"; //$NON-NLS-1$
|
||||||
|
|
||||||
Object result = mXPath.evaluate(xpathExpr, source, XPathConstants.NODESET);
|
Object result = mXPath.evaluate(xpathExpr, source, XPathConstants.NODESET);
|
||||||
if (result instanceof NodeList) {
|
if (result instanceof NodeList) {
|
||||||
NodeList list = (NodeList) result;
|
NodeList list = (NodeList) result;
|
||||||
@@ -108,14 +118,14 @@ class XmlStringFileHelper {
|
|||||||
ids.add(id);
|
ids.add(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (CoreException e1) {
|
} catch (CoreException e1) {
|
||||||
// IFile.getContents failed. Ignore.
|
// IFile.getContents failed. Ignore.
|
||||||
} catch (XPathExpressionException e) {
|
} catch (XPathExpressionException e) {
|
||||||
// mXPath.evaluate failed. Ignore.
|
// mXPath.evaluate failed. Ignore.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user