From: Raphael Moll <> Date: Wed, 25 Mar 2009 04:01:03 +0000 (-0700) Subject: Automated import from //branches/master/...@141824,141824 X-Git-Tag: android-x86-2.2~1191 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=d39c6f2103a00df18bc8cba441047a92839f9196;p=android-x86%2Fsdk.git Automated import from //branches/master/...@141824,141824 --- diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringAction.java index 528701573..dceb1441d 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringAction.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringAction.java @@ -16,7 +16,11 @@ package com.android.ide.eclipse.adt.refactorings.extractstring; +import com.android.ide.eclipse.common.AndroidConstants; + import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaCore; @@ -32,6 +36,7 @@ import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.part.FileEditorInput; /* * Quick Reference Link: @@ -71,7 +76,7 @@ public class ExtractStringAction implements IWorkbenchWindowActionDelegate { /** Keep track of the current workbench window. */ private IWorkbenchWindow mWindow; private ITextSelection mSelection; - private ICompilationUnit mUnit; + private IFile mFile; /** * Keep track of the current workbench window. @@ -99,30 +104,24 @@ public class ExtractStringAction implements IWorkbenchWindowActionDelegate { // runs since we don't have access to the AST yet. mSelection = null; - mUnit = null; + mFile = null; if (selection instanceof ITextSelection) { mSelection = (ITextSelection) selection; if (mSelection.getLength() > 0) { - mUnit = getCompilationUnit(); + mFile = getSelectedFile(); } - - // Keep for debugging purposes - //System.out.println(String.format("-- Selection: %d + %d = %s", - // mSelection.getOffset(), - // mSelection.getLength(), - // mSelection.getText())); } - action.setEnabled(mSelection != null && mUnit != null); + action.setEnabled(mSelection != null && mFile != null); } /** * Create a new instance of our refactoring and a wizard to configure it. */ public void run(IAction action) { - if (mSelection != null && mUnit != null) { - ExtractStringRefactoring ref = new ExtractStringRefactoring(mUnit, mSelection); + if (mSelection != null && mFile != null) { + ExtractStringRefactoring ref = new ExtractStringRefactoring(mFile, mSelection); RefactoringWizard wizard = new ExtractStringWizard(ref, "Extract Android String"); RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard); try { @@ -134,9 +133,14 @@ public class ExtractStringAction implements IWorkbenchWindowActionDelegate { } /** - * Returns the active {@link ICompilationUnit} or null. + * Returns the active {@link IFile} (hopefully matching our selection) or null. + * The file is only returned if it's a file from a project with an Android nature. + *

