blob: d51db7ce49efaab39d098a9806cd2a209f19fd23 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 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.util.ArrayList;
import java.util.List;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.compiler.IScanner;
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
import org.eclipse.jdt.core.compiler.InvalidInputException;
public class NLSScanner {
//no instances
private NLSScanner() {
}
/**
* Returns a list of NLSLines found in the compilation unit
*/
public static NLSLine[] scan(ICompilationUnit cu) throws JavaModelException, InvalidInputException {
return scan(cu.getBuffer().getCharacters());
}
/**
* Returns a list of NLSLines found in the string
*/
public static NLSLine[] scan(String s) throws InvalidInputException {
return scan(s.toCharArray());
}
private static NLSLine[] scan(char[] content) throws InvalidInputException {
List lines= new ArrayList();
IScanner scanner= ToolFactory.createScanner(true, true, false, true);
scanner.setSource(content);
int token= scanner.getNextToken();
int currentLineNr= -1;
int previousLineNr= -1;
NLSLine currentLine= null;
int nlsElementIndex= 0;
while (token != ITerminalSymbols.TokenNameEOF) {
switch (token) {
case ITerminalSymbols.TokenNameStringLiteral:
currentLineNr= scanner.getLineNumber(scanner.getCurrentTokenStartPosition());
if (currentLineNr != previousLineNr) {
currentLine= new NLSLine(currentLineNr - 1);
lines.add(currentLine);
previousLineNr= currentLineNr;
nlsElementIndex= 0;
}
String value= new String(scanner.getCurrentTokenSource());
currentLine.add(
new NLSElement(
value,
scanner.getCurrentTokenStartPosition(),
scanner.getCurrentTokenEndPosition() + 1 - scanner.getCurrentTokenStartPosition(),
nlsElementIndex++,
false));
break;
case ITerminalSymbols.TokenNameCOMMENT_LINE:
if (currentLineNr != scanner.getLineNumber(scanner.getCurrentTokenStartPosition()))
break;
parseTags(currentLine, scanner);
break;
}
token= scanner.getNextToken();
}
NLSLine[] result;
try {
result= (NLSLine[]) lines.toArray(new NLSLine[lines.size()]);
IDocument document= new Document(String.valueOf(scanner.getSource()));
for (int i= 0; i < result.length; i++) {
setTagPositions(document, result[i]);
}
} catch (BadLocationException exception) {
throw new InvalidInputException();
}
return result;
}
private static void parseTags(NLSLine line, IScanner scanner) {
String s= new String(scanner.getCurrentTokenSource());
int pos= s.indexOf(NLSElement.TAG_PREFIX);
while (pos != -1) {
int start= pos + NLSElement.TAG_PREFIX_LENGTH;
int end= s.indexOf(NLSElement.TAG_POSTFIX, start);
if (end < 0)
return; //no error recovery
String index= s.substring(start, end);
int i= 0;
try {
i= Integer.parseInt(index) - 1; // Tags are one based not zero based.
} catch (NumberFormatException e) {
return; //ignore the exception - no error recovery
}
if (line.exists(i)) {
NLSElement element= line.get(i);
element.setTagPosition(scanner.getCurrentTokenStartPosition() + pos, end - pos + 1);
} else {
return; //no error recovery
}
pos= s.indexOf(NLSElement.TAG_PREFIX, start);
}
}
private static void setTagPositions(IDocument document, NLSLine line) throws BadLocationException {
IRegion info= document.getLineInformation(line.getLineNumber());
int defaultValue= info.getOffset() + info.getLength();
NLSElement[] elements= line.getElements();
for (int i= 0; i < elements.length; i++) {
NLSElement element= elements[i];
if (!element.hasTag()) {
element.setTagPosition(computeInsertOffset(elements, i, defaultValue), 0);
}
}
}
private static int computeInsertOffset(NLSElement[] elements, int index, int defaultValue) {
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 defaultValue;
}
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;
}
}