1/******************************************************************************* 2 * Copyright (c) 2009, 2017 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.core.test.validation; 13 14import java.io.BufferedReader; 15import java.io.File; 16import java.io.FileReader; 17import java.io.IOException; 18import java.io.Reader; 19import java.util.ArrayList; 20import java.util.Collections; 21import java.util.HashMap; 22import java.util.List; 23import java.util.Map; 24import java.util.NoSuchElementException; 25import java.util.regex.Matcher; 26import java.util.regex.Pattern; 27 28/** 29 * Reads a single source file and allows access to it through special probe 30 * comments in the following format <code>//$line-<i>tag</i>$. 31 */ 32public class Source { 33 34 /** 35 * Reads the source for the given type from the given source folder relative 36 * to the working directory. 37 * 38 * @param srcFolder 39 * source folder 40 * @param type 41 * type to load the source file for 42 */ 43 public static Source getSourceFor(final String srcFolder, 44 final Class<?> type) throws IOException { 45 File folder = new File(srcFolder); 46 File file = new File(folder, type.getName().replace('.', '/') + ".java"); 47 return new Source(new FileReader(file)); 48 } 49 50 private static final Pattern TAG_PATTERN = Pattern 51 .compile("\\$line-(.*)\\$"); 52 53 private final List<String> lines = new ArrayList<String>(); 54 55 private final Map<String, Integer> tags = new HashMap<String, Integer>(); 56 57 /** 58 * Reads a source file from the given reader. 59 * 60 * @param reader 61 * @throws IOException 62 */ 63 public Source(final Reader reader) throws IOException { 64 final BufferedReader buffer = new BufferedReader(reader); 65 for (String l = buffer.readLine(); l != null; l = buffer.readLine()) { 66 addLine(l); 67 } 68 buffer.close(); 69 } 70 71 private void addLine(final String l) { 72 lines.add(l); 73 final Matcher m = TAG_PATTERN.matcher(l); 74 if (m.find()) { 75 final String tag = m.group(1); 76 if (tags.put(tag, Integer.valueOf(lines.size())) != null) { 77 throw new IllegalArgumentException("Duplicate tag: " + tag); 78 } 79 } 80 } 81 82 /** 83 * Returns all lines of the source file as a list. 84 * 85 * @return all lines of the source file 86 */ 87 public List<String> getLines() { 88 return Collections.unmodifiableList(lines); 89 } 90 91 /** 92 * Returns the line with the given number 93 * 94 * @param nr 95 * line number (first line is 1) 96 * @return line content 97 */ 98 public String getLine(int nr) { 99 return lines.get(nr - 1); 100 } 101 102 /** 103 * Returns the line number with the given tag 104 * 105 * @param tag 106 * tag from a <code>//$line-<i>tag</i>$ marker 107 * @return line number (first line is 1) 108 * @throws NoSuchElementException 109 * if there is no such tag 110 */ 111 public int getLineNumber(String tag) throws NoSuchElementException { 112 final Integer nr = tags.get(tag); 113 if (nr == null) { 114 throw new NoSuchElementException("Unknown tag: " + tag); 115 } 116 return nr.intValue(); 117 } 118 119} 120