JFlexXref.java revision 1020
883N/A/*
883N/A * CDDL HEADER START
883N/A *
883N/A * The contents of this file are subject to the terms of the
883N/A * Common Development and Distribution License (the "License").
883N/A * You may not use this file except in compliance with the License.
883N/A *
883N/A * See LICENSE.txt included in this distribution for the specific
883N/A * language governing permissions and limitations under the License.
883N/A *
883N/A * When distributing Covered Code, include this CDDL HEADER in each
883N/A * file and include the License file at LICENSE.txt.
883N/A * If applicable, add the following below this CDDL HEADER, with the
883N/A * fields enclosed by brackets "[]" replaced with your own identifying
883N/A * information: Portions Copyright [yyyy] [name of copyright owner]
883N/A *
883N/A * CDDL HEADER END
883N/A */
883N/A
883N/A/*
883N/A * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
883N/A * Use is subject to license terms.
3734N/A */
883N/A
883N/Apackage org.opensolaris.opengrok.analysis;
3734N/A
3734N/Aimport java.io.IOException;
3734N/Aimport java.io.Writer;
3734N/Aimport java.lang.reflect.Field;
3734N/Aimport java.util.Set;
3734N/Aimport org.opensolaris.opengrok.configuration.Project;
3734N/Aimport org.opensolaris.opengrok.configuration.RuntimeEnvironment;
883N/Aimport org.opensolaris.opengrok.history.Annotation;
956N/Aimport org.opensolaris.opengrok.web.Util;
3734N/A
3734N/A/**
883N/A * Base class for Xref lexers.
883N/A *
883N/A * @author Lubos Kosco
883N/A */
3734N/Apublic abstract class JFlexXref {
883N/A public Writer out;
3734N/A public String urlPrefix = RuntimeEnvironment.getInstance().getUrlPrefix();
3734N/A public Annotation annotation;
3734N/A public Project project;
3734N/A protected Definitions defs;
3734N/A
883N/A /** EOF value returned by yylex(). */
3734N/A private final int yyeof;
3734N/A
3734N/A protected JFlexXref() {
3734N/A try {
883N/A // TODO when bug #16053 is fixed, we should add a getter to a file
883N/A // that's included from all the Xref classes so that we avoid the
3734N/A // reflection.
3734N/A Field f = getClass().getField("YYEOF");
3734N/A yyeof = f.getInt(null);
3734N/A } catch (Exception e) {
// The auto-generated constructors for the Xref classes don't
// expect a checked exception, so wrap it in an AssertionError.
// This should never happen, since all the Xref classes will get
// a public static YYEOF field from JFlex.
AssertionError ae = new AssertionError("Couldn't initialize yyeof");
ae.initCause(e);
throw ae; // NOPMD (stack trace is preserved by initCause(), but PMD
// thinks it's lost)
}
}
public void setDefs(Definitions defs) {
this.defs = defs;
}
protected void appendProject() throws IOException {
if (project != null) {
out.write("&project=");
out.write(project.getDescription());
}
}
protected String getProjectPostfix() {
return project == null ? "" : ("&project=" + project.getDescription());
}
/** Get the next token from the scanner. */
public abstract int yylex() throws IOException;
/** Get the value of {@code yyline}. */
protected abstract int getLineNumber();
/** Set the value of {@code yyline}. */
protected abstract void setLineNumber(int x);
/**
* Write xref to the specified {@code Writer}.
*
* @param out xref destination
* @throws IOException on error when writing the xref
*/
public void write(Writer out) throws IOException {
this.out = out;
setLineNumber(0);
startNewLine();
while (yylex() != yyeof) { // NOPMD while statement intentionally empty
// nothing to do here, yylex() will do the work
}
}
/**
* Terminate the current line and insert preamble for the next line. The
* line count will be incremented.
*
* @throws IOException on error when writing the xref
*/
protected void startNewLine() throws IOException {
int line = getLineNumber() + 1;
setLineNumber(line);
Util.readableLine(line, out, annotation);
}
/**
* Write a symbol and generate links as appropriate.
*
* @param symbol the symbol to write
* @param keywords a set of keywords recognized by this analyzer (no links
* will be generated if the symbol is a keyword)
* @param line the line number on which the symbol appears
* @throws IOException if an error occurs while writing to the stream
*/
protected void writeSymbol(String symbol, Set<String> keywords, int line)
throws IOException {
if (keywords.contains(symbol)) {
// This is a keyword, so we don't create a link.
out.append("<b>").append(symbol).append("</b>");
} else if (defs != null && defs.hasDefinitionAt(symbol, line)) {
// This is the definition of the symbol.
// 1) Create an anchor for direct links. (Perhaps, we should only
// do this when there's exactly one definition of the symbol in
// this file? Otherwise, we may end up with multiple anchors with
// the same name.)
out.append("<a class=\"d\" name=\"").append(symbol).append("\"/>");
// 2) Create a link that searches for all references to this symbol.
out.append("<a href=\"").append(urlPrefix).append("refs=");
out.append(symbol);
appendProject();
out.append("\" class=\"d\">").append(symbol).append("</a>");
} else if (defs != null && defs.occurrences(symbol) == 1) {
// This is a reference to a symbol defined exactly once in this file.
// Generate a direct link to the symbol definition.
out.append("<a class=\"f\" href=\"#").append(symbol).append("\">")
.append(symbol).append("</a>");
} else {
// This is a symbol that is not defined in this file, or a symbol
// that is defined more than once in this file. In either case, we
// can't generate a direct link to the definition, so generate a
// link to search for all definitions of that symbol instead.
out.append("<a href=\"").append(urlPrefix).append("defs=");
out.append(symbol);
appendProject();
out.append("\">").append(symbol).append("</a>");
}
}
/**
* Write HTML escape sequence for the specified Unicode character, unless
* it's an ISO control character, in which case it is ignored.
*
* @param c the character to write
* @throws IOException if an error occurs while writing to the stream
*/
protected void writeUnicodeChar(char c) throws IOException {
if (!Character.isISOControl(c)) {
out.append("&#").append(Integer.toString((int) c)).append(';');
}
}
}