1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.ide.eclipse.adt.internal.refactorings.extractstring; 17 18 import com.android.ide.eclipse.adt.AdtPlugin; 19 import com.android.ide.eclipse.adt.AdtUtils; 20 21 import org.eclipse.core.resources.IFile; 22 import org.eclipse.jdt.core.IBuffer; 23 import org.eclipse.jdt.core.JavaModelException; 24 import org.eclipse.jdt.core.dom.ASTNode; 25 import org.eclipse.jdt.ui.text.java.IInvocationContext; 26 import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; 27 import org.eclipse.jface.text.IDocument; 28 import org.eclipse.jface.text.ITextSelection; 29 import org.eclipse.jface.text.TextSelection; 30 import org.eclipse.jface.text.contentassist.IContextInformation; 31 import org.eclipse.ltk.ui.refactoring.RefactoringWizard; 32 import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; 33 import org.eclipse.swt.graphics.Image; 34 import org.eclipse.swt.graphics.Point; 35 import org.eclipse.ui.IEditorPart; 36 import org.eclipse.ui.IWorkbenchWindow; 37 import org.eclipse.ui.PlatformUI; 38 39 /** 40 * Proposal for extracting strings in Java files 41 */ 42 public class ExtractStringProposal implements IJavaCompletionProposal { 43 private IInvocationContext mContext; 44 ExtractStringProposal(IInvocationContext context)45 public ExtractStringProposal(IInvocationContext context) { 46 mContext = context; 47 } 48 49 @Override apply(IDocument document)50 public void apply(IDocument document) { 51 IEditorPart editor = AdtUtils.getActiveEditor(); 52 IFile file = AdtUtils.getActiveFile(); 53 if (editor == null || file == null) { 54 return; 55 } 56 57 ASTNode coveringNode = mContext.getCoveringNode(); 58 int start = coveringNode.getStartPosition(); 59 int length = coveringNode.getLength(); 60 ITextSelection selection = new TextSelection(start, length); 61 62 ExtractStringRefactoring refactoring = new ExtractStringRefactoring(file, editor, 63 selection); 64 65 RefactoringWizard wizard = new ExtractStringWizard(refactoring, file.getProject()); 66 RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard); 67 try { 68 IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); 69 op.run(window.getShell(), wizard.getDefaultPageTitle()); 70 } catch (InterruptedException e) { 71 } 72 } 73 74 @Override getSelection(IDocument document)75 public Point getSelection(IDocument document) { 76 return null; 77 } 78 79 @Override getAdditionalProposalInfo()80 public String getAdditionalProposalInfo() { 81 try { 82 ASTNode coveringNode = mContext.getCoveringNode(); 83 int start = coveringNode.getStartPosition(); 84 int length = coveringNode.getLength(); 85 IBuffer buffer = mContext.getCompilationUnit().getBuffer(); 86 StringBuilder sb = new StringBuilder(); 87 String string = buffer.getText(start, length); 88 string = ExtractStringRefactoring.unquoteAttrValue(string); 89 String token = ExtractStringInputPage.guessId(string); 90 91 // Look up the beginning and the end of the line (outside of the extracted string) 92 // such that we can show a preview of the diff, e.g. if you have 93 // foo.setTitle("Hello"); we want to show foo.setTitle(R.string.hello); 94 // so we need to extract "foo.setTitle(" and ");". 95 96 // Look backwards to the beginning of the line (and strip whitespace) 97 int i = start - 1; 98 while (i > 0) { 99 char c = buffer.getChar(i); 100 if (c == '\r' || (c == '\n')) { 101 break; 102 } 103 i--; 104 } 105 String linePrefix = buffer.getText(i + 1, start - (i + 1)).trim(); 106 107 // Look forwards to the end of the line (and strip whitespace) 108 i = start + length; 109 while (i < buffer.getLength()) { 110 char c = buffer.getChar(i); 111 if (c == '\r' || (c == '\n')) { 112 break; 113 } 114 i++; 115 } 116 String lineSuffix = buffer.getText(start + length, i - (start + length)); 117 118 // Should we show the replacement as just R.string.foo or 119 // context.getString(R.string.foo) ? 120 boolean useContext = false; 121 ASTNode parent = coveringNode.getParent(); 122 if (parent != null) { 123 int type = parent.getNodeType(); 124 if (type == ASTNode.ASSIGNMENT 125 || type == ASTNode.VARIABLE_DECLARATION_STATEMENT 126 || type == ASTNode.VARIABLE_DECLARATION_FRAGMENT 127 || type == ASTNode.VARIABLE_DECLARATION_EXPRESSION) { 128 useContext = true; 129 } 130 } 131 132 // Display .java change: 133 sb.append("...<br>"); //$NON-NLS-1$ 134 sb.append(linePrefix); 135 sb.append("<b>"); //$NON-NLS-1$ 136 if (useContext) { 137 sb.append("context.getString("); //$NON-NLS-1$ 138 } 139 sb.append("R.string."); //$NON-NLS-1$ 140 sb.append(token); 141 if (useContext) { 142 sb.append(")"); //$NON-NLS-1$ 143 } 144 sb.append("</b>"); //$NON-NLS-1$ 145 sb.append(lineSuffix); 146 sb.append("<br>...<br>"); //$NON-NLS-1$ 147 148 // Display strings.xml change: 149 sb.append("<br>"); //$NON-NLS-1$ 150 sb.append("<resources><br>"); //$NON-NLS-1$ 151 sb.append(" <b><string name=\""); //$NON-NLS-1$ 152 sb.append(token); 153 sb.append("\">"); //$NON-NLS-1$ 154 sb.append(string); 155 sb.append("</string></b><br>"); //$NON-NLS-1$ 156 sb.append("</resources>"); //$NON-NLS-1$ 157 158 return sb.toString(); 159 } catch (JavaModelException e) { 160 AdtPlugin.log(e, null); 161 } 162 163 return "Initiates the Extract String refactoring operation"; 164 } 165 166 @Override getDisplayString()167 public String getDisplayString() { 168 return "Extract String"; 169 } 170 171 @Override getImage()172 public Image getImage() { 173 return AdtPlugin.getAndroidLogo(); 174 } 175 176 @Override getContextInformation()177 public IContextInformation getContextInformation() { 178 return null; 179 } 180 181 @Override getRelevance()182 public int getRelevance() { 183 return 80; 184 } 185 }