/******************************************************************************* * Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors * 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: * Marc R. Hoffmann - initial API and implementation * *******************************************************************************/ package org.jacoco.core.test.validation; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Reads a single source file and allows access to it through special probe * comments in the following format //$line-tag$. */ public class Source { /** * Reads the source for the given type from the given source folder relative * to the working directory. * * @param srcFolder * source folder * @param type * type to load the source file for */ public static Source getSourceFor(final String srcFolder, final Class type) throws IOException { File folder = new File(srcFolder); File file = new File(folder, type.getName().replace('.', '/') + ".java"); return new Source(new FileReader(file)); } private static final Pattern TAG_PATTERN = Pattern .compile("\\$line-(.*)\\$"); private final List lines = new ArrayList(); private final Map tags = new HashMap(); /** * Reads a source file from the given reader. * * @param reader * @throws IOException */ public Source(final Reader reader) throws IOException { final BufferedReader buffer = new BufferedReader(reader); for (String l = buffer.readLine(); l != null; l = buffer.readLine()) { addLine(l); } buffer.close(); } private void addLine(final String l) { lines.add(l); final Matcher m = TAG_PATTERN.matcher(l); if (m.find()) { final String tag = m.group(1); if (tags.put(tag, Integer.valueOf(lines.size())) != null) { throw new IllegalArgumentException("Duplicate tag: " + tag); } } } /** * Returns all lines of the source file as a list. * * @return all lines of the source file */ public List getLines() { return Collections.unmodifiableList(lines); } /** * Returns the line with the given number * * @param nr * line number (first line is 1) * @return line content */ public String getLine(int nr) { return lines.get(nr - 1); } /** * Returns the line number with the given tag * * @param tag * tag from a //$line-tag$ marker * @return line number (first line is 1) * @throws NoSuchElementException * if there is no such tag */ public int getLineNumber(String tag) throws NoSuchElementException { final Integer nr = tags.get(tag); if (nr == null) { throw new NoSuchElementException("Unknown tag: " + tag); } return nr.intValue(); } }