SourceHighlighter.java
1/*******************************************************************************
2 * Copyright (c) 2009, 2010 Mountainminds GmbH & Co. KG and Contributors
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Marc R. Hoffmann - initial API and implementation
10 *
11 * $Id: $
12 *******************************************************************************/
13package org.jacoco.report.html;
14
15import java.io.BufferedReader;
16import java.io.IOException;
17import java.io.Reader;
18import java.util.Arrays;
19
20import org.jacoco.core.analysis.ILines;
21import org.jacoco.report.html.resources.Styles;
22
23/**
24 * Creates a highlighted output of a source file.
25 *
26 * @author Marc R. Hoffmann
27 * @version $Revision: $
28 */
29public class SourceHighlighter {
30
31 /** Number of characters reserved for the line number column */
32 private static final int LINENR_WIDTH = 5;
33
34 private String tabReplacement;
35
36 private String lang = "java";
37
38 /**
39 * Creates a new highlighter with default settings.
40 */
41 public SourceHighlighter() {
42 setTabWidth(4);
43 }
44
45 /**
46 * Specifies the number of spaces that are represented by a single tab.
47 * Default is 4.
48 *
49 * @param width
50 * spaces per tab
51 */
52 public void setTabWidth(final int width) {
53 final char[] blanks = new char[width];
54 Arrays.fill(blanks, ' ');
55 tabReplacement = new String(blanks);
56 }
57
58 /**
59 * Specifies the source language. This value might be used for syntax
60 * highlighting. Default is "java".
61 *
62 * @param lang
63 * source language identifier
64 */
65 public void setLanguage(final String lang) {
66 this.lang = lang;
67 }
68
69 /**
70 * Highlights the given source file.
71 *
72 * @param parent
73 * parent HTML element
74 * @param lines
75 * highlighting information
76 * @param contents
77 * contents of the source file
78 * @throws IOException
79 * problems while reading the source file or writing the output
80 */
81 public void render(final HTMLElement parent, final ILines lines,
82 final Reader contents) throws IOException {
83 final HTMLElement pre = parent.pre(Styles.SOURCE + " lang-" + lang);
84 final BufferedReader lineBuffer = new BufferedReader(contents);
85 String line;
86 int nr = 0;
87 while ((line = lineBuffer.readLine()) != null) {
88 nr++;
89 renderLineNr(pre, nr);
90 renderCodeLine(pre, line, lines.getStatus(nr));
91 }
92 }
93
94 private void renderLineNr(final HTMLElement pre, final int nr)
95 throws IOException {
96 final String linestr = String.valueOf(nr);
97 final HTMLElement linespan = pre.span(Styles.NR, "L" + linestr);
98 for (int i = linestr.length(); i < LINENR_WIDTH; i++) {
99 linespan.text("\u00A0"); // non-breaking space
100 }
101 linespan.text(linestr);
102 }
103
104 private void renderCodeLine(final HTMLElement pre, final String line,
105 final int status) throws IOException {
106 final String lineWithoutTabs = line.replace("\t", tabReplacement);
107 switch (status) {
108 case ILines.NOT_COVERED:
109 pre.span(Styles.NOT_COVERED).text(lineWithoutTabs);
110 break;
111 case ILines.FULLY_COVERED:
112 pre.span(Styles.FULLY_COVERED).text(lineWithoutTabs);
113 break;
114 case ILines.PARTLY_COVERED:
115 pre.span(Styles.PARTLY_COVERED).text(lineWithoutTabs);
116 break;
117 default:
118 pre.text(lineWithoutTabs);
119 }
120 pre.text("\n");
121 }
122
123}