aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-plugin-api
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2018-04-24 15:27:56 +0200
committerSonarTech <sonartech@sonarsource.com>2018-05-09 20:20:46 +0200
commitfa4019b992510560be8c6d1b51bc2dc2f6b41546 (patch)
tree815cf6138b9e0b3a419c27cfe98e691080264af3 /sonar-plugin-api
parent09b3d167fa8f399e18a37d56e7c8cbb61f68f97f (diff)
downloadsonarqube-fa4019b992510560be8c6d1b51bc2dc2f6b41546.tar.gz
sonarqube-fa4019b992510560be8c6d1b51bc2dc2f6b41546.zip
SONAR-10638 Create Java API for analyzers to report significant code
Diffstat (limited to 'sonar-plugin-api')
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java11
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/NewSignificantCode.java50
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCode.java76
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/internal/package-info.java21
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/package-info.java21
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorage.java21
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java18
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java6
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCodeTest.java81
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java3
10 files changed, 301 insertions, 7 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java
index 287fc2f89b3..ed4ffe22b3c 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java
@@ -26,6 +26,7 @@ import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputModule;
import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.sensor.code.NewSignificantCode;
import org.sonar.api.batch.sensor.coverage.NewCoverage;
import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
import org.sonar.api.batch.sensor.error.NewAnalysisError;
@@ -163,6 +164,16 @@ public interface SensorContext {
NewAnalysisError newAnalysisError();
/**
+ * Builder to declare which parts of the code is significant code.
+ * Ranges that are not reported as significant code will be ignored and won't be considered when calculating which lines were modified.
+ *
+ * If the significant code is not reported for a file, it is assumed that the entire file is significant code.
+ *
+ * @since 7.2
+ */
+ NewSignificantCode newSignificantCode();
+
+ /**
* Add a property to the scanner context. This context is available
* in Compute Engine when processing the report.
* <br/>
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/NewSignificantCode.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/NewSignificantCode.java
new file mode 100644
index 00000000000..dcaf087ddad
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/NewSignificantCode.java
@@ -0,0 +1,50 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.code;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+
+/**
+ * This object is used to report ranges of a file which contain significant code.
+ * Lines that are left out (no range reported) will be ignored and won't be considered when calculating which lines were modified.
+ * It's particularly useful when portions of the lines are automatically modified by code editors and do not contain
+ * code or comments were issues might be created.
+ *
+ * Don't forget to call {@link #save()} after setting the file and the ranges where the significant code is.
+ *
+ * @since 7.2
+ */
+public interface NewSignificantCode {
+ /**
+ * The file for which significant code is being reported. This field must be set before saving the error.
+ */
+ NewSignificantCode onFile(InputFile file);
+
+ /**
+ * Add a range of significant code. The range may only include a single line and only one range is accepted per line.
+ */
+ NewSignificantCode addRange(TextRange range);
+
+ /**
+ * Save the reported information for the given file.
+ */
+ void save();
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCode.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCode.java
new file mode 100644
index 00000000000..97d2e25a9bd
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCode.java
@@ -0,0 +1,76 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.code.internal;
+
+import com.google.common.base.Preconditions;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.sensor.code.NewSignificantCode;
+import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+
+public class DefaultSignificantCode extends DefaultStorable implements NewSignificantCode {
+ private SortedMap<Integer, TextRange> significantCodePerLine = new TreeMap<>();
+ private InputFile inputFile;
+
+ public DefaultSignificantCode() {
+ super();
+ }
+
+ public DefaultSignificantCode(@Nullable SensorStorage storage) {
+ super(storage);
+ }
+
+ @Override
+ public DefaultSignificantCode onFile(InputFile inputFile) {
+ this.inputFile = inputFile;
+ return this;
+ }
+
+ @Override
+ public DefaultSignificantCode addRange(TextRange range) {
+ Preconditions.checkState(this.inputFile != null, "addRange() should be called after on()");
+
+ int line = range.start().line();
+
+ Preconditions.checkArgument(line == range.end().line(), "Ranges of significant code must be located in a single line");
+ Preconditions.checkState(!significantCodePerLine.containsKey(line), "Significant code was already reported for line '%s'. Can only report once per line.", line);
+
+ significantCodePerLine.put(line, range);
+ return this;
+ }
+
+ @Override
+ protected void doSave() {
+ Preconditions.checkState(inputFile != null, "Call onFile() first");
+ storage.store(this);
+ }
+
+ public InputFile inputFile() {
+ return inputFile;
+ }
+
+ public SortedMap<Integer, TextRange> significantCodePerLine() {
+ return significantCodePerLine;
+ }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/internal/package-info.java
new file mode 100644
index 00000000000..3a93ee2e007
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/internal/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.api.batch.sensor.code.internal;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/package-info.java
new file mode 100644
index 00000000000..e8b9a012e09
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/code/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.api.batch.sensor.code;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorage.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorage.java
index ef225532139..e46b8121830 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorage.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorage.java
@@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
+import org.sonar.api.batch.sensor.code.internal.DefaultSignificantCode;
import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage;
import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens;
import org.sonar.api.batch.sensor.error.AnalysisError;
@@ -35,7 +36,6 @@ import org.sonar.api.batch.sensor.issue.ExternalIssue;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.batch.sensor.measure.Measure;
import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
-import org.sonar.api.utils.SonarException;
import static com.google.common.base.Preconditions.checkArgument;
@@ -52,6 +52,7 @@ class InMemorySensorStorage implements SensorStorage {
Multimap<String, DefaultCoverage> coverageByComponent = ArrayListMultimap.create();
Map<String, DefaultSymbolTable> symbolsPerComponent = new HashMap<>();
Map<String, String> contextProperties = new HashMap<>();
+ Map<String, DefaultSignificantCode> significantCodePerComponent = new HashMap<>();
@Override
public void store(Measure measure) {
@@ -59,7 +60,7 @@ class InMemorySensorStorage implements SensorStorage {
String componentKey = measure.inputComponent().key();
String metricKey = measure.metric().key();
if (measuresByComponentAndMetric.contains(componentKey, metricKey)) {
- throw new SonarException("Can not add the same measure twice");
+ throw new IllegalStateException("Can not add the same measure twice");
}
measuresByComponentAndMetric.row(componentKey).put(metricKey, measure);
}
@@ -74,7 +75,7 @@ class InMemorySensorStorage implements SensorStorage {
String fileKey = highlighting.inputFile().key();
// Emulate duplicate storage check
if (highlightingByComponent.containsKey(fileKey)) {
- throw new UnsupportedOperationException("Trying to save highlighting twice for the same file is not supported: " + highlighting.inputFile().relativePath());
+ throw new UnsupportedOperationException("Trying to save highlighting twice for the same file is not supported: " + highlighting.inputFile());
}
highlightingByComponent.put(fileKey, highlighting);
}
@@ -90,7 +91,7 @@ class InMemorySensorStorage implements SensorStorage {
String fileKey = defaultCpdTokens.inputFile().key();
// Emulate duplicate storage check
if (cpdTokensByComponent.containsKey(fileKey)) {
- throw new UnsupportedOperationException("Trying to save CPD tokens twice for the same file is not supported: " + defaultCpdTokens.inputFile().relativePath());
+ throw new UnsupportedOperationException("Trying to save CPD tokens twice for the same file is not supported: " + defaultCpdTokens.inputFile());
}
cpdTokensByComponent.put(fileKey, defaultCpdTokens);
}
@@ -100,7 +101,7 @@ class InMemorySensorStorage implements SensorStorage {
String fileKey = symbolTable.inputFile().key();
// Emulate duplicate storage check
if (symbolsPerComponent.containsKey(fileKey)) {
- throw new UnsupportedOperationException("Trying to save symbol table twice for the same file is not supported: " + symbolTable.inputFile().relativePath());
+ throw new UnsupportedOperationException("Trying to save symbol table twice for the same file is not supported: " + symbolTable.inputFile());
}
symbolsPerComponent.put(fileKey, symbolTable);
}
@@ -121,4 +122,14 @@ class InMemorySensorStorage implements SensorStorage {
public void store(ExternalIssue issue) {
allExternalIssues.add(issue);
}
+
+ @Override
+ public void store(DefaultSignificantCode significantCode) {
+ String fileKey = significantCode.inputFile().key();
+ // Emulate duplicate storage check
+ if (significantCodePerComponent.containsKey(fileKey)) {
+ throw new UnsupportedOperationException("Trying to save significant code information twice for the same file is not supported: " + significantCode.inputFile());
+ }
+ significantCodePerComponent.put(fileKey, significantCode);
+ }
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
index b13340fb1c1..76977f55bd7 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
@@ -47,6 +47,8 @@ import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.code.NewSignificantCode;
+import org.sonar.api.batch.sensor.code.internal.DefaultSignificantCode;
import org.sonar.api.batch.sensor.coverage.NewCoverage;
import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage;
import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
@@ -268,6 +270,17 @@ public class SensorContextTester implements SensorContext {
}
@CheckForNull
+ public TextRange significantCodeTextRange(String fileKey, int line) {
+ if (sensorStorage.significantCodePerComponent.containsKey(fileKey)) {
+ return sensorStorage.significantCodePerComponent.get(fileKey)
+ .significantCodePerLine()
+ .get(line);
+ }
+ return null;
+
+ }
+
+ @CheckForNull
public static Integer maxOrNull(@Nullable Integer o1, @Nullable Integer o2) {
return o1 == null ? o2 : Math.max(o1, o2);
}
@@ -366,4 +379,9 @@ public class SensorContextTester implements SensorContext {
DefaultInputFile file = (DefaultInputFile) inputFile;
file.setPublished(true);
}
+
+ @Override
+ public NewSignificantCode newSignificantCode() {
+ return new DefaultSignificantCode(sensorStorage);
+ }
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java
index d8c7cb5648f..ede3c9e9910 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java
@@ -20,6 +20,7 @@
package org.sonar.api.batch.sensor.internal;
import org.sonar.api.batch.ScannerSide;
+import org.sonar.api.batch.sensor.code.internal.DefaultSignificantCode;
import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage;
import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens;
import org.sonar.api.batch.sensor.error.AnalysisError;
@@ -71,4 +72,9 @@ public interface SensorStorage {
* @since 6.1
*/
void storeProperty(String key, String value);
+
+ /**
+ * @since 7.2
+ */
+ void store(DefaultSignificantCode significantCode);
}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCodeTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCodeTest.java
new file mode 100644
index 00000000000..73b5f57ed9b
--- /dev/null
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCodeTest.java
@@ -0,0 +1,81 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.code.internal;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class DefaultSignificantCodeTest {
+ private SensorStorage sensorStorage = mock(SensorStorage.class);
+ private DefaultSignificantCode underTest = new DefaultSignificantCode(sensorStorage);
+ private InputFile inputFile = TestInputFileBuilder.create("module", "file1.xoo")
+ .setContents("this is\na file\n with some code")
+ .build();
+
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+ @Test
+ public void should_save_ranges() {
+ underTest.onFile(inputFile)
+ .addRange(inputFile.selectLine(1))
+ .save();
+ verify(sensorStorage).store(underTest);
+ }
+
+ @Test
+ public void fail_if_save_without_file() {
+ exception.expect(IllegalStateException.class);
+ exception.expectMessage("Call onFile() first");
+ underTest.save();
+ }
+
+ @Test
+ public void fail_if_add_range_to_same_line_twice() {
+ underTest.onFile(inputFile);
+ underTest.addRange(inputFile.selectLine(1));
+
+ exception.expect(IllegalStateException.class);
+ exception.expectMessage("Significant code was already reported for line '1'.");
+ underTest.addRange(inputFile.selectLine(1));
+ }
+
+ @Test
+ public void fail_if_range_includes_many_lines() {
+ underTest.onFile(inputFile);
+
+ exception.expect(IllegalArgumentException.class);
+ exception.expectMessage("Ranges of significant code must be located in a single line");
+ underTest.addRange(inputFile.newRange(1, 1, 2, 1));
+ }
+
+ @Test
+ public void fail_if_add_range_before_setting_file() {
+ exception.expect(IllegalStateException.class);
+ exception.expectMessage("addRange() should be called after on()");
+ underTest.addRange(inputFile.selectLine(1));
+ }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java
index c43f0275b34..a4d659e29f0 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java
@@ -47,7 +47,6 @@ import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.RuleType;
-import org.sonar.api.utils.SonarException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
@@ -176,7 +175,7 @@ public class SensorContextTesterTest {
assertThat(tester.measure("foo", "directories")).isNotNull();
}
- @Test(expected = SonarException.class)
+ @Test(expected = IllegalStateException.class)
public void duplicateMeasures() {
tester.<Integer>newMeasure()
.on(new TestInputFileBuilder("foo", "src/Foo.java").build())