blob: 5f0a2b4e5e40741073912a87971cb1d2efea512b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2009 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
* Matt McCutchen - fix for bug 197169 and complementary fix for 109636
*******************************************************************************/
package org.eclipse.jdt.internal.formatter.comment;
import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.internal.compiler.parser.*;
/**
* <code>SubstitutionTextReader</code> that will substitute html entities for
* html symbols encountered in the original text. Line breaks and whitespaces
* are preserved.
*
* @since 3.0
*/
public class Java2HTMLEntityReader extends SubstitutionTextReader {
private static final int BEGIN_LINE = 0x01;
/** The hardcoded entity map. */
private static final Map fgEntityLookup;
/**
* True if we have not yet seen a non-whitespace character on the current
* line.
*/
private int bits = BEGIN_LINE;
static {
fgEntityLookup= new HashMap(7);
fgEntityLookup.put("<", "&lt;"); //$NON-NLS-1$ //$NON-NLS-2$
fgEntityLookup.put(">", "&gt;"); //$NON-NLS-1$ //$NON-NLS-2$
fgEntityLookup.put("&", "&amp;"); //$NON-NLS-1$ //$NON-NLS-2$
fgEntityLookup.put("^", "&circ;"); //$NON-NLS-1$ //$NON-NLS-2$
fgEntityLookup.put("~", "&tilde;"); //$NON-NLS-2$ //$NON-NLS-1$
fgEntityLookup.put("\"", "&quot;"); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Creates a new instance that will read from <code>reader</code>
*
* @param reader the source reader
*/
public Java2HTMLEntityReader(Reader reader) {
super(reader);
setSkipWhitespace(false);
}
/*
* @see org.eclipse.jdt.internal.ui.text.SubstitutionTextReader#computeSubstitution(int)
*/
protected String computeSubstitution(int c) throws IOException {
StringBuffer buf = new StringBuffer();
// Accumulate *s into the buffer until we see something other than *.
while (c == '*') {
this.bits &= ~BEGIN_LINE;
c = nextChar();
buf.append('*');
}
if (c == -1)
// Snippet must have ended with *s. Just return them.
return buf.toString();
if (c == '/' && buf.length() > 0) {
/*
* Translate a * that precedes a / to &#42; so it isn't
* misinterpreted as the end of the Javadoc comment that contains
* the code we are formatting.
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=109636
*/
buf.setLength(buf.length() - 1);
buf.append("&#42;/"); //$NON-NLS-1$
} else if (c == '@' && (this.bits & BEGIN_LINE) != 0) {
/*
* When @ is first on a line, translate it to &#064; so it isn't
* misinterpreted as a Javadoc tag.
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=197169
*/
buf.append("&#064;"); //$NON-NLS-1$
} else {
/*
* Ordinary processing. If the character needs an entity in HTML,
* add the entity, otherwise add the character.
*/
String entity = (String) fgEntityLookup.get(String.valueOf((char) c));
if (entity != null)
buf.append(entity);
else
buf.append((char) c);
}
// Update bits for the benefit of the next character.
if (c == '\n' || c == '\r') {
this.bits |= BEGIN_LINE;
} else if (!ScannerHelper.isWhitespace((char) c)) {
this.bits &= ~BEGIN_LINE;
}
return buf.toString();
}
}