blob: 1b6711b546704cbf5c24420372ef078d79c52e91 [file] [log] [blame]
/*******************************************************************************
* 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;
}
}