+ * At that point we do not try to analyze if the selection nor the file is suitable + * for the refactoring. This check is performed when the refactoring is invoked since + * it can then produce meaningful error messages as needed. */ - private ICompilationUnit getCompilationUnit() { + private IFile getSelectedFile() { IWorkbenchWindow wwin = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (wwin != null) { IWorkbenchPage page = wwin.getActivePage(); @@ -144,12 +148,19 @@ public class ExtractStringAction implements IWorkbenchWindowActionDelegate { IEditorPart editor = page.getActiveEditor(); if (editor != null) { IEditorInput input = editor.getEditorInput(); - if (input != null) { - ITypeRoot typeRoot = JavaUI.getEditorInputTypeRoot(input); - // The type root can be either a .class or a .java (aka compilation unit). - // We want the compilation unit kind. - if (typeRoot instanceof ICompilationUnit) { - return (ICompilationUnit) typeRoot; + + if (input instanceof FileEditorInput) { + FileEditorInput fi = (FileEditorInput) input; + IFile file = fi.getFile(); + if (file.exists()) { + IProject proj = file.getProject(); + try { + if (proj != null && proj.hasNature(AndroidConstants.NATURE)) { + return file; + } + } catch (CoreException e) { + // ignore + } } } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringRefactoring.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringRefactoring.java index 715503c1f..99711bf20 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringRefactoring.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringRefactoring.java @@ -24,7 +24,9 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourceAttributes; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; @@ -126,46 +128,54 @@ import javax.xml.xpath.XPathExpressionException; */ class ExtractStringRefactoring extends Refactoring { - /** The compilation unit, a.k.a. the Java file model. */ - private final ICompilationUnit mUnit; + /** The file model being manipulated. */ + private final IFile mFile; + /** The start of the selection in {@link #mFile}. */ private final int mSelectionStart; + /** The end of the selection in {@link #mFile}. */ private final int mSelectionEnd; + + /** The compilation unit, only defined if {@link #mFile} points to a usable Java source file. */ + private ICompilationUnit mUnit; /** The actual string selected, after UTF characters have been escaped, good for display. */ private String mTokenString; - /** Start position of the string token in the source buffer. */ - private int mTokenStart; - /** End position of the string token in the source buffer. */ - private int mTokenEnd; + + /** The XML string ID selected by the user in the wizard. */ private String mXmlStringId; + /** The path of the XML file that will define {@link #mXmlStringId}, selected by the user + * in the wizard. */ private String mTargetXmlFileWsPath; + + /** 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. */ private HashMap> mResIdCache; + /** An instance of XPath, created lazily on demand. */ private XPath mXPath; + /** The list of changes computed by {@link #checkFinalConditions(IProgressMonitor)} and + * used by {@link #createChange(IProgressMonitor)}. */ private ArrayList mChanges; public ExtractStringRefactoring(Map arguments) throws NullPointerException { - mUnit = (ICompilationUnit) JavaCore.create(arguments.get("CU")); //$NON-NLS-1$ + + IPath path = Path.fromPortableString(arguments.get("file")); //$NON-NLS-1$ + mFile = (IFile) ResourcesPlugin.getWorkspace().getRoot().findMember(path); mSelectionStart = Integer.parseInt(arguments.get("sel-start")); //$NON-NLS-1$ mSelectionEnd = Integer.parseInt(arguments.get("sel-end")); //$NON-NLS-1$ - mTokenStart = Integer.parseInt(arguments.get("tok-start")); //$NON-NLS-1$ - mTokenEnd = Integer.parseInt(arguments.get("tok-end")); //$NON-NLS-1$ mTokenString = arguments.get("tok-esc"); //$NON-NLS-1$ } private Map createArgumentMap() { HashMap args = new HashMap(); - args.put("CU", mUnit.getHandleIdentifier()); //$NON-NLS-1$ + args.put("file", mFile.getFullPath().toPortableString()); //$NON-NLS-1$ args.put("sel-start", Integer.toString(mSelectionStart)); //$NON-NLS-1$ args.put("sel-end", Integer.toString(mSelectionEnd)); //$NON-NLS-1$ - args.put("tok-start", Integer.toString(mTokenStart)); //$NON-NLS-1$ - args.put("tok-end", Integer.toString(mTokenEnd)); //$NON-NLS-1$ args.put("tok-esc", mTokenString); //$NON-NLS-1$ return args; } - public ExtractStringRefactoring(ICompilationUnit unit, ITextSelection selection) { - mUnit = unit; - + public ExtractStringRefactoring(IFile file, ITextSelection selection) { + mFile = file; mSelectionStart = selection.getOffset(); mSelectionEnd = mSelectionStart + selection.getLength(); } @@ -207,75 +217,42 @@ class ExtractStringRefactoring extends Refactoring { public RefactoringStatus checkInitialConditions(IProgressMonitor monitor) throws CoreException, OperationCanceledException { + mUnit = null; mTokenString = null; - mTokenStart = -1; - mTokenEnd = -1; RefactoringStatus status = new RefactoringStatus(); try { - monitor.beginTask("Checking preconditions...", 3); - - if (!extraChecks(monitor, status)) { + monitor.beginTask("Checking preconditions...", 5); + + if (!checkSourceFile(mFile, status, monitor)) { return status; } - + + // Try to get a compilation unit from this file. If it fails, mUnit is null. try { - IBuffer buffer = mUnit.getBuffer(); - - IScanner scanner = ToolFactory.createScanner( - false, //tokenizeComments - false, //tokenizeWhiteSpace - false, //assertMode - false //recordLineSeparator - ); - scanner.setSource(buffer.getCharacters()); - monitor.worked(1); - - for(int token = scanner.getNextToken(); - token != ITerminalSymbols.TokenNameEOF; - token = scanner.getNextToken()) { - if (scanner.getCurrentTokenStartPosition() <= mSelectionStart && - scanner.getCurrentTokenEndPosition() >= mSelectionEnd) { - // found the token, but only keep of the right type - if (token == ITerminalSymbols.TokenNameStringLiteral) { - mTokenString = new String(scanner.getCurrentTokenSource()); - mTokenStart = scanner.getCurrentTokenStartPosition(); - mTokenEnd = scanner.getCurrentTokenEndPosition(); - } - break; - } else if (scanner.getCurrentTokenStartPosition() > mSelectionEnd) { - // scanner is past the selection, abort. - break; - } - } - } catch (JavaModelException e1) { - // Error in mUnit.getBuffer. Ignore. - } catch (InvalidInputException e2) { - // Error in scanner.getNextToken. Ignore. - } finally { - monitor.worked(1); - } + mUnit = JavaCore.createCompilationUnitFrom(mFile); - if (mTokenString != null) { - // As a literal string, the token should have surrounding quotes. Remove them. - int len = mTokenString.length(); - if (len > 0 && - mTokenString.charAt(0) == '"' && - mTokenString.charAt(len - 1) == '"') { - mTokenString = mTokenString.substring(1, len - 1); + // Make sure the unit is not read-only, e.g. it's not a class file or inside a Jar + if (mUnit.isReadOnly()) { + status.addFatalError("The file is read-only, please make it writeable first."); + return status; } - // We need a non-empty string literal - if (mTokenString.length() == 0) { - mTokenString = null; + + // This is a Java file. Check if it contains the selection we want. + if (!findSelectionInJavaUnit(mUnit, status, monitor)) { + return status; } + + } catch (Exception e) { + // That was not a Java file. Ignore. } - if (mTokenString == null) { - status.addFatalError("Please select a Java string literal."); + if (mUnit == null) { + // Check this an XML file and get the selection and its context. + // TODO + status.addFatalError("Selection must be inside a Java source file."); } - - monitor.worked(1); } finally { monitor.done(); } @@ -284,30 +261,93 @@ class ExtractStringRefactoring extends Refactoring { } /** - * Tests from org.eclipse.jdt.internal.corext.refactoringChecks#validateEdit() - * Might not be useful. + * Try to find the selected Java element in the compilation unit. * - * @return False if caller should abort, true if caller should continue. + * If selection matches a string literal, capture it, otherwise add a fatal error + * to the status. + * + * On success, advance the monitor by 3. */ - private boolean extraChecks(IProgressMonitor monitor, RefactoringStatus status) { - // - IResource res = mUnit.getPrimary().getResource(); - if (res == null || res.getType() != IResource.FILE) { - status.addFatalError("Cannot access resource; only regular files can be used."); - return false; + private boolean findSelectionInJavaUnit(ICompilationUnit unit, + RefactoringStatus status, IProgressMonitor monitor) { + try { + IBuffer buffer = unit.getBuffer(); + + IScanner scanner = ToolFactory.createScanner( + false, //tokenizeComments + false, //tokenizeWhiteSpace + false, //assertMode + false //recordLineSeparator + ); + scanner.setSource(buffer.getCharacters()); + monitor.worked(1); + + for(int token = scanner.getNextToken(); + token != ITerminalSymbols.TokenNameEOF; + token = scanner.getNextToken()) { + if (scanner.getCurrentTokenStartPosition() <= mSelectionStart && + scanner.getCurrentTokenEndPosition() >= mSelectionEnd) { + // found the token, but only keep of the right type + if (token == ITerminalSymbols.TokenNameStringLiteral) { + mTokenString = new String(scanner.getCurrentTokenSource()); + } + break; + } else if (scanner.getCurrentTokenStartPosition() > mSelectionEnd) { + // scanner is past the selection, abort. + break; + } + } + } catch (JavaModelException e1) { + // Error in unit.getBuffer. Ignore. + } catch (InvalidInputException e2) { + // Error in scanner.getNextToken. Ignore. + } finally { + monitor.worked(1); + } + + if (mTokenString != null) { + // As a literal string, the token should have surrounding quotes. Remove them. + int len = mTokenString.length(); + if (len > 0 && + mTokenString.charAt(0) == '"' && + mTokenString.charAt(len - 1) == '"') { + mTokenString = mTokenString.substring(1, len - 1); + } + // We need a non-empty string literal + if (mTokenString.length() == 0) { + mTokenString = null; + } } + + if (mTokenString == null) { + status.addFatalError("Please select a Java string literal."); + } + monitor.worked(1); + return status.isOK(); + } + /** + * Tests from org.eclipse.jdt.internal.corext.refactoringChecks#validateEdit() + * Might not be useful. + * + * On success, advance the monitor by 2. + * + * @return False if caller should abort, true if caller should continue. + */ + private boolean checkSourceFile(IFile file, + RefactoringStatus status, + IProgressMonitor monitor) { // check whether the source file is in sync - if (!res.isSynchronized(IResource.DEPTH_ZERO)) { + if (!file.isSynchronized(IResource.DEPTH_ZERO)) { status.addFatalError("The file is not synchronized. Please save it first."); return false; } monitor.worked(1); // make sure we can write to it. - ResourceAttributes resAttr = res.getResourceAttributes(); - if (mUnit.isReadOnly() || resAttr == null || resAttr.isReadOnly()) { + ResourceAttributes resAttr = file.getResourceAttributes(); + if (resAttr == null || resAttr.isReadOnly()) { status.addFatalError("The file is read-only, please make it writeable first."); return false; }