1/******************************************************************************* 2 * Copyright (c) 2009, 2018 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 *******************************************************************************/ 12package org.jacoco.report.internal.html.page; 13 14import java.io.BufferedReader; 15import java.io.IOException; 16import java.io.Reader; 17import java.util.Locale; 18 19import org.jacoco.core.analysis.ICounter; 20import org.jacoco.core.analysis.ILine; 21import org.jacoco.core.analysis.ISourceNode; 22import org.jacoco.report.internal.html.HTMLElement; 23import org.jacoco.report.internal.html.resources.Styles; 24 25/** 26 * Creates a highlighted output of a source file. 27 */ 28final class SourceHighlighter { 29 30 private final Locale locale; 31 32 private String lang; 33 34 /** 35 * Creates a new highlighter with default settings. 36 * 37 * @param locale 38 * locale for tooltip rendering 39 */ 40 public SourceHighlighter(final Locale locale) { 41 this.locale = locale; 42 lang = "java"; 43 } 44 45 /** 46 * Specifies the source language. This value might be used for syntax 47 * highlighting. Default is "java". 48 * 49 * @param lang 50 * source language identifier 51 */ 52 public void setLanguage(final String lang) { 53 this.lang = lang; 54 } 55 56 /** 57 * Highlights the given source file. 58 * 59 * @param parent 60 * parent HTML element 61 * @param source 62 * highlighting information 63 * @param contents 64 * contents of the source file 65 * @throws IOException 66 * problems while reading the source file or writing the output 67 */ 68 public void render(final HTMLElement parent, final ISourceNode source, 69 final Reader contents) throws IOException { 70 final HTMLElement pre = parent.pre(Styles.SOURCE + " lang-" + lang 71 + " linenums"); 72 final BufferedReader lineBuffer = new BufferedReader(contents); 73 String line; 74 int nr = 0; 75 while ((line = lineBuffer.readLine()) != null) { 76 nr++; 77 renderCodeLine(pre, line, source.getLine(nr), nr); 78 } 79 } 80 81 private void renderCodeLine(final HTMLElement pre, final String linesrc, 82 final ILine line, final int lineNr) throws IOException { 83 highlight(pre, line, lineNr).text(linesrc); 84 pre.text("\n"); 85 } 86 87 HTMLElement highlight(final HTMLElement pre, final ILine line, 88 final int lineNr) throws IOException { 89 final String style; 90 switch (line.getStatus()) { 91 case ICounter.NOT_COVERED: 92 style = Styles.NOT_COVERED; 93 break; 94 case ICounter.FULLY_COVERED: 95 style = Styles.FULLY_COVERED; 96 break; 97 case ICounter.PARTLY_COVERED: 98 style = Styles.PARTLY_COVERED; 99 break; 100 default: 101 return pre; 102 } 103 104 final String lineId = "L" + Integer.toString(lineNr); 105 final ICounter branches = line.getBranchCounter(); 106 switch (branches.getStatus()) { 107 case ICounter.NOT_COVERED: 108 return span(pre, lineId, style, Styles.BRANCH_NOT_COVERED, 109 "All %2$d branches missed.", branches); 110 case ICounter.FULLY_COVERED: 111 return span(pre, lineId, style, Styles.BRANCH_FULLY_COVERED, 112 "All %2$d branches covered.", branches); 113 case ICounter.PARTLY_COVERED: 114 return span(pre, lineId, style, Styles.BRANCH_PARTLY_COVERED, 115 "%1$d of %2$d branches missed.", branches); 116 default: 117 return pre.span(style, lineId); 118 } 119 } 120 121 private HTMLElement span(final HTMLElement parent, final String id, 122 final String style1, final String style2, final String title, 123 final ICounter branches) throws IOException { 124 final HTMLElement span = parent.span(style1 + " " + style2, id); 125 final Integer missed = Integer.valueOf(branches.getMissedCount()); 126 final Integer total = Integer.valueOf(branches.getTotalCount()); 127 span.attr("title", String.format(locale, title, missed, total)); 128 return span; 129 } 130 131} 132