| /******************************************************************************* |
| * Copyright (c) 2000, 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.corext.refactoring.nls; |
| |
| import java.io.BufferedReader; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| import org.eclipse.text.edits.InsertEdit; |
| import org.eclipse.text.edits.TextEdit; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| |
| import org.eclipse.jface.text.Region; |
| |
| import org.eclipse.jdt.core.IBuffer; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.compiler.InvalidInputException; |
| import org.eclipse.jdt.core.formatter.IndentManipulation; |
| |
| |
| public class NLSUtil { |
| |
| //no instances |
| private NLSUtil() { |
| } |
| |
| /** |
| * Returns null if an error occurred. |
| * closes the stream |
| */ |
| public static String readString(InputStream is) { |
| if (is == null) |
| return null; |
| BufferedReader reader= null; |
| try { |
| StringBuffer buffer= new StringBuffer(); |
| char[] part= new char[2048]; |
| int read= 0; |
| reader= new BufferedReader(new InputStreamReader(is, "8859_1")); //$NON-NLS-1$ |
| |
| while ((read= reader.read(part)) != -1) |
| buffer.append(part, 0, read); |
| |
| return buffer.toString(); |
| |
| } catch (IOException ex) { |
| } finally { |
| if (reader != null) { |
| try { |
| reader.close(); |
| } catch (IOException ex) { |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Creates and returns an NLS tag edit for a string that is at the specified position in |
| * a compilation unit. Returns <code>null</code> if the string is already NLSed |
| * or the edit could not be created for some other reason. |
| * @throws CoreException |
| */ |
| public static TextEdit createNLSEdit(ICompilationUnit cu, int position) throws CoreException { |
| NLSLine nlsLine= scanCurrentLine(cu, position); |
| if (nlsLine == null) |
| return null; |
| NLSElement element= findElement(nlsLine, position); |
| if (element.hasTag()) |
| return null; |
| NLSElement[] elements= nlsLine.getElements(); |
| int indexInElementList= Arrays.asList(elements).indexOf(element); |
| int editOffset= computeInsertOffset(elements, indexInElementList, cu); |
| String editText= ' ' + NLSElement.createTagText(indexInElementList + 1); //tags are 1-based |
| return new InsertEdit(editOffset, editText); |
| } |
| |
| /** |
| * Creates and returns NLS tag edits for strings that are at the specified positions in |
| * a compilation unit. Returns <code>null</code> if all the strings are already NLSed |
| * or the edits could not be created for some other reason. |
| * @throws CoreException |
| */ |
| public static TextEdit[] createNLSEdits(ICompilationUnit cu, int[] positions) throws CoreException { |
| List result= new ArrayList(); |
| try { |
| NLSLine[] allLines= NLSScanner.scan(cu); |
| for (int i= 0; i < allLines.length; i++) { |
| NLSLine line= allLines[i]; |
| NLSElement[] elements= line.getElements(); |
| for (int j= 0; j < elements.length; j++) { |
| NLSElement element= elements[j]; |
| if (!element.hasTag()) { |
| for (int k= 0; k < positions.length; k++) { |
| if (isPositionInElement(element, positions[k])) { |
| int editOffset; |
| if (j==0) { |
| if (elements.length > j+1) { |
| editOffset= elements[j+1].getTagPosition().getOffset(); |
| } else { |
| editOffset= findLineEnd(cu, element.getPosition().getOffset()); |
| } |
| } else { |
| Region previousPosition= elements[j-1].getTagPosition(); |
| editOffset= previousPosition.getOffset() + previousPosition.getLength(); |
| } |
| String editText= ' ' + NLSElement.createTagText(j + 1); //tags are 1-based |
| result.add(new InsertEdit(editOffset, editText)); |
| } |
| } |
| } |
| } |
| } |
| } catch (InvalidInputException e) { |
| return null; |
| } |
| if (result.isEmpty()) |
| return null; |
| |
| return (TextEdit[])result.toArray(new TextEdit[result.size()]); |
| } |
| |
| private static NLSLine scanCurrentLine(ICompilationUnit cu, int position) throws JavaModelException { |
| try { |
| Assert.isTrue(position >= 0 && position <= cu.getBuffer().getLength()); |
| NLSLine[] allLines= NLSScanner.scan(cu); |
| for (int i= 0; i < allLines.length; i++) { |
| NLSLine line= allLines[i]; |
| if (findElement(line, position) != null) |
| return line; |
| } |
| return null; |
| } catch (InvalidInputException e) { |
| return null; |
| } |
| } |
| |
| private static boolean isPositionInElement(NLSElement element, int position) { |
| Region elementPosition= element.getPosition(); |
| return (elementPosition.getOffset() <= position && position <= elementPosition.getOffset() + elementPosition.getLength()); |
| } |
| |
| private static NLSElement findElement(NLSLine line, int position) { |
| NLSElement[] elements= line.getElements(); |
| for (int i= 0; i < elements.length; i++) { |
| NLSElement element= elements[i]; |
| if (isPositionInElement(element, position)) |
| return element; |
| } |
| return null; |
| } |
| |
| //we try to find a good place to put the nls tag |
| //first, try to find the previous nlsed-string and try putting after its tag |
| //if no such string exists, try finding the next nlsed-string try putting before its tag |
| //otherwise, find the line end and put the tag there |
| private static int computeInsertOffset(NLSElement[] elements, int index, ICompilationUnit cu) throws CoreException { |
| NLSElement previousTagged= findPreviousTagged(index, elements); |
| if (previousTagged != null) |
| return previousTagged.getTagPosition().getOffset() + previousTagged.getTagPosition().getLength(); |
| NLSElement nextTagged= findNextTagged(index, elements); |
| if (nextTagged != null) |
| return nextTagged.getTagPosition().getOffset(); |
| return findLineEnd(cu, elements[index].getPosition().getOffset()); |
| } |
| |
| private static NLSElement findPreviousTagged(int startIndex, NLSElement[] elements) { |
| int i= startIndex - 1; |
| while (i >= 0) { |
| if (elements[i].hasTag()) |
| return elements[i]; |
| i--; |
| } |
| return null; |
| } |
| |
| private static NLSElement findNextTagged(int startIndex, NLSElement[] elements) { |
| int i= startIndex + 1; |
| while (i < elements.length) { |
| if (elements[i].hasTag()) |
| return elements[i]; |
| i++; |
| } |
| return null; |
| } |
| |
| private static int findLineEnd(ICompilationUnit cu, int position) throws JavaModelException { |
| IBuffer buffer= cu.getBuffer(); |
| int length= buffer.getLength(); |
| for (int i= position; i < length; i++) { |
| if (IndentManipulation.isLineDelimiterChar(buffer.getChar(i))) { |
| return i; |
| } |
| } |
| return length; |
| } |
| } |