GitHub #288: New agent option 'inclnolocationclasses'
With the new agent option 'inclnolocationclasses' classes without source
location can be optionally included. This helps to retrieve code
coverage for environments like Android where no source location is
provided at runtime.
diff --git a/jacoco-maven-plugin.test/it/it-customize-agent/pom.xml b/jacoco-maven-plugin.test/it/it-customize-agent/pom.xml
index 53d208f..5f3b653 100644
--- a/jacoco-maven-plugin.test/it/it-customize-agent/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-customize-agent/pom.xml
@@ -26,12 +26,15 @@
<jacoco.destFile>${project.build.directory}/coverage.exec</jacoco.destFile>
<jacoco.append>false</jacoco.append>
<jacoco.exclClassLoaders>sun.reflect.DelegatingClassLoader:MyClassLoader</jacoco.exclClassLoaders>
+ <jacoco.inclBootstrapClasses>true</jacoco.inclBootstrapClasses>
+ <jacoco.inclNoLocationClasses>true</jacoco.inclNoLocationClasses>
<jacoco.sessionId>session</jacoco.sessionId>
<jacoco.dumpOnExit>true</jacoco.dumpOnExit>
<jacoco.output>file</jacoco.output>
<jacoco.address>localhost</jacoco.address>
<jacoco.port>9999</jacoco.port>
<jacoco.classDumpDir>${project.build.directory}/classdumps</jacoco.classDumpDir>
+ <jacoco.jmx>true</jacoco.jmx>
</properties>
<build>
diff --git a/jacoco-maven-plugin.test/it/it-customize-agent/verify.bsh b/jacoco-maven-plugin.test/it/it-customize-agent/verify.bsh
index 43c91d0..7dc56e5 100644
--- a/jacoco-maven-plugin.test/it/it-customize-agent/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-customize-agent/verify.bsh
@@ -17,12 +17,15 @@
+ ",includes=*"
+ ",excludes=java.*:sun.*"
+ ",exclclassloader=sun.reflect.DelegatingClassLoader:MyClassLoader"
+ + ",inclbootstrapclasses=true"
+ + ",inclnolocationclasses=true"
+ ",sessionid=session"
+ ",dumponexit=true"
+ ",output=file"
+ ",address=localhost"
+ ",port=9999"
- + ",classdumpdir=" + basedir + File.separator + "target" + File.separator + "classdumps";
+ + ",classdumpdir=" + basedir + File.separator + "target" + File.separator + "classdumps"
+ + ",jmx=true";
//backslashes will be escaped
agentOptions = agentOptions.replace("\\","\\\\");
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/AbstractAgentMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/AbstractAgentMojo.java
index 6be31ca..51e7529 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/AbstractAgentMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/AbstractAgentMojo.java
@@ -81,6 +81,12 @@
*/
Boolean inclBootstrapClasses;
/**
+ * Specifies whether classes without source location should be instrumented.
+ *
+ * @parameter property="jacoco.inclNoLocationClasses"
+ */
+ Boolean inclNoLocationClasses;
+ /**
* A session identifier that is written with the execution data. Without
* this parameter a random identifier is created by the agent.
*
@@ -190,6 +196,10 @@
agentOptions.setInclBootstrapClasses(inclBootstrapClasses
.booleanValue());
}
+ if (inclNoLocationClasses != null) {
+ agentOptions.setInclNoLocationClasses(inclNoLocationClasses
+ .booleanValue());
+ }
if (sessionId != null) {
agentOptions.setSessionId(sessionId);
}
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/CoverageTransformerTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/CoverageTransformerTest.java
index 572d120..68693d8 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/CoverageTransformerTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/CoverageTransformerTest.java
@@ -63,51 +63,25 @@
}
@Test
- public void testHasSourceLocationNegative1() {
- CoverageTransformer t = createTransformer();
- assertFalse(t.hasSourceLocation(null));
- }
-
- @Test
- public void testHasSourceLocationNegative2() {
- CoverageTransformer t = createTransformer();
- ProtectionDomain pd = new ProtectionDomain(null, null);
- assertFalse(t.hasSourceLocation(pd));
- }
-
- @Test
- public void testHasSourceLocationNegative3() {
- CoverageTransformer t = createTransformer();
- CodeSource cs = new CodeSource(null, new Certificate[0]);
- ProtectionDomain pd = new ProtectionDomain(cs, null);
- assertFalse(t.hasSourceLocation(pd));
- }
-
- @Test
- public void testHasSourceLocationPositive() {
- CoverageTransformer t = createTransformer();
- assertTrue(t.hasSourceLocation(protectionDomain));
- }
-
- @Test
public void testFilterAgentClass() {
CoverageTransformer t = createTransformer();
assertFalse(t.filter(classLoader,
- "org/jacoco/agent/rt/internal/somepkg/SomeClass"));
+ "org/jacoco/agent/rt/internal/somepkg/SomeClass",
+ protectionDomain));
}
@Test
- public void testFilterIncludesBootstrapClassesPositive() {
+ public void testFilterInclBootstrapClassesPositive() {
options.setInclBootstrapClasses(true);
CoverageTransformer t = createTransformer();
- assertTrue(t.filter(null, "java/util/TreeSet"));
+ assertTrue(t.filter(null, "java/util/TreeSet", protectionDomain));
}
@Test
- public void testFilterIncludesBootstrapClassesNegative() {
+ public void testFilterInclBootstrapClassesNegative() {
options.setInclBootstrapClasses(false);
CoverageTransformer t = createTransformer();
- assertFalse(t.filter(null, "java/util/TreeSet"));
+ assertFalse(t.filter(null, "java/util/TreeSet", protectionDomain));
}
@Test
@@ -115,7 +89,7 @@
options.setInclBootstrapClasses(false);
options.setExclClassloader("org.jacoco.agent.SomeWhere$*");
CoverageTransformer t = createTransformer();
- assertTrue(t.filter(classLoader, "org/example/Foo"));
+ assertTrue(t.filter(classLoader, "org/example/Foo", protectionDomain));
}
@Test
@@ -123,7 +97,7 @@
options.setInclBootstrapClasses(true);
options.setExclClassloader("org.jacoco.agent.SomeWhere$*");
CoverageTransformer t = createTransformer();
- assertTrue(t.filter(classLoader, "org/example/Foo"));
+ assertTrue(t.filter(classLoader, "org/example/Foo", protectionDomain));
}
@Test
@@ -133,7 +107,8 @@
CoverageTransformer t = createTransformer();
ClassLoader myClassLoader = new ClassLoader(null) {
};
- assertFalse(t.filter(myClassLoader, "org/example/Foo"));
+ assertFalse(t
+ .filter(myClassLoader, "org/example/Foo", protectionDomain));
}
@Test
@@ -143,42 +118,76 @@
CoverageTransformer t = createTransformer();
ClassLoader myClassLoader = new ClassLoader(null) {
};
- assertFalse(t.filter(myClassLoader, "org/example/Foo"));
+ assertFalse(t
+ .filter(myClassLoader, "org/example/Foo", protectionDomain));
}
@Test
public void testFilterIncludedClassPositive() {
options.setIncludes("org.jacoco.core.*:org.jacoco.agent.rt.*");
CoverageTransformer t = createTransformer();
- assertTrue(t.filter(classLoader, "org/jacoco/core/Foo"));
+ assertTrue(t.filter(classLoader, "org/jacoco/core/Foo",
+ protectionDomain));
}
@Test
public void testFilterIncludedClassNegative() {
options.setIncludes("org.jacoco.core.*:org.jacoco.agent.rt.*");
CoverageTransformer t = createTransformer();
- assertFalse(t.filter(classLoader, "org/jacoco/report/Foo"));
+ assertFalse(t.filter(classLoader, "org/jacoco/report/Foo",
+ protectionDomain));
}
@Test
public void testFilterExcludedClassPositive() {
options.setExcludes("*Test");
CoverageTransformer t = createTransformer();
- assertFalse(t.filter(classLoader, "org/jacoco/core/FooTest"));
+ assertFalse(t.filter(classLoader, "org/jacoco/core/FooTest",
+ protectionDomain));
}
@Test
public void testFilterExcludedClassPositiveInner() {
options.setExcludes("org.jacoco.example.Foo$Inner");
CoverageTransformer t = createTransformer();
- assertFalse(t.filter(classLoader, "org/jacoco/example/Foo$Inner"));
+ assertFalse(t.filter(classLoader, "org/jacoco/example/Foo$Inner",
+ protectionDomain));
}
@Test
public void testFilterExcludedClassNegative() {
options.setExcludes("*Test");
CoverageTransformer t = createTransformer();
- assertTrue(t.filter(classLoader, "org/jacoco/core/Foo"));
+ assertTrue(t.filter(classLoader, "org/jacoco/core/Foo",
+ protectionDomain));
+ }
+
+ @Test
+ public void testFilterSourceLocationPositive1() {
+ CoverageTransformer t = createTransformer();
+ assertFalse(t.filter(classLoader, "org/jacoco/core/Foo", null));
+ }
+
+ @Test
+ public void testFilterSourceLocationPositive2() {
+ CoverageTransformer t = createTransformer();
+ ProtectionDomain pd = new ProtectionDomain(null, null);
+ assertFalse(t.filter(classLoader, "org/jacoco/core/Foo", pd));
+ }
+
+ @Test
+ public void testFilterSourceLocationPositive3() {
+ CoverageTransformer t = createTransformer();
+ CodeSource cs = new CodeSource(null, new Certificate[0]);
+ ProtectionDomain pd = new ProtectionDomain(cs, null);
+ assertFalse(t.filter(classLoader, "org/jacoco/core/Foo", pd));
+ }
+
+ @Test
+ public void testFilterSourceLocationNegative() {
+ options.setInclNoLocationClasses(true);
+ CoverageTransformer t = createTransformer();
+ assertTrue(t.filter(classLoader, "org/jacoco/core/Foo", null));
}
@Test
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/CoverageTransformer.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/CoverageTransformer.java
index 41c9703..3ab0443 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/CoverageTransformer.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/CoverageTransformer.java
@@ -45,7 +45,9 @@
private final ClassFileDumper classFileDumper;
- private final boolean includeBootstrapClasses;
+ private final boolean inclBootstrapClasses;
+
+ private final boolean inclNoLocationClasses;
/**
* New transformer with the given delegates.
@@ -66,7 +68,8 @@
excludes = new WildcardMatcher(toVMName(options.getExcludes()));
exclClassloader = new WildcardMatcher(options.getExclClassloader());
classFileDumper = new ClassFileDumper(options.getClassDumpDir());
- includeBootstrapClasses = options.getInclBootstrapClasses();
+ inclBootstrapClasses = options.getInclBootstrapClasses();
+ inclNoLocationClasses = options.getInclNoLocationClasses();
}
public byte[] transform(final ClassLoader loader, final String classname,
@@ -79,12 +82,7 @@
return null;
}
- // We exclude dynamically created non-bootstrap classes.
- if (loader != null && !hasSourceLocation(protectionDomain)) {
- return null;
- }
-
- if (!filter(loader, classname)) {
+ if (!filter(loader, classname, protectionDomain)) {
return null;
}
@@ -102,39 +100,26 @@
}
/**
- * Checks whether this protection domain is associated with a source
- * location.
- *
- * @param protectionDomain
- * protection domain to check (or <code>null</code>)
- * @return <code>true</code> if a source location is defined
- */
- boolean hasSourceLocation(final ProtectionDomain protectionDomain) {
- if (protectionDomain == null) {
- return false;
- }
- final CodeSource codeSource = protectionDomain.getCodeSource();
- if (codeSource == null) {
- return false;
- }
- return codeSource.getLocation() != null;
- }
-
- /**
* Checks whether this class should be instrumented.
*
* @param loader
* loader for the class
* @param classname
* VM name of the class to check
+ * @param protectionDomain
+ * protection domain for the class
* @return <code>true</code> if the class should be instrumented
*/
- boolean filter(final ClassLoader loader, final String classname) {
+ boolean filter(final ClassLoader loader, final String classname,
+ final ProtectionDomain protectionDomain) {
if (loader == null) {
- if (!includeBootstrapClasses) {
+ if (!inclBootstrapClasses) {
return false;
}
} else {
+ if (!inclNoLocationClasses && !hasSourceLocation(protectionDomain)) {
+ return false;
+ }
if (exclClassloader.matches(loader.getClass().getName())) {
return false;
}
@@ -147,6 +132,25 @@
!excludes.matches(classname);
}
+ /**
+ * Checks whether this protection domain is associated with a source
+ * location.
+ *
+ * @param protectionDomain
+ * protection domain to check (or <code>null</code>)
+ * @return <code>true</code> if a source location is defined
+ */
+ private boolean hasSourceLocation(final ProtectionDomain protectionDomain) {
+ if (protectionDomain == null) {
+ return false;
+ }
+ final CodeSource codeSource = protectionDomain.getCodeSource();
+ if (codeSource == null) {
+ return false;
+ }
+ return codeSource.getLocation() != null;
+ }
+
private static String toVMName(final String srcName) {
return srcName.replace('.', '/');
}
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.xml b/org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.xml
index 43691ed..81105d5 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.xml
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.xml
@@ -17,9 +17,10 @@
<target name="testCoverageAgent">
<jacoco:agent property="jacocoagent" append="false" destfile="test.exec"
- exclClassLoader="EvilClassLoader" includes="org.example.*"
- excludes="*Test" sessionid="testid" dumponexit="false"
- output="file" address="remotehost" port="1234"
+ exclClassLoader="EvilClassLoader" includes="org.example.*" excludes="*Test"
+ inclbootstrapclasses="true" inclnolocationclasses="true"
+ sessionid="testid" dumponexit="false"
+ output="file" address="remotehost" port="1234" jmx="true"
classdumpdir="target/dump"/>
<au:assertPropertySet name="jacocoagent"/>
<au:assertPropertyContains name="jacocoagent" value="-javaagent:"/>
@@ -29,11 +30,14 @@
<au:assertPropertyContains name="jacocoagent" value="exclclassloader=EvilClassLoader"/>
<au:assertPropertyContains name="jacocoagent" value="includes=org.example.*"/>
<au:assertPropertyContains name="jacocoagent" value="excludes=*Test"/>
+ <au:assertPropertyContains name="jacocoagent" value="inclbootstrapclasses=true"/>
+ <au:assertPropertyContains name="jacocoagent" value="inclnolocationclasses=true"/>
<au:assertPropertyContains name="jacocoagent" value="sessionid=testid"/>
<au:assertPropertyContains name="jacocoagent" value="dumponexit=false"/>
<au:assertPropertyContains name="jacocoagent" value="output=file"/>
<au:assertPropertyContains name="jacocoagent" value="address=remotehost"/>
<au:assertPropertyContains name="jacocoagent" value="port=1234"/>
+ <au:assertPropertyContains name="jacocoagent" value="jmx=true"/>
<property name="dump.dir" location="target/dump"/>
<au:assertPropertyContains name="jacocoagent" value="classdumpdir=${dump.dir}"/>
</target>
diff --git a/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java b/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java
index 30175cf..1569ffc 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java
@@ -126,6 +126,17 @@
}
/**
+ * Sets whether classes without source location should be instrumented.
+ *
+ * @param include
+ * <code>true</code> if classes without source location should be
+ * instrumented
+ */
+ public void setInclNoLocationClasses(final boolean include) {
+ agentOptions.setInclNoLocationClasses(include);
+ }
+
+ /**
* Sets the session identifier. Default is a auto-generated id
*
* @param id
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java
index 2c7abe9..886b2f9 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java
@@ -44,6 +44,7 @@
assertEquals("sun.reflect.DelegatingClassLoader",
options.getExclClassloader());
assertFalse(options.getInclBootstrapClasses());
+ assertFalse(options.getInclNoLocationClasses());
assertNull(options.getSessionId());
assertTrue(options.getDumpOnExit());
assertEquals(AgentOptions.OutputMode.file, options.getOutput());
@@ -76,6 +77,7 @@
properties.put("excludes", "*Test");
properties.put("exclclassloader", "org.jacoco.test.TestLoader");
properties.put("inclbootstrapclasses", "true");
+ properties.put("inclnolocationclasses", "true");
properties.put("sessionid", "testsession");
properties.put("dumponexit", "false");
properties.put("output", "tcpserver");
@@ -92,6 +94,7 @@
assertEquals("*Test", options.getExcludes());
assertEquals("org.jacoco.test.TestLoader", options.getExclClassloader());
assertTrue(options.getInclBootstrapClasses());
+ assertTrue(options.getInclNoLocationClasses());
assertEquals("testsession", options.getSessionId());
assertFalse(options.getDumpOnExit());
assertEquals(AgentOptions.OutputMode.tcpserver, options.getOutput());
@@ -102,6 +105,12 @@
}
@Test
+ public void testEmptyPropertiesOptions() {
+ AgentOptions options = new AgentOptions(new Properties());
+ assertEquals("", options.toString());
+ }
+
+ @Test
public void testGetDestile() {
AgentOptions options = new AgentOptions("destfile=/var/test.exec");
assertEquals("/var/test.exec", options.getDestfile());
@@ -188,19 +197,19 @@
}
@Test
- public void testGetIncludeBootstrapClassesTrue() {
+ public void testGetInclBootstrapClassesTrue() {
AgentOptions options = new AgentOptions("inclbootstrapclasses=true");
assertTrue(options.getInclBootstrapClasses());
}
@Test
- public void testGetIncludeBootstrapClassesFalse() {
+ public void testGetInclBootstrapClassesFalse() {
AgentOptions options = new AgentOptions("inclbootstrapclasses=false");
assertFalse(options.getInclBootstrapClasses());
}
@Test
- public void testSetIncludeBootstrapClassesTrue() {
+ public void testSetInclBootstrapClassesTrue() {
AgentOptions options = new AgentOptions();
options.setInclBootstrapClasses(true);
assertTrue(options.getInclBootstrapClasses());
@@ -208,7 +217,7 @@
}
@Test
- public void testSetIncludeBootstrapClassesFalse() {
+ public void testSetInclBootstrapClassesFalse() {
AgentOptions options = new AgentOptions();
options.setInclBootstrapClasses(false);
assertFalse(options.getInclBootstrapClasses());
@@ -216,6 +225,34 @@
}
@Test
+ public void testGetInclNoLocationClassesTrue() {
+ AgentOptions options = new AgentOptions("inclnolocationclasses=true");
+ assertTrue(options.getInclNoLocationClasses());
+ }
+
+ @Test
+ public void testGetInclNoLocationClassesFalse() {
+ AgentOptions options = new AgentOptions("inclnolocationclasses=false");
+ assertFalse(options.getInclNoLocationClasses());
+ }
+
+ @Test
+ public void testSetInclNoLocationClassesTrue() {
+ AgentOptions options = new AgentOptions();
+ options.setInclNoLocationClasses(true);
+ assertTrue(options.getInclNoLocationClasses());
+ assertEquals("inclnolocationclasses=true", options.toString());
+ }
+
+ @Test
+ public void testSetInclNoLocationClassesFalse() {
+ AgentOptions options = new AgentOptions();
+ options.setInclNoLocationClasses(false);
+ assertFalse(options.getInclNoLocationClasses());
+ assertEquals("inclnolocationclasses=false", options.toString());
+ }
+
+ @Test
public void testGetSessionId() {
AgentOptions options = new AgentOptions("sessionid=testsession");
assertEquals("testsession", options.getSessionId());
@@ -429,10 +466,12 @@
String.format("-javaagent:%s= a b c",
defaultAgentJarFile.toString()), vmArgument);
}
-
- @Test // issue #358
+
+ @Test
+ // issue #358
public void testDestFileWithComma() {
- AgentOptions options = new AgentOptions("destfile=build/jacoco/foo, bar.exec");
+ AgentOptions options = new AgentOptions(
+ "destfile=build/jacoco/foo, bar.exec");
assertEquals("build/jacoco/foo, bar.exec", options.getDestfile());
}
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java b/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
index cfc3c7c..7bd5f2a 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
@@ -85,6 +85,14 @@
public static final String INCLBOOTSTRAPCLASSES = "inclbootstrapclasses";
/**
+ * Specifies whether also classes without a source location should be
+ * instrumented. Normally such classes are generated at runtime e.g. by
+ * mocking frameworks and are therefore excluded by default. Default is
+ * <code>false</code>.
+ */
+ public static final String INCLNOLOCATIONCLASSES = "inclnolocationclasses";
+
+ /**
* Specifies a session identifier that is written with the execution data.
* Without this parameter a random identifier is created by the agent.
*/
@@ -105,7 +113,7 @@
* @see OutputMode#none
*/
public static final String OUTPUT = "output";
-
+
private static final Pattern OPTION_SPLIT = Pattern.compile(",(?=[a-z]+=)");
/**
@@ -181,8 +189,8 @@
private static final Collection<String> VALID_OPTIONS = Arrays.asList(
DESTFILE, APPEND, INCLUDES, EXCLUDES, EXCLCLASSLOADER,
- INCLBOOTSTRAPCLASSES, SESSIONID, DUMPONEXIT, OUTPUT, ADDRESS, PORT,
- CLASSDUMPDIR, JMX);
+ INCLBOOTSTRAPCLASSES, INCLNOLOCATIONCLASSES, SESSIONID, DUMPONEXIT,
+ OUTPUT, ADDRESS, PORT, CLASSDUMPDIR, JMX);
private final Map<String, String> options;
@@ -354,7 +362,8 @@
* Returns whether classes from the bootstrap classloader should be
* instrumented.
*
- * @return <code>true</code> if coverage data will be written on VM exit
+ * @return <code>true</code> if classes from the bootstrap classloader
+ * should be instrumented
*/
public boolean getInclBootstrapClasses() {
return getOption(INCLBOOTSTRAPCLASSES, false);
@@ -372,6 +381,27 @@
}
/**
+ * Returns whether classes without source location should be instrumented.
+ *
+ * @return <code>true</code> if classes without source location should be
+ * instrumented
+ */
+ public boolean getInclNoLocationClasses() {
+ return getOption(INCLNOLOCATIONCLASSES, false);
+ }
+
+ /**
+ * Sets whether classes without source location should be instrumented.
+ *
+ * @param include
+ * <code>true</code> if classes without source location should be
+ * instrumented
+ */
+ public void setInclNoLocationClasses(final boolean include) {
+ setOption(INCLNOLOCATIONCLASSES, include);
+ }
+
+ /**
* Returns the session identifier.
*
* @return session identifier
diff --git a/org.jacoco.doc/docroot/doc/agent.html b/org.jacoco.doc/docroot/doc/agent.html
index 0710bce..bca6f77 100644
--- a/org.jacoco.doc/docroot/doc/agent.html
+++ b/org.jacoco.doc/docroot/doc/agent.html
@@ -125,6 +125,14 @@
<td><code>false</code></td>
</tr>
<tr>
+ <td><code>inclnolocationclasses</code></td>
+ <td>Specifies whether also classes without a source location should be
+ instrumented. Normally such classes are generated at runtime e.g. by
+ mocking frameworks and are therefore excluded by default.
+ </td>
+ <td><code>false</code></td>
+ </tr>
+ <tr>
<td><code>sessionid</code></td>
<td>A session identifier that is written with the execution data. Without
this parameter a random identifier is created by the agent.
diff --git a/org.jacoco.doc/docroot/doc/ant.html b/org.jacoco.doc/docroot/doc/ant.html
index 5098c1e..2cfd5cf 100644
--- a/org.jacoco.doc/docroot/doc/ant.html
+++ b/org.jacoco.doc/docroot/doc/ant.html
@@ -216,6 +216,14 @@
<td><code>false</code></td>
</tr>
<tr>
+ <td><code>inclnolocationclasses</code></td>
+ <td>Specifies whether also classes without a source location should be
+ instrumented. Normally such classes are generated at runtime e.g. by
+ mocking frameworks and are therefore excluded by default.
+ </td>
+ <td><code>false</code></td>
+ </tr>
+ <tr>
<td><code>sessionid</code></td>
<td>A session identifier that is written with the execution data. Without
this parameter a random identifier is created by the agent.
diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
index 636244e..3388feb 100644
--- a/org.jacoco.doc/docroot/doc/changes.html
+++ b/org.jacoco.doc/docroot/doc/changes.html
@@ -22,6 +22,9 @@
<h3>New Features</h3>
<ul>
+ <li>New agent option <code>inclnolocationclasses</code> to support execution
+ environments like Android where no source location is provided with classes
+ (GitHub <a href="https://github.com/jacoco/jacoco/issues/288">#288</a>).</li>
<li>Improved error message in case of incompatible execution data files.
(GitHub <a href="https://github.com/jacoco/jacoco/issues/319">#319</a>).</li>
<li>Command line agent options now supports comma in file names. Contributed