import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.fs.internal.DefaultTextPointer;
-import org.sonar.api.batch.fs.internal.DefaultTextRange;
+import org.sonar.scanner.fs.DefaultTextPointer;
+import org.sonar.scanner.fs.DefaultTextRange;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.sensor.DefaultSensorDescriptor;
import org.sonar.scanner.sensor.SensorContextTester;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultTextPointer;
-import org.sonar.api.batch.fs.internal.DefaultTextRange;
+import org.sonar.scanner.fs.DefaultTextPointer;
+import org.sonar.scanner.fs.DefaultTextRange;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.sensor.DefaultSensorDescriptor;
import org.sonar.scanner.sensor.SensorContextTester;
sensor.execute(context);
assertThat(context.referencesForSymbolAt("foo:src/foo.xoo", 1, 2))
- .containsOnly(new DefaultTextRange(new DefaultTextPointer(1, 7), new DefaultTextPointer(1,10)));
+ .containsOnly(new DefaultTextRange(new DefaultTextPointer(1, 7), new DefaultTextPointer(1, 10)));
assertThat(context.referencesForSymbolAt("foo:src/foo.xoo", 1, 13))
- .containsOnly(new DefaultTextRange(new DefaultTextPointer(1, 23), new DefaultTextPointer(1,33)));
+ .containsOnly(new DefaultTextRange(new DefaultTextPointer(1, 23), new DefaultTextPointer(1, 33)));
}
}
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.sensor.DefaultSensorDescriptor;
import org.sonar.scanner.sensor.SensorContextTester;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultTextPointer;
import org.sonar.api.batch.sensor.error.AnalysisError;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultTextPointer;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.sensor.SensorContextTester;
package org.sonar.xoo.rule;
import java.io.IOException;
-import org.sonar.api.SonarEdition;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.sonar.api.SonarEdition;
import org.sonar.api.SonarQubeSide;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.internal.SonarRuntimeImpl;
import org.sonar.api.utils.Version;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.sensor.DefaultSensorDescriptor;
import org.sonar.scanner.sensor.SensorContextTester;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.scm.BlameCommand.BlameInput;
import org.sonar.api.batch.scm.BlameCommand.BlameOutput;
import org.sonar.api.batch.scm.BlameLine;
import org.sonar.api.utils.DateUtils;
import org.sonar.scanner.fs.DefaultFileSystem;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.xoo.Xoo;
import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import static com.google.common.base.Preconditions.checkArgument;
// only static stuff
}
- public static String createEffectiveKey(String projectKey, DefaultInputFile inputPath) {
- return createEffectiveKey(projectKey, inputPath.getProjectRelativePath());
- }
-
public static String createEffectiveKey(String projectKey, @Nullable String path) {
StringBuilder sb = new StringBuilder(MAX_COMPONENT_KEY_LENGTH);
sb.append(projectKey);
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
public class ComponentKeysTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
- @Test
- public void create_effective_key() {
- DefaultInputFile file = mock(DefaultInputFile.class);
- when(file.getProjectRelativePath()).thenReturn("foo/Bar.php");
- assertThat(ComponentKeys.createEffectiveKey("my_project", file)).isEqualTo("my_project:foo/Bar.php");
- }
-
@Test
public void create_key_from_module_key_path_and_branch() {
assertThat(ComponentKeys.createKey("module_key", "file", "origin/master")).isEqualTo("module_key:origin/master:file");
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.LinkOption;
-import java.nio.file.Path;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import javax.annotation.CheckForNull;
-import javax.annotation.concurrent.Immutable;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.SystemUtils;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-
-@Immutable
-public abstract class AbstractProjectOrModule extends DefaultInputComponent {
- private static final Logger LOGGER = Loggers.get(AbstractProjectOrModule.class);
- private final Path baseDir;
- private final Path workDir;
- private final String name;
- private final String originalName;
- private final String description;
- private final String keyWithBranch;
- private final String branch;
- private final Map<String, String> properties;
-
- private final String key;
- private final ProjectDefinition definition;
- private final Charset encoding;
-
- public AbstractProjectOrModule(ProjectDefinition definition, int scannerComponentId) {
- super(scannerComponentId);
- this.baseDir = initBaseDir(definition);
- this.workDir = initWorkingDir(definition);
- this.name = definition.getName();
- this.originalName = definition.getOriginalName();
- this.description = definition.getDescription();
- this.keyWithBranch = definition.getKeyWithBranch();
- this.branch = definition.getBranch();
- this.properties = Collections.unmodifiableMap(new HashMap<>(definition.properties()));
-
- this.definition = definition;
- this.key = definition.getKey();
- this.encoding = initEncoding(definition);
- }
-
- private static Charset initEncoding(ProjectDefinition module) {
- String encodingStr = module.properties().get(CoreProperties.ENCODING_PROPERTY);
- Charset result;
- if (StringUtils.isNotEmpty(encodingStr)) {
- result = Charset.forName(StringUtils.trim(encodingStr));
- } else {
- result = Charset.defaultCharset();
- }
- return result;
- }
-
- private static Path initBaseDir(ProjectDefinition module) {
- Path result;
- try {
- result = module.getBaseDir().toPath().toRealPath(LinkOption.NOFOLLOW_LINKS);
- } catch (IOException e) {
- throw new IllegalStateException("Unable to resolve module baseDir", e);
- }
- return result;
- }
-
- private static Path initWorkingDir(ProjectDefinition module) {
- File workingDirAsFile = module.getWorkDir();
- Path workingDir = workingDirAsFile.getAbsoluteFile().toPath().normalize();
- if (SystemUtils.IS_OS_WINDOWS) {
- try {
- Files.createDirectories(workingDir);
- Files.setAttribute(workingDir, "dos:hidden", true, LinkOption.NOFOLLOW_LINKS);
- } catch (IOException e) {
- LOGGER.warn("Failed to set working directory hidden: {}", e.getMessage());
- }
- }
- return workingDir;
- }
-
- /**
- * Module key without branch
- */
- @Override
- public String key() {
- return key;
- }
-
- @Override
- public boolean isFile() {
- return false;
- }
-
- public ProjectDefinition definition() {
- return definition;
- }
-
- public Path getBaseDir() {
- return baseDir;
- }
-
- public Path getWorkDir() {
- return workDir;
- }
-
- public String getKeyWithBranch() {
- return keyWithBranch;
- }
-
- @CheckForNull
- public String getBranch() {
- return branch;
- }
-
- public Map<String, String> properties() {
- return properties;
- }
-
- @CheckForNull
- public String getOriginalName() {
- return originalName;
- }
-
- public String getName() {
- return name;
- }
-
- public String getDescription() {
- return description;
- }
-
- public Charset getEncoding() {
- return encoding;
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.concurrent.atomic.AtomicInteger;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.batch.fs.IndexedFile;
-import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.utils.PathUtils;
-
-/**
- * @since 6.3
- */
-@Immutable
-public class DefaultIndexedFile extends DefaultInputComponent implements IndexedFile {
- private static AtomicInteger intGenerator = new AtomicInteger(0);
-
- private final String projectRelativePath;
- private final String moduleRelativePath;
- private final String projectKey;
- private final String language;
- private final Type type;
- private final Path absolutePath;
- private final SensorStrategy sensorStrategy;
-
- /**
- * Testing purposes only!
- */
- public DefaultIndexedFile(String projectKey, Path baseDir, String relativePath, @Nullable String language) {
- this(baseDir.resolve(relativePath), projectKey, relativePath, relativePath, Type.MAIN, language, intGenerator.getAndIncrement(),
- new SensorStrategy());
- }
-
- public DefaultIndexedFile(Path absolutePath, String projectKey, String projectRelativePath, String moduleRelativePath, Type type, @Nullable String language, int batchId,
- SensorStrategy sensorStrategy) {
- super(batchId);
- this.projectKey = projectKey;
- this.projectRelativePath = PathUtils.sanitize(projectRelativePath);
- this.moduleRelativePath = PathUtils.sanitize(moduleRelativePath);
- this.type = type;
- this.language = language;
- this.sensorStrategy = sensorStrategy;
- this.absolutePath = absolutePath;
- }
-
- @Override
- public String relativePath() {
- return sensorStrategy.isGlobal() ? projectRelativePath : moduleRelativePath;
- }
-
- public String getModuleRelativePath() {
- return moduleRelativePath;
- }
-
- public String getProjectRelativePath() {
- return projectRelativePath;
- }
-
- @Override
- public String absolutePath() {
- return PathUtils.sanitize(path().toString());
- }
-
- @Override
- public File file() {
- return path().toFile();
- }
-
- @Override
- public Path path() {
- return absolutePath;
- }
-
- @Override
- public InputStream inputStream() throws IOException {
- return Files.newInputStream(path());
- }
-
- @CheckForNull
- @Override
- public String language() {
- return language;
- }
-
- @Override
- public Type type() {
- return type;
- }
-
- /**
- * Component key (without branch).
- */
- @Override
- public String key() {
- return new StringBuilder().append(projectKey).append(":").append(projectRelativePath).toString();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (!(o instanceof DefaultIndexedFile)) {
- return false;
- }
-
- DefaultIndexedFile that = (DefaultIndexedFile) o;
- return projectRelativePath.equals(that.projectRelativePath);
- }
-
- @Override
- public int hashCode() {
- return projectRelativePath.hashCode();
- }
-
- @Override
- public String toString() {
- return projectRelativePath;
- }
-
- @Override
- public boolean isFile() {
- return true;
- }
-
- @Override
- public String filename() {
- return path().getFileName().toString();
- }
-
- @Override
- public URI uri() {
- return path().toUri();
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import java.util.HashSet;
-import java.util.Set;
-import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.measure.Metric;
-
-/**
- * @since 5.2
- */
-public abstract class DefaultInputComponent implements InputComponent {
- private int id;
- private Set<String> storedMetricKeys = new HashSet<>();
-
- public DefaultInputComponent(int scannerId) {
- this.id = scannerId;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || this.getClass() != o.getClass()) {
- return false;
- }
-
- DefaultInputComponent that = (DefaultInputComponent) o;
- return key().equals(that.key());
- }
-
- public int scannerId() {
- return id;
- }
-
- @Override
- public int hashCode() {
- return key().hashCode();
- }
-
- @Override
- public String toString() {
- return "[key=" + key() + "]";
- }
-
- public void setHasMeasureFor(Metric metric) {
- storedMetricKeys.add(metric.key());
- }
-
- public boolean hasMeasureFor(Metric metric) {
- return storedMetricKeys.contains(metric.key());
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import java.io.File;
-import java.net.URI;
-import java.nio.file.Path;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.fs.InputDir;
-import org.sonar.api.utils.PathUtils;
-
-/**
- * @since 4.5
- */
-public class DefaultInputDir extends DefaultInputComponent implements InputDir {
-
- private final String relativePath;
- private final String moduleKey;
- private Path moduleBaseDir;
-
- public DefaultInputDir(String moduleKey, String relativePath) {
- super(-1);
- this.moduleKey = moduleKey;
- this.relativePath = PathUtils.sanitize(relativePath);
- }
-
- @Override
- public String relativePath() {
- return relativePath;
- }
-
- @Override
- public String absolutePath() {
- return PathUtils.sanitize(path().toString());
- }
-
- @Override
- public File file() {
- return path().toFile();
- }
-
- @Override
- public Path path() {
- if (moduleBaseDir == null) {
- throw new IllegalStateException("Can not return the java.nio.file.Path because module baseDir is not set (see method setModuleBaseDir(java.io.File))");
- }
- return moduleBaseDir.resolve(relativePath);
- }
-
- public String moduleKey() {
- return moduleKey;
- }
-
- @Override
- public String key() {
- StringBuilder sb = new StringBuilder().append(moduleKey).append(":");
- if (StringUtils.isEmpty(relativePath)) {
- sb.append("/");
- } else {
- sb.append(relativePath);
- }
- return sb.toString();
- }
-
- /**
- * For testing purpose. Will be automatically set when dir is added to {@link DefaultFileSystem}
- */
- public DefaultInputDir setModuleBaseDir(Path moduleBaseDir) {
- this.moduleBaseDir = moduleBaseDir.normalize();
- return this;
- }
-
- @Override
- public boolean isFile() {
- return false;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || this.getClass() != o.getClass()) {
- return false;
- }
-
- DefaultInputDir that = (DefaultInputDir) o;
- return moduleKey.equals(that.moduleKey) && relativePath.equals(that.relativePath);
- }
-
- @Override
- public int hashCode() {
- return moduleKey.hashCode() + relativePath.hashCode() * 13;
- }
-
- @Override
- public String toString() {
- return "[moduleKey=" + moduleKey + ", relative=" + relativePath + ", basedir=" + moduleBaseDir + "]";
- }
-
- @Override
- public URI uri() {
- return path().toUri();
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.Collection;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.apache.commons.io.ByteOrderMark;
-import org.apache.commons.io.input.BOMInputStream;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextPointer;
-import org.sonar.api.batch.fs.TextRange;
-
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-/**
- * @since 4.2
- * To create {@link InputFile} in tests, use TestInputFileBuilder.
- */
-public class DefaultInputFile extends DefaultInputComponent implements InputFile {
-
- private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
-
- private final DefaultIndexedFile indexedFile;
- private final String contents;
- private final Consumer<DefaultInputFile> metadataGenerator;
-
- private boolean published;
- private boolean excludedForCoverage;
- private boolean excludedForDuplication;
- private boolean ignoreAllIssues;
- // Lazy init to save memory
- private BitSet noSonarLines;
- private Status status;
- private Charset charset;
- private Metadata metadata;
- private Collection<int[]> ignoreIssuesOnlineRanges;
- private BitSet executableLines;
-
- public DefaultInputFile(DefaultIndexedFile indexedFile, Consumer<DefaultInputFile> metadataGenerator) {
- this(indexedFile, metadataGenerator, null);
- }
-
- // For testing
- public DefaultInputFile(DefaultIndexedFile indexedFile, Consumer<DefaultInputFile> metadataGenerator, @Nullable String contents) {
- super(indexedFile.scannerId());
- this.indexedFile = indexedFile;
- this.metadataGenerator = metadataGenerator;
- this.metadata = null;
- this.published = false;
- this.excludedForCoverage = false;
- this.contents = contents;
- }
-
- public void checkMetadata() {
- if (metadata == null) {
- metadataGenerator.accept(this);
- }
- }
-
- @Override
- public InputStream inputStream() throws IOException {
- return contents != null ? new ByteArrayInputStream(contents.getBytes(charset()))
- : new BOMInputStream(Files.newInputStream(path()),
- ByteOrderMark.UTF_8, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE);
- }
-
- @Override
- public String contents() throws IOException {
- if (contents != null) {
- return contents;
- } else {
- ByteArrayOutputStream result = new ByteArrayOutputStream();
- try (InputStream inputStream = inputStream()) {
- byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
- int length;
- while ((length = inputStream.read(buffer)) != -1) {
- result.write(buffer, 0, length);
- }
- }
- return result.toString(charset().name());
- }
- }
-
- public DefaultInputFile setPublished(boolean published) {
- this.published = published;
- return this;
- }
-
- public boolean isPublished() {
- return published;
- }
-
- public DefaultInputFile setExcludedForCoverage(boolean excludedForCoverage) {
- this.excludedForCoverage = excludedForCoverage;
- return this;
- }
-
- public boolean isExcludedForCoverage() {
- return excludedForCoverage;
- }
-
- public DefaultInputFile setExcludedForDuplication(boolean excludedForDuplication) {
- this.excludedForDuplication = excludedForDuplication;
- return this;
- }
-
- public boolean isExcludedForDuplication() {
- return excludedForDuplication;
- }
-
- /**
- * @deprecated since 6.6
- */
- @Deprecated
- @Override
- public String relativePath() {
- return indexedFile.relativePath();
- }
-
- public String getModuleRelativePath() {
- return indexedFile.getModuleRelativePath();
- }
-
- public String getProjectRelativePath() {
- return indexedFile.getProjectRelativePath();
- }
-
- @Override
- public String absolutePath() {
- return indexedFile.absolutePath();
- }
-
- @Override
- public File file() {
- return indexedFile.file();
- }
-
- @Override
- public Path path() {
- return indexedFile.path();
- }
-
- @CheckForNull
- @Override
- public String language() {
- return indexedFile.language();
- }
-
- @Override
- public Type type() {
- return indexedFile.type();
- }
-
- /**
- * Component key (without branch).
- */
- @Override
- public String key() {
- return indexedFile.key();
- }
-
- @Override
- public int hashCode() {
- return indexedFile.hashCode();
- }
-
- @Override
- public String toString() {
- return indexedFile.toString();
- }
-
- /**
- * {@link #setStatus(org.sonar.api.batch.fs.InputFile.Status)}
- */
- @Override
- public Status status() {
- checkMetadata();
- return status;
- }
-
- @Override
- public int lines() {
- checkMetadata();
- return metadata.lines();
- }
-
- @Override
- public boolean isEmpty() {
- checkMetadata();
- return metadata.isEmpty();
- }
-
- @Override
- public Charset charset() {
- checkMetadata();
- return charset;
- }
-
- public int lastValidOffset() {
- checkMetadata();
- return metadata.lastValidOffset();
- }
-
- /**
- * Digest hash of the file.
- */
- public String hash() {
- checkMetadata();
- return metadata.hash();
- }
-
- public int nonBlankLines() {
- checkMetadata();
- return metadata.nonBlankLines();
- }
-
- public int[] originalLineStartOffsets() {
- checkMetadata();
- checkState(metadata.originalLineStartOffsets() != null, "InputFile is not properly initialized.");
- checkState(metadata.originalLineStartOffsets().length == metadata.lines(),
- "InputFile is not properly initialized. 'originalLineStartOffsets' property length should be equal to 'lines'");
- return metadata.originalLineStartOffsets();
- }
-
- public int[] originalLineEndOffsets() {
- checkMetadata();
- checkState(metadata.originalLineEndOffsets() != null, "InputFile is not properly initialized.");
- checkState(metadata.originalLineEndOffsets().length == metadata.lines(),
- "InputFile is not properly initialized. 'originalLineEndOffsets' property length should be equal to 'lines'");
- return metadata.originalLineEndOffsets();
- }
-
- @Override
- public TextPointer newPointer(int line, int lineOffset) {
- checkMetadata();
- DefaultTextPointer textPointer = new DefaultTextPointer(line, lineOffset);
- checkValid(textPointer, "pointer");
- return textPointer;
- }
-
- @Override
- public TextRange newRange(TextPointer start, TextPointer end) {
- checkMetadata();
- checkValid(start, "start pointer");
- checkValid(end, "end pointer");
- return newRangeValidPointers(start, end, false);
- }
-
- @Override
- public TextRange newRange(int startLine, int startLineOffset, int endLine, int endLineOffset) {
- checkMetadata();
- TextPointer start = newPointer(startLine, startLineOffset);
- TextPointer end = newPointer(endLine, endLineOffset);
- return newRangeValidPointers(start, end, false);
- }
-
- @Override
- public TextRange selectLine(int line) {
- checkMetadata();
- TextPointer startPointer = newPointer(line, 0);
- TextPointer endPointer = newPointer(line, lineLength(line));
- return newRangeValidPointers(startPointer, endPointer, true);
- }
-
- public void validate(TextRange range) {
- checkMetadata();
- checkValid(range.start(), "start pointer");
- checkValid(range.end(), "end pointer");
- }
-
- /**
- * Create Range from global offsets. Used for backward compatibility with older API.
- */
- public TextRange newRange(int startOffset, int endOffset) {
- checkMetadata();
- return newRangeValidPointers(newPointer(startOffset), newPointer(endOffset), false);
- }
-
- public TextPointer newPointer(int globalOffset) {
- checkMetadata();
- checkArgument(globalOffset >= 0, "%s is not a valid offset for a file", globalOffset);
- checkArgument(globalOffset <= lastValidOffset(), "%s is not a valid offset for file %s. Max offset is %s", globalOffset, this, lastValidOffset());
- int line = findLine(globalOffset);
- int startLineOffset = originalLineStartOffsets()[line - 1];
- // In case the global offset is between \r and \n, move the pointer to a valid location
- return new DefaultTextPointer(line, Math.min(globalOffset, originalLineEndOffsets()[line - 1]) - startLineOffset);
- }
-
- public DefaultInputFile setStatus(Status status) {
- this.status = status;
- return this;
- }
-
- public DefaultInputFile setCharset(Charset charset) {
- this.charset = charset;
- return this;
- }
-
- private void checkValid(TextPointer pointer, String owner) {
- checkArgument(pointer.line() >= 1, "%s is not a valid line for a file", pointer.line());
- checkArgument(pointer.line() <= this.metadata.lines(), "%s is not a valid line for %s. File %s has %s line(s)", pointer.line(), owner, this, metadata.lines());
- checkArgument(pointer.lineOffset() >= 0, "%s is not a valid line offset for a file", pointer.lineOffset());
- int lineLength = lineLength(pointer.line());
- checkArgument(pointer.lineOffset() <= lineLength,
- "%s is not a valid line offset for %s. File %s has %s character(s) at line %s", pointer.lineOffset(), owner, this, lineLength, pointer.line());
- }
-
- private int lineLength(int line) {
- return originalLineEndOffsets()[line - 1] - originalLineStartOffsets()[line - 1];
- }
-
- private static TextRange newRangeValidPointers(TextPointer start, TextPointer end, boolean acceptEmptyRange) {
- checkArgument(acceptEmptyRange ? (start.compareTo(end) <= 0) : (start.compareTo(end) < 0),
- "Start pointer %s should be before end pointer %s", start, end);
- return new DefaultTextRange(start, end);
- }
-
- private int findLine(int globalOffset) {
- return Math.abs(Arrays.binarySearch(originalLineStartOffsets(), globalOffset) + 1);
- }
-
- public DefaultInputFile setMetadata(Metadata metadata) {
- this.metadata = metadata;
- return this;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null) {
- return false;
- }
-
- if (this.getClass() != obj.getClass()) {
- return false;
- }
-
- DefaultInputFile that = (DefaultInputFile) obj;
- return this.getProjectRelativePath().equals(that.getProjectRelativePath());
- }
-
- @Override
- public boolean isFile() {
- return true;
- }
-
- @Override
- public String filename() {
- return indexedFile.filename();
- }
-
- @Override
- public URI uri() {
- return indexedFile.uri();
- }
-
- public void noSonarAt(Set<Integer> noSonarLines) {
- if (this.noSonarLines == null) {
- this.noSonarLines = new BitSet(lines());
- }
- noSonarLines.forEach(l -> this.noSonarLines.set(l - 1));
- }
-
- public boolean hasNoSonarAt(int line) {
- if (this.noSonarLines == null) {
- return false;
- }
- return this.noSonarLines.get(line - 1);
- }
-
- public boolean isIgnoreAllIssues() {
- return ignoreAllIssues;
- }
-
- public void setIgnoreAllIssues(boolean ignoreAllIssues) {
- this.ignoreAllIssues = ignoreAllIssues;
- }
-
- public void addIgnoreIssuesOnLineRanges(Collection<int[]> lineRanges) {
- if (this.ignoreIssuesOnlineRanges == null) {
- this.ignoreIssuesOnlineRanges = new ArrayList<>();
- }
- this.ignoreIssuesOnlineRanges.addAll(lineRanges);
- }
-
- public boolean isIgnoreAllIssuesOnLine(@Nullable Integer line) {
- if (line == null || ignoreIssuesOnlineRanges == null) {
- return false;
- }
- return ignoreIssuesOnlineRanges.stream().anyMatch(r -> r[0] <= line && line <= r[1]);
- }
-
- public void setExecutableLines(Set<Integer> executableLines) {
- checkState(this.executableLines == null, "Executable lines have already been saved for file: {}", this.toString());
- this.executableLines = new BitSet(lines());
- executableLines.forEach(l -> this.executableLines.set(l - 1));
- }
-
- public Optional<Set<Integer>> getExecutableLines() {
- if (this.executableLines == null) {
- return Optional.empty();
- }
- return Optional.of(this.executableLines.stream().map(i -> i + 1).boxed().collect(Collectors.toSet()));
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import java.io.File;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import javax.annotation.CheckForNull;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.InputModule;
-import org.sonar.api.scan.filesystem.PathResolver;
-
-import static org.sonar.api.config.internal.MultivalueProperty.parseAsCsv;
-
-@Immutable
-public class DefaultInputModule extends AbstractProjectOrModule implements InputModule {
-
- private final List<Path> sourceDirsOrFiles;
- private final List<Path> testDirsOrFiles;
-
- /**
- * For testing only!
- */
- public DefaultInputModule(ProjectDefinition definition) {
- this(definition, 0);
- }
-
- public DefaultInputModule(ProjectDefinition definition, int scannerComponentId) {
- super(definition, scannerComponentId);
-
- this.sourceDirsOrFiles = initSources(definition, ProjectDefinition.SOURCES_PROPERTY);
- this.testDirsOrFiles = initSources(definition, ProjectDefinition.TESTS_PROPERTY);
- }
-
- @CheckForNull
- private List<Path> initSources(ProjectDefinition module, String propertyKey) {
- if (!module.properties().containsKey(propertyKey)) {
- return null;
- }
- List<Path> result = new ArrayList<>();
- PathResolver pathResolver = new PathResolver();
- String srcPropValue = module.properties().get(propertyKey);
- if (srcPropValue != null) {
- for (String sourcePath : parseAsCsv(propertyKey, srcPropValue)) {
- File dirOrFile = pathResolver.relativeFile(getBaseDir().toFile(), sourcePath);
- if (dirOrFile.exists()) {
- result.add(dirOrFile.toPath());
- }
- }
- }
- return result;
- }
-
- public Optional<List<Path>> getSourceDirsOrFiles() {
- return Optional.ofNullable(sourceDirsOrFiles);
- }
-
- public Optional<List<Path>> getTestDirsOrFiles() {
- return Optional.ofNullable(testDirsOrFiles);
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.scanner.fs.InputProject;
-
-@Immutable
-public class DefaultInputProject extends AbstractProjectOrModule implements InputProject {
-
- /**
- * For testing only!
- */
- public DefaultInputProject(ProjectDefinition definition) {
- super(definition, 0);
- }
-
- public DefaultInputProject(ProjectDefinition definition, int scannerComponentId) {
- super(definition, scannerComponentId);
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import org.sonar.api.batch.fs.TextPointer;
-
-/**
- * @since 5.2
- */
-public class DefaultTextPointer implements TextPointer {
-
- private final int line;
- private final int lineOffset;
-
- public DefaultTextPointer(int line, int lineOffset) {
- this.line = line;
- this.lineOffset = lineOffset;
- }
-
- @Override
- public int line() {
- return line;
- }
-
- @Override
- public int lineOffset() {
- return lineOffset;
- }
-
- @Override
- public String toString() {
- return "[line=" + line + ", lineOffset=" + lineOffset + "]";
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof DefaultTextPointer)) {
- return false;
- }
- DefaultTextPointer other = (DefaultTextPointer) obj;
- return other.line == this.line && other.lineOffset == this.lineOffset;
- }
-
- @Override
- public int hashCode() {
- return 37 * this.line + lineOffset;
- }
-
- @Override
- public int compareTo(TextPointer o) {
- if (this.line == o.line()) {
- return Integer.compare(this.lineOffset, o.lineOffset());
- }
- return Integer.compare(this.line, o.line());
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import org.sonar.api.batch.fs.TextPointer;
-import org.sonar.api.batch.fs.TextRange;
-
-/**
- * @since 5.2
- */
-public class DefaultTextRange implements TextRange {
-
- private final TextPointer start;
- private final TextPointer end;
-
- public DefaultTextRange(TextPointer start, TextPointer end) {
- this.start = start;
- this.end = end;
- }
-
- @Override
- public TextPointer start() {
- return start;
- }
-
- @Override
- public TextPointer end() {
- return end;
- }
-
- @Override
- public boolean overlap(TextRange another) {
- // [A,B] and [C,D]
- // B > C && D > A
- return this.end.compareTo(another.start()) > 0 && another.end().compareTo(this.start) > 0;
- }
-
- @Override
- public String toString() {
- return "Range[from " + start + " to " + end + "]";
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof DefaultTextRange)) {
- return false;
- }
- DefaultTextRange other = (DefaultTextRange) obj;
- return start.equals(other.start) && end.equals(other.end);
- }
-
- @Override
- public int hashCode() {
- return start.hashCode() * 17 + end.hashCode();
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import java.util.Collection;
-import javax.annotation.CheckForNull;
-import javax.annotation.concurrent.Immutable;
-
-@Immutable
-public interface InputModuleHierarchy {
- DefaultInputModule root();
-
- boolean isRoot(DefaultInputModule module);
-
- Collection<DefaultInputModule> children(DefaultInputModule module);
-
- @CheckForNull
- DefaultInputModule parent(DefaultInputModule module);
-
- @CheckForNull
- String relativePath(DefaultInputModule module);
-
- @CheckForNull
- String relativePathToRoot(DefaultInputModule module);
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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 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;
-import org.sonar.api.utils.Preconditions;
-
-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;
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.coverage.internal;
-
-import java.util.Collections;
-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.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.coverage.CoverageType;
-import org.sonar.api.batch.sensor.coverage.NewCoverage;
-import org.sonar.api.batch.sensor.internal.DefaultStorable;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultCoverage extends DefaultStorable implements NewCoverage {
-
- private InputFile inputFile;
- private CoverageType type;
- private int totalCoveredLines = 0;
- private int totalConditions = 0;
- private int totalCoveredConditions = 0;
- private SortedMap<Integer, Integer> hitsByLine = new TreeMap<>();
- private SortedMap<Integer, Integer> conditionsByLine = new TreeMap<>();
- private SortedMap<Integer, Integer> coveredConditionsByLine = new TreeMap<>();
-
- public DefaultCoverage() {
- super();
- }
-
- public DefaultCoverage(@Nullable SensorStorage storage) {
- super(storage);
- }
-
- @Override
- public DefaultCoverage onFile(InputFile inputFile) {
- this.inputFile = inputFile;
- return this;
- }
-
- public InputFile inputFile() {
- return inputFile;
- }
-
- @Override
- public NewCoverage ofType(CoverageType type) {
- this.type = requireNonNull(type, "type can't be null");
- return this;
- }
-
- public CoverageType type() {
- return type;
- }
-
- @Override
- public NewCoverage lineHits(int line, int hits) {
- validateFile();
- if (isExcluded()) {
- return this;
- }
- validateLine(line);
-
- if (!hitsByLine.containsKey(line)) {
- hitsByLine.put(line, hits);
- if (hits > 0) {
- totalCoveredLines += 1;
- }
- }
- return this;
- }
-
- private void validateLine(int line) {
- checkState(line <= inputFile.lines(), "Line %s is out of range in the file %s (lines: %s)", line, inputFile, inputFile.lines());
- checkState(line > 0, "Line number must be strictly positive: %s", line);
- }
-
- private void validateFile() {
- requireNonNull(inputFile, "Call onFile() first");
- }
-
- @Override
- public NewCoverage conditions(int line, int conditions, int coveredConditions) {
- validateFile();
- if (isExcluded()) {
- return this;
- }
- validateLine(line);
-
- if (conditions > 0 && !conditionsByLine.containsKey(line)) {
- totalConditions += conditions;
- totalCoveredConditions += coveredConditions;
- conditionsByLine.put(line, conditions);
- coveredConditionsByLine.put(line, coveredConditions);
- }
- return this;
- }
-
- public int coveredLines() {
- return totalCoveredLines;
- }
-
- public int linesToCover() {
- return hitsByLine.size();
- }
-
- public int conditions() {
- return totalConditions;
- }
-
- public int coveredConditions() {
- return totalCoveredConditions;
- }
-
- public SortedMap<Integer, Integer> hitsByLine() {
- return Collections.unmodifiableSortedMap(hitsByLine);
- }
-
- public SortedMap<Integer, Integer> conditionsByLine() {
- return Collections.unmodifiableSortedMap(conditionsByLine);
- }
-
- public SortedMap<Integer, Integer> coveredConditionsByLine() {
- return Collections.unmodifiableSortedMap(coveredConditionsByLine);
- }
-
- @Override
- public void doSave() {
- validateFile();
- if (!isExcluded()) {
- storage.store(this);
- }
- }
-
- private boolean isExcluded() {
- return ((DefaultInputFile) inputFile).isExcludedForCoverage();
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.coverage.internal;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.cpd.internal;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
-import org.sonar.api.batch.sensor.internal.DefaultStorable;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-
-import static java.util.Collections.unmodifiableList;
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultCpdTokens extends DefaultStorable implements NewCpdTokens {
- private static final Logger LOG = Loggers.get(DefaultCpdTokens.class);
- private final List<TokensLine> result = new ArrayList<>();
- private DefaultInputFile inputFile;
- private int startLine = Integer.MIN_VALUE;
- private int startIndex = 0;
- private int currentIndex = 0;
- private StringBuilder sb = new StringBuilder();
- private TextRange lastRange;
- private boolean loggedTestCpdWarning = false;
-
- public DefaultCpdTokens(SensorStorage storage) {
- super(storage);
- }
-
- @Override
- public DefaultCpdTokens onFile(InputFile inputFile) {
- this.inputFile = (DefaultInputFile) requireNonNull(inputFile, "file can't be null");
- return this;
- }
-
- public InputFile inputFile() {
- return inputFile;
- }
-
- @Override
- public NewCpdTokens addToken(int startLine, int startLineOffset, int endLine, int endLineOffset, String image) {
- checkInputFileNotNull();
- TextRange newRange;
- try {
- newRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
- } catch (Exception e) {
- throw new IllegalArgumentException("Unable to register token in file " + inputFile, e);
- }
- return addToken(newRange, image);
- }
-
- @Override
- public DefaultCpdTokens addToken(TextRange range, String image) {
- requireNonNull(range, "Range should not be null");
- requireNonNull(image, "Image should not be null");
- checkInputFileNotNull();
- if (isExcludedForDuplication()) {
- return this;
- }
- checkState(lastRange == null || lastRange.end().compareTo(range.start()) <= 0,
- "Tokens of file %s should be provided in order.\nPrevious token: %s\nLast token: %s", inputFile, lastRange, range);
-
- int line = range.start().line();
- if (line != startLine) {
- addNewTokensLine(result, startIndex, currentIndex, startLine, sb);
- startIndex = currentIndex + 1;
- startLine = line;
- }
- currentIndex++;
- sb.append(image);
- lastRange = range;
-
- return this;
- }
-
- private boolean isExcludedForDuplication() {
- if (inputFile.isExcludedForDuplication()) {
- return true;
- }
- if (inputFile.type() == InputFile.Type.TEST) {
- if (!loggedTestCpdWarning) {
- LOG.warn("Duplication reported for '{}' will be ignored because it's a test file.", inputFile);
- loggedTestCpdWarning = true;
- }
- return true;
- }
- return false;
- }
-
- public List<TokensLine> getTokenLines() {
- return unmodifiableList(new ArrayList<>(result));
- }
-
- private static void addNewTokensLine(List<TokensLine> result, int startUnit, int endUnit, int startLine, StringBuilder sb) {
- if (sb.length() != 0) {
- result.add(new TokensLine(startUnit, endUnit, startLine, sb.toString()));
- sb.setLength(0);
- }
- }
-
- @Override
- protected void doSave() {
- checkState(inputFile != null, "Call onFile() first");
- if (isExcludedForDuplication()) {
- return;
- }
- addNewTokensLine(result, startIndex, currentIndex, startLine, sb);
- storage.store(this);
- }
-
- private void checkInputFileNotNull() {
- checkState(inputFile != null, "Call onFile() first");
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.error.internal;
-
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextPointer;
-import org.sonar.api.batch.sensor.error.AnalysisError;
-import org.sonar.api.batch.sensor.error.NewAnalysisError;
-import org.sonar.api.batch.sensor.internal.DefaultStorable;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultAnalysisError extends DefaultStorable implements NewAnalysisError, AnalysisError {
- private InputFile inputFile;
- private String message;
- private TextPointer location;
-
- public DefaultAnalysisError() {
- super(null);
- }
-
- public DefaultAnalysisError(SensorStorage storage) {
- super(storage);
- }
-
- @Override
- public InputFile inputFile() {
- return inputFile;
- }
-
- @Override
- public String message() {
- return message;
- }
-
- @Override
- public TextPointer location() {
- return location;
- }
-
- @Override
- public NewAnalysisError onFile(InputFile inputFile) {
- checkArgument(inputFile != null, "Cannot use a inputFile that is null");
- checkState(this.inputFile == null, "onFile() already called");
- this.inputFile = inputFile;
- return this;
- }
-
- @Override
- public NewAnalysisError message(String message) {
- this.message = message;
- return this;
- }
-
- @Override
- public NewAnalysisError at(TextPointer location) {
- checkState(this.location == null, "at() already called");
- this.location = location;
- return this;
- }
-
- @Override
- protected void doSave() {
- requireNonNull(this.inputFile, "inputFile is mandatory on AnalysisError");
- storage.store(this);
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.error.internal;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.internal;
-
-import javax.annotation.Nullable;
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public abstract class DefaultStorable {
-
- protected final transient SensorStorage storage;
- private transient boolean saved = false;
-
- public DefaultStorable() {
- this.storage = null;
- }
-
- public DefaultStorable(@Nullable SensorStorage storage) {
- this.storage = storage;
- }
-
- public final void save() {
- requireNonNull(this.storage, "No persister on this object");
- checkState(!saved, "This object was already saved");
- doSave();
- this.saved = true;
- }
-
- protected abstract void doSave();
-
- @Override
- public String toString() {
- return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
- }
-
-}
*/
package org.sonar.api.batch.sensor.internal;
-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.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.AnalysisError;
import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
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.rule.AdHocRule;
-import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
+import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
import org.sonar.api.scanner.ScannerSide;
/**
/**
* @since 5.2
*/
- void store(DefaultCoverage defaultCoverage);
+ void store(NewCoverage defaultCoverage);
/**
* @since 5.5
*/
- void store(DefaultCpdTokens defaultCpdTokens);
+ void store(NewCpdTokens cpdTokens);
/**
* @since 5.6
*/
- void store(DefaultSymbolTable symbolTable);
+ void store(NewSymbolTable symbolTable);
/**
* @since 6.0
/**
* @since 7.2
*/
- void store(DefaultSignificantCode significantCode);
+ void store(NewSignificantCode significantCode);
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.symbol.internal;
-
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.internal.DefaultStorable;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.symbol.NewSymbol;
-import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
-
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultSymbolTable extends DefaultStorable implements NewSymbolTable {
-
- private final Map<TextRange, Set<TextRange>> referencesBySymbol;
- private DefaultInputFile inputFile;
-
- public DefaultSymbolTable(SensorStorage storage) {
- super(storage);
- referencesBySymbol = new LinkedHashMap<>();
- }
-
- public Map<TextRange, Set<TextRange>> getReferencesBySymbol() {
- return referencesBySymbol;
- }
-
- @Override
- public DefaultSymbolTable onFile(InputFile inputFile) {
- requireNonNull(inputFile, "file can't be null");
- this.inputFile = (DefaultInputFile) inputFile;
- return this;
- }
-
- public InputFile inputFile() {
- return inputFile;
- }
-
- @Override
- public NewSymbol newSymbol(int startLine, int startLineOffset, int endLine, int endLineOffset) {
- checkInputFileNotNull();
- TextRange declarationRange;
- try {
- declarationRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
- } catch (Exception e) {
- throw new IllegalArgumentException("Unable to create symbol on file " + inputFile, e);
- }
- return newSymbol(declarationRange);
- }
-
- @Override
- public NewSymbol newSymbol(int startOffset, int endOffset) {
- checkInputFileNotNull();
- TextRange declarationRange;
- try {
- declarationRange = inputFile.newRange(startOffset, endOffset);
- } catch (Exception e) {
- throw new IllegalArgumentException("Unable to create symbol on file " + inputFile, e);
- }
- return newSymbol(declarationRange);
- }
-
- @Override
- public NewSymbol newSymbol(TextRange range) {
- checkInputFileNotNull();
- TreeSet<TextRange> references = new TreeSet<>((o1, o2) -> o1.start().compareTo(o2.start()));
- referencesBySymbol.put(range, references);
- return new DefaultSymbol(inputFile, range, references);
- }
-
- private static class DefaultSymbol implements NewSymbol {
-
- private final Collection<TextRange> references;
- private final DefaultInputFile inputFile;
- private final TextRange declaration;
-
- public DefaultSymbol(DefaultInputFile inputFile, TextRange declaration, Collection<TextRange> references) {
- this.inputFile = inputFile;
- this.declaration = declaration;
- this.references = references;
- }
-
- @Override
- public NewSymbol newReference(int startOffset, int endOffset) {
- TextRange referenceRange;
- try {
- referenceRange = inputFile.newRange(startOffset, endOffset);
- } catch (Exception e) {
- throw new IllegalArgumentException("Unable to create symbol reference on file " + inputFile, e);
- }
- return newReference(referenceRange);
- }
-
- @Override
- public NewSymbol newReference(int startLine, int startLineOffset, int endLine, int endLineOffset) {
- TextRange referenceRange;
- try {
- referenceRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
- } catch (Exception e) {
- throw new IllegalArgumentException("Unable to create symbol reference on file " + inputFile, e);
- }
- return newReference(referenceRange);
- }
-
- @Override
- public NewSymbol newReference(TextRange range) {
- requireNonNull(range, "Provided range is null");
- checkArgument(!declaration.overlap(range), "Overlapping symbol declaration and reference for symbol at %s", declaration);
- references.add(range);
- return this;
- }
-
- }
-
- @Override
- protected void doSave() {
- checkInputFileNotNull();
- storage.store(this);
- }
-
- private void checkInputFileNotNull() {
- checkState(inputFile != null, "Call onFile() first");
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.symbol.internal;
import java.util.Set;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.scanner.ScannerSide;
/**
* @since 3.6
*/
@ScannerSide
-public class NoSonarFilter {
+public abstract class NoSonarFilter {
/**
* Register lines in a file that contains the NOSONAR flag.
* @since 5.0
* @since 7.6 the method can be called multiple times by different sensors, and NOSONAR lines are merged
*/
- public NoSonarFilter noSonarInFile(InputFile inputFile, Set<Integer> noSonarLines) {
- ((DefaultInputFile) inputFile).noSonarAt(noSonarLines);
- return this;
- }
-
+ public abstract NoSonarFilter noSonarInFile(InputFile inputFile, Set<Integer> noSonarLines);
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-
-import java.io.File;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultInputDirTest {
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- @Test
- public void test() throws Exception {
- File baseDir = temp.newFolder();
- DefaultInputDir inputDir = new DefaultInputDir("ABCDE", "src")
- .setModuleBaseDir(baseDir.toPath());
-
- assertThat(inputDir.key()).isEqualTo("ABCDE:src");
- assertThat(inputDir.file().getAbsolutePath()).isEqualTo(new File(baseDir, "src").getAbsolutePath());
- assertThat(inputDir.relativePath()).isEqualTo("src");
- assertThat(new File(inputDir.relativePath())).isRelative();
- assertThat(inputDir.absolutePath()).endsWith("src");
- assertThat(new File(inputDir.absolutePath())).isAbsolute();
- }
-
- @Test
- public void testEqualsAndHashCode() throws Exception {
- DefaultInputDir inputDir1 = new DefaultInputDir("ABCDE", "src");
-
- DefaultInputDir inputDir2 = new DefaultInputDir("ABCDE", "src");
-
- assertThat(inputDir1.equals(inputDir1)).isTrue();
- assertThat(inputDir1.equals(inputDir2)).isTrue();
- assertThat(inputDir1.equals("foo")).isFalse();
-
- assertThat(inputDir1.hashCode()).isEqualTo(63545559);
-
- assertThat(inputDir1.toString()).contains("[moduleKey=ABCDE, relative=src, basedir=null");
-
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.StringReader;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-import java.util.stream.Collectors;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextRange;
-import org.sonar.scanner.fs.FileMetadata;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-
-public class DefaultInputFileTest {
-
- private static final String PROJECT_RELATIVE_PATH = "module1/src/Foo.php";
- private static final String MODULE_RELATIVE_PATH = "src/Foo.php";
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- private DefaultIndexedFile indexedFile;
-
- private Path baseDir;
- private SensorStrategy sensorStrategy;
-
- @Before
- public void prepare() throws IOException {
- baseDir = temp.newFolder().toPath();
- sensorStrategy = new SensorStrategy();
- indexedFile = new DefaultIndexedFile(baseDir.resolve(PROJECT_RELATIVE_PATH), "ABCDE", PROJECT_RELATIVE_PATH, MODULE_RELATIVE_PATH, InputFile.Type.TEST, "php", 0,
- sensorStrategy);
- }
-
- @Test
- public void test() throws Exception {
-
- Metadata metadata = new Metadata(42, 42, "", new int[0], new int[0], 10);
- DefaultInputFile inputFile = new DefaultInputFile(indexedFile, (f) -> f.setMetadata(metadata))
- .setStatus(InputFile.Status.ADDED)
- .setCharset(StandardCharsets.ISO_8859_1);
-
- assertThat(inputFile.absolutePath()).endsWith("Foo.php");
- assertThat(inputFile.filename()).isEqualTo("Foo.php");
- assertThat(inputFile.uri()).hasPath(baseDir.resolve(PROJECT_RELATIVE_PATH).toUri().getPath());
- assertThat(new File(inputFile.absolutePath())).isAbsolute();
- assertThat(inputFile.language()).isEqualTo("php");
- assertThat(inputFile.status()).isEqualTo(InputFile.Status.ADDED);
- assertThat(inputFile.type()).isEqualTo(InputFile.Type.TEST);
- assertThat(inputFile.lines()).isEqualTo(42);
- assertThat(inputFile.charset()).isEqualTo(StandardCharsets.ISO_8859_1);
-
- assertThat(inputFile.getModuleRelativePath()).isEqualTo(MODULE_RELATIVE_PATH);
- assertThat(inputFile.getProjectRelativePath()).isEqualTo(PROJECT_RELATIVE_PATH);
-
- sensorStrategy.setGlobal(false);
- assertThat(inputFile.relativePath()).isEqualTo(MODULE_RELATIVE_PATH);
- assertThat(new File(inputFile.relativePath())).isRelative();
- sensorStrategy.setGlobal(true);
- assertThat(inputFile.relativePath()).isEqualTo(PROJECT_RELATIVE_PATH);
- assertThat(new File(inputFile.relativePath())).isRelative();
- }
-
- @Test
- public void test_content() throws IOException {
- Path testFile = baseDir.resolve(PROJECT_RELATIVE_PATH);
- Files.createDirectories(testFile.getParent());
- String content = "test é string";
- Files.write(testFile, content.getBytes(StandardCharsets.ISO_8859_1));
-
- assertThat(Files.readAllLines(testFile, StandardCharsets.ISO_8859_1).get(0)).hasSize(content.length());
-
- Metadata metadata = new Metadata(42, 30, "", new int[0], new int[0], 10);
-
- DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> f.setMetadata(metadata))
- .setStatus(InputFile.Status.ADDED)
- .setCharset(StandardCharsets.ISO_8859_1);
-
- assertThat(inputFile.contents()).isEqualTo(content);
- try (InputStream inputStream = inputFile.inputStream()) {
- String result = new BufferedReader(new InputStreamReader(inputStream, inputFile.charset())).lines().collect(Collectors.joining());
- assertThat(result).isEqualTo(content);
- }
-
- }
-
- @Test
- public void test_content_exclude_bom() throws IOException {
- Path testFile = baseDir.resolve(PROJECT_RELATIVE_PATH);
- Files.createDirectories(testFile.getParent());
- try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(testFile.toFile()), StandardCharsets.UTF_8))) {
- out.write('\ufeff');
- }
- String content = "test é string €";
- Files.write(testFile, content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
-
- assertThat(Files.readAllLines(testFile, StandardCharsets.UTF_8).get(0)).hasSize(content.length() + 1);
-
- Metadata metadata = new Metadata(42, 30, "", new int[0], new int[0], 10);
-
- DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> f.setMetadata(metadata))
- .setStatus(InputFile.Status.ADDED)
- .setCharset(StandardCharsets.UTF_8);
-
- assertThat(inputFile.contents()).isEqualTo(content);
- try (InputStream inputStream = inputFile.inputStream()) {
- String result = new BufferedReader(new InputStreamReader(inputStream, inputFile.charset())).lines().collect(Collectors.joining());
- assertThat(result).isEqualTo(content);
- }
-
- }
-
- @Test
- public void test_equals_and_hashcode() throws Exception {
- DefaultInputFile f1 = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class));
- DefaultInputFile f1a = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class));
- DefaultInputFile f2 = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Bar.php", null), (f) -> mock(Metadata.class));
-
- assertThat(f1).isEqualTo(f1);
- assertThat(f1).isEqualTo(f1a);
- assertThat(f1).isNotEqualTo(f2);
- assertThat(f1.equals("foo")).isFalse();
- assertThat(f1.equals(null)).isFalse();
-
- assertThat(f1.hashCode()).isEqualTo(f1.hashCode());
- assertThat(f1.hashCode()).isEqualTo(f1a.hashCode());
- }
-
- @Test
- public void test_toString() throws Exception {
- DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class));
- assertThat(file.toString()).isEqualTo(MODULE_RELATIVE_PATH);
- }
-
- @Test
- public void checkValidPointer() {
- Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {9, 15}, 16);
- DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
- assertThat(file.newPointer(1, 0).line()).isEqualTo(1);
- assertThat(file.newPointer(1, 0).lineOffset()).isEqualTo(0);
- // Don't fail
- file.newPointer(1, 9);
- file.newPointer(2, 0);
- file.newPointer(2, 5);
-
- try {
- file.newPointer(0, 1);
- fail();
- } catch (Exception e) {
- assertThat(e).hasMessage("0 is not a valid line for a file");
- }
- try {
- file.newPointer(3, 1);
- fail();
- } catch (Exception e) {
- assertThat(e).hasMessage("3 is not a valid line for pointer. File src/Foo.php has 2 line(s)");
- }
- try {
- file.newPointer(1, -1);
- fail();
- } catch (Exception e) {
- assertThat(e).hasMessage("-1 is not a valid line offset for a file");
- }
- try {
- file.newPointer(1, 10);
- fail();
- } catch (Exception e) {
- assertThat(e).hasMessage("10 is not a valid line offset for pointer. File src/Foo.php has 9 character(s) at line 1");
- }
- }
-
- @Test
- public void checkValidPointerUsingGlobalOffset() {
- Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {8, 15}, 16);
- DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
- assertThat(file.newPointer(0).line()).isEqualTo(1);
- assertThat(file.newPointer(0).lineOffset()).isEqualTo(0);
-
- assertThat(file.newPointer(9).line()).isEqualTo(1);
- // Ignore eol characters
- assertThat(file.newPointer(9).lineOffset()).isEqualTo(8);
-
- assertThat(file.newPointer(10).line()).isEqualTo(2);
- assertThat(file.newPointer(10).lineOffset()).isEqualTo(0);
-
- assertThat(file.newPointer(15).line()).isEqualTo(2);
- assertThat(file.newPointer(15).lineOffset()).isEqualTo(5);
-
- assertThat(file.newPointer(16).line()).isEqualTo(2);
- // Ignore eol characters
- assertThat(file.newPointer(16).lineOffset()).isEqualTo(5);
-
- try {
- file.newPointer(-1);
- fail();
- } catch (Exception e) {
- assertThat(e).hasMessage("-1 is not a valid offset for a file");
- }
-
- try {
- file.newPointer(17);
- fail();
- } catch (Exception e) {
- assertThat(e).hasMessage("17 is not a valid offset for file src/Foo.php. Max offset is 16");
- }
- }
-
- @Test
- public void checkValidRange() {
- Metadata metadata = new FileMetadata().readMetadata(new StringReader("bla bla a\nabcde"));
- DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
-
- assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(2, 1)).start().line()).isEqualTo(1);
- // Don't fail
- file.newRange(file.newPointer(1, 0), file.newPointer(1, 1));
- file.newRange(file.newPointer(1, 0), file.newPointer(1, 9));
- file.newRange(file.newPointer(1, 0), file.newPointer(2, 0));
- assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(2, 5))).isEqualTo(file.newRange(0, 15));
-
- try {
- file.newRange(file.newPointer(1, 0), file.newPointer(1, 0));
- fail();
- } catch (Exception e) {
- assertThat(e).hasMessage("Start pointer [line=1, lineOffset=0] should be before end pointer [line=1, lineOffset=0]");
- }
- try {
- file.newRange(file.newPointer(1, 0), file.newPointer(1, 10));
- fail();
- } catch (Exception e) {
- assertThat(e).hasMessage("10 is not a valid line offset for pointer. File src/Foo.php has 9 character(s) at line 1");
- }
- }
-
- @Test
- public void selectLine() {
- Metadata metadata = new FileMetadata().readMetadata(new StringReader("bla bla a\nabcde\n\nabc"));
- DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
-
- assertThat(file.selectLine(1).start().line()).isEqualTo(1);
- assertThat(file.selectLine(1).start().lineOffset()).isEqualTo(0);
- assertThat(file.selectLine(1).end().line()).isEqualTo(1);
- assertThat(file.selectLine(1).end().lineOffset()).isEqualTo(9);
-
- // Don't fail when selecting empty line
- assertThat(file.selectLine(3).start().line()).isEqualTo(3);
- assertThat(file.selectLine(3).start().lineOffset()).isEqualTo(0);
- assertThat(file.selectLine(3).end().line()).isEqualTo(3);
- assertThat(file.selectLine(3).end().lineOffset()).isEqualTo(0);
-
- try {
- file.selectLine(5);
- fail();
- } catch (Exception e) {
- assertThat(e).hasMessage("5 is not a valid line for pointer. File src/Foo.php has 4 line(s)");
- }
- }
-
- @Test
- public void checkValidRangeUsingGlobalOffset() {
- Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {9, 15}, 16);
- DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
- TextRange newRange = file.newRange(10, 13);
- assertThat(newRange.start().line()).isEqualTo(2);
- assertThat(newRange.start().lineOffset()).isEqualTo(0);
- assertThat(newRange.end().line()).isEqualTo(2);
- assertThat(newRange.end().lineOffset()).isEqualTo(3);
- }
-
- @Test
- public void testRangeOverlap() {
- Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {9, 15}, 16);
- DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
- // Don't fail
- assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)))).isTrue();
- assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 2)))).isTrue();
- assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 1), file.newPointer(1, 2)))).isFalse();
- assertThat(file.newRange(file.newPointer(1, 2), file.newPointer(1, 3)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 2)))).isFalse();
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultInputModuleTest {
-
- private static final String FILE_1 = "file1";
- private static final String TEST_1 = "test1";
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- @Test
- public void check_getters() throws IOException {
- ProjectDefinition def = ProjectDefinition.create();
- def.setKey("moduleKey");
- File baseDir = temp.newFolder();
- Path src = baseDir.toPath().resolve(FILE_1);
- Files.createFile(src);
- Path test = baseDir.toPath().resolve(TEST_1);
- Files.createFile(test);
- def.setBaseDir(baseDir);
- File workDir = temp.newFolder();
- def.setWorkDir(workDir);
- def.setSources(FILE_1);
- def.setTests(TEST_1);
- DefaultInputModule module = new DefaultInputModule(def);
-
- assertThat(module.key()).isEqualTo("moduleKey");
- assertThat(module.definition()).isEqualTo(def);
- assertThat(module.getBranch()).isNull();
- assertThat(module.getBaseDir()).isEqualTo(baseDir.toPath());
- assertThat(module.getKeyWithBranch()).isEqualTo("moduleKey");
- assertThat(module.getWorkDir()).isEqualTo(workDir.toPath());
- assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
- assertThat(module.getSourceDirsOrFiles().get()).containsExactlyInAnyOrder(src);
- assertThat(module.getTestDirsOrFiles().get()).containsExactlyInAnyOrder(test);
- assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
-
- assertThat(module.isFile()).isFalse();
- }
-
- @Test
- public void no_sources() throws IOException {
- ProjectDefinition def = ProjectDefinition.create();
- def.setKey("moduleKey");
- File baseDir = temp.newFolder();
- Path src = baseDir.toPath().resolve(FILE_1);
- Files.createFile(src);
- Path test = baseDir.toPath().resolve(TEST_1);
- Files.createFile(test);
- def.setBaseDir(baseDir);
- File workDir = temp.newFolder();
- def.setWorkDir(workDir);
- DefaultInputModule module = new DefaultInputModule(def);
-
- assertThat(module.key()).isEqualTo("moduleKey");
- assertThat(module.definition()).isEqualTo(def);
- assertThat(module.getBranch()).isNull();
- assertThat(module.getBaseDir()).isEqualTo(baseDir.toPath());
- assertThat(module.getKeyWithBranch()).isEqualTo("moduleKey");
- assertThat(module.getWorkDir()).isEqualTo(workDir.toPath());
- assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
- assertThat(module.getSourceDirsOrFiles()).isNotPresent();
- assertThat(module.getTestDirsOrFiles()).isNotPresent();
- assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
-
- assertThat(module.isFile()).isFalse();
- }
-
- @Test
- public void working_directory_should_be_hidden() throws IOException {
- ProjectDefinition def = ProjectDefinition.create();
- File workDir = temp.newFolder(".sonar");
- def.setWorkDir(workDir);
- File baseDir = temp.newFolder();
- def.setBaseDir(baseDir);
- DefaultInputModule module = new DefaultInputModule(def);
- assertThat(workDir.isHidden()).isTrue();
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultInputProjectTest {
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- @Test
- public void testGetters() throws IOException {
- ProjectDefinition def = ProjectDefinition.create();
- def.setKey("projectKey");
- def.setName("projectName");
- File baseDir = temp.newFolder();
- def.setBaseDir(baseDir);
- def.setDescription("desc");
- File workDir = temp.newFolder();
- def.setWorkDir(workDir);
- def.setSources("file1");
- def.setTests("test1");
- AbstractProjectOrModule project = new DefaultInputProject(def);
-
- assertThat(project.key()).isEqualTo("projectKey");
- assertThat(project.getName()).isEqualTo("projectName");
- assertThat(project.getOriginalName()).isEqualTo("projectName");
- assertThat(project.definition()).isEqualTo(def);
- assertThat(project.getBranch()).isNull();
- assertThat(project.getBaseDir()).isEqualTo(baseDir.toPath());
- assertThat(project.getKeyWithBranch()).isEqualTo("projectKey");
- assertThat(project.getDescription()).isEqualTo("desc");
- assertThat(project.getWorkDir()).isEqualTo(workDir.toPath());
- assertThat(project.getEncoding()).isEqualTo(Charset.defaultCharset());
-
- assertThat(project.properties()).hasSize(5);
-
- assertThat(project.isFile()).isFalse();
- }
-
- @Test
- public void testEncoding() throws IOException {
- ProjectDefinition def = ProjectDefinition.create();
- def.setKey("projectKey");
- def.setName("projectName");
- File baseDir = temp.newFolder();
- def.setBaseDir(baseDir);
- def.setProjectVersion("version");
- def.setDescription("desc");
- File workDir = temp.newFolder();
- def.setWorkDir(workDir);
- def.setSources("file1");
- def.setProperty("sonar.sourceEncoding", "UTF-16");
- AbstractProjectOrModule project = new DefaultInputProject(def);
-
- assertThat(project.getEncoding()).isEqualTo(StandardCharsets.UTF_16);
- }
-
-}
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.IndexedFile;
+import org.sonar.scanner.fs.DefaultIndexedFile;
import static org.assertj.core.api.Assertions.assertThat;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.fs.internal;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import org.apache.commons.io.IOUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.InputFile.Status;
-import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class TestInputFileBuilderTest {
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- @Test
- public void setContent() throws IOException {
- DefaultInputFile file = TestInputFileBuilder.create("module", "invalidPath")
- .setContents("my content")
- .setCharset(StandardCharsets.UTF_8)
- .build();
- assertThat(file.contents()).isEqualTo("my content");
- assertThat(IOUtils.toString(file.inputStream())).isEqualTo("my content");
- }
-
- @Test
- public void testGetters() {
- DefaultInputFile file = TestInputFileBuilder.create("module", new File("baseDir"), new File("baseDir", "path"))
- .setStatus(Status.SAME)
- .setType(Type.MAIN)
- .build();
-
- assertThat(file.type()).isEqualTo(Type.MAIN);
- assertThat(file.status()).isEqualTo(Status.SAME);
- assertThat(file.isPublished()).isTrue();
- assertThat(file.type()).isEqualTo(Type.MAIN);
- assertThat(file.relativePath()).isEqualTo("path");
- assertThat(file.absolutePath()).isEqualTo("baseDir/path");
-
- }
-
- @Test
- public void testCreateInputModule() throws IOException {
- File baseDir = temp.newFolder();
- AbstractProjectOrModule module = TestInputFileBuilder.newDefaultInputModule("key", baseDir);
- assertThat(module.key()).isEqualTo("key");
- assertThat(module.getBaseDir()).isEqualTo(baseDir.toPath());
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.sensor.internal.SensorStorage;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-
-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));
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.cpd.internal;
-
-import org.junit.Test;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
-import static org.assertj.core.api.Assertions.tuple;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-
-public class DefaultCpdTokensTest {
- private final SensorStorage sensorStorage = mock(SensorStorage.class);
-
- private final DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.java")
- .setLines(2)
- .setOriginalLineStartOffsets(new int[] {0, 50})
- .setOriginalLineEndOffsets(new int[] {49, 100})
- .setLastValidOffset(101)
- .build();
-
- @Test
- public void save_no_tokens() {
- DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
- .onFile(inputFile);
-
- tokens.save();
-
- verify(sensorStorage).store(tokens);
-
- assertThat(tokens.inputFile()).isEqualTo(inputFile);
- }
-
- @Test
- public void save_one_token() {
- DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
- .onFile(inputFile)
- .addToken(inputFile.newRange(1, 2, 1, 5), "foo");
-
- tokens.save();
-
- verify(sensorStorage).store(tokens);
-
- assertThat(tokens.getTokenLines()).extracting("value", "startLine", "hashCode", "startUnit", "endUnit").containsExactly(tuple("foo", 1, "foo".hashCode(), 1, 1));
- }
-
- @Test
- public void handle_exclusions() {
- inputFile.setExcludedForDuplication(true);
- DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
- .onFile(inputFile)
- .addToken(inputFile.newRange(1, 2, 1, 5), "foo");
-
- tokens.save();
-
- verifyZeroInteractions(sensorStorage);
-
- assertThat(tokens.getTokenLines()).isEmpty();
- }
-
- @Test
- public void dont_save_for_test_files() {
- DefaultInputFile testInputFile = new TestInputFileBuilder("foo", "src/Foo.java")
- .setLines(2)
- .setOriginalLineStartOffsets(new int[] {0, 50})
- .setOriginalLineEndOffsets(new int[] {49, 100})
- .setLastValidOffset(101)
- .setType(InputFile.Type.TEST)
- .build();
-
- DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
- .onFile(testInputFile)
- .addToken(testInputFile.newRange(1, 2, 1, 5), "foo");
-
- tokens.save();
- verifyZeroInteractions(sensorStorage);
- assertThat(tokens.getTokenLines()).isEmpty();
- }
-
- @Test
- public void save_many_tokens() {
- DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
- .onFile(inputFile)
- .addToken(inputFile.newRange(1, 2, 1, 5), "foo")
- .addToken(inputFile.newRange(1, 6, 1, 10), "bar")
- .addToken(inputFile.newRange(1, 20, 1, 25), "biz")
- .addToken(inputFile.newRange(2, 1, 2, 10), "next");
-
- tokens.save();
-
- verify(sensorStorage).store(tokens);
-
- assertThat(tokens.getTokenLines())
- .extracting("value", "startLine", "hashCode", "startUnit", "endUnit")
- .containsExactly(
- tuple("foobarbiz", 1, "foobarbiz".hashCode(), 1, 3),
- tuple("next", 2, "next".hashCode(), 4, 4));
- }
-
- @Test
- public void basic_validation() {
- SensorStorage sensorStorage = mock(SensorStorage.class);
- DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage);
- try {
- tokens.save();
- fail("Expected exception");
- } catch (Exception e) {
- assertThat(e).hasMessage("Call onFile() first");
- }
- try {
- tokens.addToken(inputFile.newRange(1, 2, 1, 5), "foo");
- fail("Expected exception");
- } catch (Exception e) {
- assertThat(e).hasMessage("Call onFile() first");
- }
- try {
- tokens.addToken(null, "foo");
- fail("Expected exception");
- } catch (Exception e) {
- assertThat(e).hasMessage("Range should not be null");
- }
- try {
- tokens.addToken(inputFile.newRange(1, 2, 1, 5), null);
- fail("Expected exception");
- } catch (Exception e) {
- assertThat(e).hasMessage("Image should not be null");
- }
- }
-
- @Test
- public void validate_tokens_order() {
- SensorStorage sensorStorage = mock(SensorStorage.class);
- DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
- .onFile(inputFile)
- .addToken(inputFile.newRange(1, 6, 1, 10), "bar");
-
- try {
- tokens.addToken(inputFile.newRange(1, 2, 1, 5), "foo");
- fail("Expected exception");
- } catch (Exception e) {
- assertThat(e).hasMessage("Tokens of file src/Foo.java should be provided in order.\n" +
- "Previous token: Range[from [line=1, lineOffset=6] to [line=1, lineOffset=10]]\n" +
- "Last token: Range[from [line=1, lineOffset=2] to [line=1, lineOffset=5]]");
- }
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.error.internal;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
-import org.junit.Before;
-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.TextPointer;
-import org.sonar.api.batch.fs.internal.DefaultTextPointer;
-import org.sonar.api.batch.sensor.error.NewAnalysisError;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.*;
-
-public class DefaultAnalysisErrorTest {
- private InputFile inputFile;
- private SensorStorage storage;
- private TextPointer textPointer;
-
- @Rule
- public ExpectedException exception = ExpectedException.none();
-
- @Before
- public void setUp() {
- inputFile = new TestInputFileBuilder("module1", "src/File.java").build();
- textPointer = new DefaultTextPointer(5, 2);
- storage = mock(SensorStorage.class);
- }
-
- @Test
- public void test_analysis_error() {
- DefaultAnalysisError analysisError = new DefaultAnalysisError(storage);
- analysisError.onFile(inputFile)
- .at(textPointer)
- .message("msg");
-
- assertThat(analysisError.location()).isEqualTo(textPointer);
- assertThat(analysisError.message()).isEqualTo("msg");
- assertThat(analysisError.inputFile()).isEqualTo(inputFile);
- }
-
- @Test
- public void test_save() {
- DefaultAnalysisError analysisError = new DefaultAnalysisError(storage);
- analysisError.onFile(inputFile).save();
-
- verify(storage).store(analysisError);
- verifyNoMoreInteractions(storage);
- }
-
- @Test
- public void test_no_storage() {
- exception.expect(NullPointerException.class);
- DefaultAnalysisError analysisError = new DefaultAnalysisError();
- analysisError.onFile(inputFile).save();
- }
-
- @Test
- public void test_validation() {
- try {
- new DefaultAnalysisError(storage).onFile(null);
- fail("Expected exception");
- } catch (IllegalArgumentException e) {
- // expected
- }
-
- NewAnalysisError error = new DefaultAnalysisError(storage).onFile(inputFile);
- try {
- error.onFile(inputFile);
- fail("Expected exception");
- } catch (IllegalStateException e) {
- // expected
- }
-
- error = new DefaultAnalysisError(storage).at(textPointer);
- try {
- error.at(textPointer);
- fail("Expected exception");
- } catch (IllegalStateException e) {
- // expected
- }
-
- try {
- new DefaultAnalysisError(storage).save();
- fail("Expected exception");
- } catch (NullPointerException e) {
- // expected
- }
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.symbol.internal;
-
-import java.util.Map;
-import java.util.Set;
-import org.junit.Before;
-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.TextRange;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class DefaultSymbolTableTest {
-
- private static final InputFile INPUT_FILE = new TestInputFileBuilder("foo", "src/Foo.java")
- .setLines(2)
- .setOriginalLineStartOffsets(new int[] {0, 50})
- .setOriginalLineEndOffsets(new int[] {49, 100})
- .setLastValidOffset(101)
- .build();
-
- private Map<TextRange, Set<TextRange>> referencesPerSymbol;
-
- @Rule
- public ExpectedException throwable = ExpectedException.none();
-
- @Before
- public void setUpSampleSymbols() {
-
- DefaultSymbolTable symbolTableBuilder = new DefaultSymbolTable(mock(SensorStorage.class))
- .onFile(INPUT_FILE);
- symbolTableBuilder
- .newSymbol(0, 10)
- .newReference(12, 15)
- .newReference(2, 10, 2, 15);
-
- symbolTableBuilder.newSymbol(1, 12, 1, 15).newReference(52, 55);
-
- symbolTableBuilder.save();
-
- referencesPerSymbol = symbolTableBuilder.getReferencesBySymbol();
- }
-
- @Test
- public void should_register_symbols() {
- assertThat(referencesPerSymbol).hasSize(2);
- }
-
-}
import java.util.Arrays;
import java.util.HashSet;
import org.junit.Test;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.scanner.issue.DefaultNoSonarFilter;
import static org.assertj.core.api.Assertions.assertThat;
@Test
public void should_store_nosonar_lines_on_inputfile() {
DefaultInputFile f = TestInputFileBuilder.create("module1", "myfile.java").setLines(8).build();
- new NoSonarFilter().noSonarInFile(f, new HashSet<>(Arrays.asList(1, 4)));
+ new DefaultNoSonarFilter().noSonarInFile(f, new HashSet<>(Arrays.asList(1, 4)));
assertThat(f.hasNoSonarAt(1)).isTrue();
assertThat(f.hasNoSonarAt(2)).isFalse();
import org.picocontainer.ComponentLifecycle;
import org.picocontainer.PicoContainer;
import org.picocontainer.injectors.ProviderAdapter;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.utils.TempFolder;
import org.sonar.api.utils.internal.DefaultTempFolder;
+import org.sonar.scanner.fs.DefaultInputProject;
public class AnalysisTempFolderProvider extends ProviderAdapter implements ComponentLifecycle<TempFolder> {
static final String TMP_NAME = ".sonartmp";
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.index.ClonePart;
import org.sonar.duplications.index.PackedMemoryCloneIndex.ResourceBlocks;
import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
+import org.sonar.scanner.fs.DefaultInputComponent;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReport.Duplicate;
import org.sonar.scanner.protocol.output.ScannerReport.Duplication;
saveDuplications(inputFile, filtered);
}
- @VisibleForTesting final void saveDuplications(final DefaultInputComponent component, List<CloneGroup> duplications) {
+ @VisibleForTesting
+ final void saveDuplications(final DefaultInputComponent component, List<CloneGroup> duplications) {
if (duplications.size() > MAX_CLONE_GROUP_PER_FILE) {
LOG.warn("Too many duplication groups on file {}. Keep only the first {} groups.", component, MAX_CLONE_GROUP_PER_FILE);
}
import org.apache.commons.lang.StringUtils;
import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.config.Configuration;
import org.sonar.duplications.block.BlockChunker;
+import org.sonar.scanner.fs.DefaultInputProject;
public class CpdSettings {
private final Configuration settings;
}
/**
- * Not applicable to Java, as the {@link BlockChunker} that it uses does not record start and end units of each block.
- * Also, it uses statements instead of tokens.
+ * Not applicable to Java, as the {@link BlockChunker} that it uses does not record start and end units of each block.
+ * Also, it uses statements instead of tokens.
*/
int getMinimumTokens(String languageKey) {
return settings.getInt("sonar.cpd." + languageKey + ".minimumTokens").orElse(100);
import org.sonar.api.batch.Phase;
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.SensorDescriptor;
import org.sonar.api.scanner.sensor.ProjectSensor;
import org.sonar.duplications.statement.StatementChunker;
import org.sonar.duplications.token.TokenChunker;
import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
+import org.sonar.scanner.fs.DefaultInputFile;
/**
* Special case for Java that use a dedicated block indexer.
import java.util.Iterator;
import java.util.Set;
import java.util.stream.Collectors;
-
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.index.PackedMemoryCloneIndex;
import org.sonar.duplications.index.PackedMemoryCloneIndex.ResourceBlocks;
import org.sonar.scanner.cpd.CpdSettings;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.protocol.output.FileStructure;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.report.ReportPublisher;
package org.sonar.scanner.deprecated.test;
import java.util.List;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.test.CoverageBlock;
import org.sonar.api.test.TestCase;
import org.sonar.api.test.Testable;
+import org.sonar.scanner.fs.DefaultInputFile;
public class DefaultCoverageBlock implements CoverageBlock {
import javax.annotation.Nullable;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.test.CoverageBlock;
import org.sonar.api.test.MutableTestCase;
import org.sonar.api.test.TestPlan;
import org.sonar.api.test.Testable;
import org.sonar.api.test.exception.CoverageAlreadyExistsException;
import org.sonar.api.test.exception.IllegalDurationException;
+import org.sonar.scanner.fs.DefaultInputFile;
public class DefaultTestCase implements MutableTestCase {
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.test.CoverageBlock;
import org.sonar.api.test.MutableTestable;
import org.sonar.api.test.TestCase;
+import org.sonar.scanner.fs.DefaultInputFile;
public class DefaultTestable implements MutableTestable {
import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.test.MutableTestPlan;
import org.sonar.scanner.deprecated.perspectives.PerspectiveBuilder;
+import org.sonar.scanner.fs.DefaultInputFile;
public class TestPlanBuilder extends PerspectiveBuilder<MutableTestPlan> {
import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.test.MutableTestable;
import org.sonar.scanner.deprecated.perspectives.PerspectiveBuilder;
+import org.sonar.scanner.fs.DefaultInputFile;
public class TestableBuilder extends PerspectiveBuilder<MutableTestable> {
import org.apache.commons.lang.SystemUtils;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.internal.DefaultInputComponent;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputDir;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputDir;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.api.utils.PathUtils;
import org.sonar.scanner.fs.predicates.DefaultFilePredicates;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.fs;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.batch.fs.IndexedFile;
+import org.sonar.api.batch.fs.InputFile.Type;
+import org.sonar.api.batch.fs.internal.SensorStrategy;
+import org.sonar.api.utils.PathUtils;
+
+/**
+ * @since 6.3
+ */
+@Immutable
+public class DefaultIndexedFile extends DefaultInputComponent implements IndexedFile {
+ private static AtomicInteger intGenerator = new AtomicInteger(0);
+
+ private final String projectRelativePath;
+ private final String moduleRelativePath;
+ private final String projectKey;
+ private final String language;
+ private final Type type;
+ private final Path absolutePath;
+ private final SensorStrategy sensorStrategy;
+
+ /**
+ * Testing purposes only!
+ */
+ public DefaultIndexedFile(String projectKey, Path baseDir, String relativePath, @Nullable String language) {
+ this(baseDir.resolve(relativePath), projectKey, relativePath, relativePath, Type.MAIN, language, intGenerator.getAndIncrement(),
+ new SensorStrategy());
+ }
+
+ public DefaultIndexedFile(Path absolutePath, String projectKey, String projectRelativePath, String moduleRelativePath, Type type, @Nullable String language, int batchId,
+ SensorStrategy sensorStrategy) {
+ super(batchId);
+ this.projectKey = projectKey;
+ this.projectRelativePath = PathUtils.sanitize(projectRelativePath);
+ this.moduleRelativePath = PathUtils.sanitize(moduleRelativePath);
+ this.type = type;
+ this.language = language;
+ this.sensorStrategy = sensorStrategy;
+ this.absolutePath = absolutePath;
+ }
+
+ @Override
+ public String relativePath() {
+ return sensorStrategy.isGlobal() ? projectRelativePath : moduleRelativePath;
+ }
+
+ public String getModuleRelativePath() {
+ return moduleRelativePath;
+ }
+
+ public String getProjectRelativePath() {
+ return projectRelativePath;
+ }
+
+ @Override
+ public String absolutePath() {
+ return PathUtils.sanitize(path().toString());
+ }
+
+ @Override
+ public File file() {
+ return path().toFile();
+ }
+
+ @Override
+ public Path path() {
+ return absolutePath;
+ }
+
+ @Override
+ public InputStream inputStream() throws IOException {
+ return Files.newInputStream(path());
+ }
+
+ @CheckForNull
+ @Override
+ public String language() {
+ return language;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Component key (without branch).
+ */
+ @Override
+ public String key() {
+ return new StringBuilder().append(projectKey).append(":").append(projectRelativePath).toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof DefaultIndexedFile)) {
+ return false;
+ }
+
+ DefaultIndexedFile that = (DefaultIndexedFile) o;
+ return projectRelativePath.equals(that.projectRelativePath);
+ }
+
+ @Override
+ public int hashCode() {
+ return projectRelativePath.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return projectRelativePath;
+ }
+
+ @Override
+ public boolean isFile() {
+ return true;
+ }
+
+ @Override
+ public String filename() {
+ return path().getFileName().toString();
+ }
+
+ @Override
+ public URI uri() {
+ return path().toUri();
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.fs;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.measure.Metric;
+
+/**
+ * @since 5.2
+ */
+public abstract class DefaultInputComponent implements InputComponent {
+ private int id;
+ private Set<String> storedMetricKeys = new HashSet<>();
+
+ public DefaultInputComponent(int scannerId) {
+ this.id = scannerId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || this.getClass() != o.getClass()) {
+ return false;
+ }
+
+ DefaultInputComponent that = (DefaultInputComponent) o;
+ return key().equals(that.key());
+ }
+
+ public int scannerId() {
+ return id;
+ }
+
+ @Override
+ public int hashCode() {
+ return key().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "[key=" + key() + "]";
+ }
+
+ public void setHasMeasureFor(Metric metric) {
+ storedMetricKeys.add(metric.key());
+ }
+
+ public boolean hasMeasureFor(Metric metric) {
+ return storedMetricKeys.contains(metric.key());
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.fs;
+
+import java.io.File;
+import java.net.URI;
+import java.nio.file.Path;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.batch.fs.InputDir;
+import org.sonar.api.utils.PathUtils;
+
+/**
+ * @since 4.5
+ */
+public class DefaultInputDir extends DefaultInputComponent implements InputDir {
+
+ private final String relativePath;
+ private final String moduleKey;
+ private Path moduleBaseDir;
+
+ public DefaultInputDir(String moduleKey, String relativePath) {
+ super(-1);
+ this.moduleKey = moduleKey;
+ this.relativePath = PathUtils.sanitize(relativePath);
+ }
+
+ @Override
+ public String relativePath() {
+ return relativePath;
+ }
+
+ @Override
+ public String absolutePath() {
+ return PathUtils.sanitize(path().toString());
+ }
+
+ @Override
+ public File file() {
+ return path().toFile();
+ }
+
+ @Override
+ public Path path() {
+ if (moduleBaseDir == null) {
+ throw new IllegalStateException("Can not return the java.nio.file.Path because module baseDir is not set (see method setModuleBaseDir(java.io.File))");
+ }
+ return moduleBaseDir.resolve(relativePath);
+ }
+
+ public String moduleKey() {
+ return moduleKey;
+ }
+
+ @Override
+ public String key() {
+ StringBuilder sb = new StringBuilder().append(moduleKey).append(":");
+ if (StringUtils.isEmpty(relativePath)) {
+ sb.append("/");
+ } else {
+ sb.append(relativePath);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * For testing purpose. Will be automatically set when dir is added to {@link DefaultFileSystem}
+ */
+ public DefaultInputDir setModuleBaseDir(Path moduleBaseDir) {
+ this.moduleBaseDir = moduleBaseDir.normalize();
+ return this;
+ }
+
+ @Override
+ public boolean isFile() {
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || this.getClass() != o.getClass()) {
+ return false;
+ }
+
+ DefaultInputDir that = (DefaultInputDir) o;
+ return moduleKey.equals(that.moduleKey) && relativePath.equals(that.relativePath);
+ }
+
+ @Override
+ public int hashCode() {
+ return moduleKey.hashCode() + relativePath.hashCode() * 13;
+ }
+
+ @Override
+ public String toString() {
+ return "[moduleKey=" + moduleKey + ", relative=" + relativePath + ", basedir=" + moduleBaseDir + "]";
+ }
+
+ @Override
+ public URI uri() {
+ return path().toUri();
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.fs;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.io.ByteOrderMark;
+import org.apache.commons.io.input.BOMInputStream;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextPointer;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.fs.internal.Metadata;
+
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+/**
+ * @since 4.2
+ * To create {@link InputFile} in tests, use TestInputFileBuilder.
+ */
+public class DefaultInputFile extends DefaultInputComponent implements InputFile {
+
+ private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+
+ private final DefaultIndexedFile indexedFile;
+ private final String contents;
+ private final Consumer<DefaultInputFile> metadataGenerator;
+
+ private boolean published;
+ private boolean excludedForCoverage;
+ private boolean excludedForDuplication;
+ private boolean ignoreAllIssues;
+ // Lazy init to save memory
+ private BitSet noSonarLines;
+ private Status status;
+ private Charset charset;
+ private Metadata metadata;
+ private Collection<int[]> ignoreIssuesOnlineRanges;
+ private BitSet executableLines;
+
+ public DefaultInputFile(DefaultIndexedFile indexedFile, Consumer<DefaultInputFile> metadataGenerator) {
+ this(indexedFile, metadataGenerator, null);
+ }
+
+ // For testing
+ public DefaultInputFile(DefaultIndexedFile indexedFile, Consumer<DefaultInputFile> metadataGenerator, @Nullable String contents) {
+ super(indexedFile.scannerId());
+ this.indexedFile = indexedFile;
+ this.metadataGenerator = metadataGenerator;
+ this.metadata = null;
+ this.published = false;
+ this.excludedForCoverage = false;
+ this.contents = contents;
+ }
+
+ public void checkMetadata() {
+ if (metadata == null) {
+ metadataGenerator.accept(this);
+ }
+ }
+
+ @Override
+ public InputStream inputStream() throws IOException {
+ return contents != null ? new ByteArrayInputStream(contents.getBytes(charset()))
+ : new BOMInputStream(Files.newInputStream(path()),
+ ByteOrderMark.UTF_8, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE);
+ }
+
+ @Override
+ public String contents() throws IOException {
+ if (contents != null) {
+ return contents;
+ } else {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ try (InputStream inputStream = inputStream()) {
+ byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+ int length;
+ while ((length = inputStream.read(buffer)) != -1) {
+ result.write(buffer, 0, length);
+ }
+ }
+ return result.toString(charset().name());
+ }
+ }
+
+ public DefaultInputFile setPublished(boolean published) {
+ this.published = published;
+ return this;
+ }
+
+ public boolean isPublished() {
+ return published;
+ }
+
+ public DefaultInputFile setExcludedForCoverage(boolean excludedForCoverage) {
+ this.excludedForCoverage = excludedForCoverage;
+ return this;
+ }
+
+ public boolean isExcludedForCoverage() {
+ return excludedForCoverage;
+ }
+
+ public DefaultInputFile setExcludedForDuplication(boolean excludedForDuplication) {
+ this.excludedForDuplication = excludedForDuplication;
+ return this;
+ }
+
+ public boolean isExcludedForDuplication() {
+ return excludedForDuplication;
+ }
+
+ /**
+ * @deprecated since 6.6
+ */
+ @Deprecated
+ @Override
+ public String relativePath() {
+ return indexedFile.relativePath();
+ }
+
+ public String getModuleRelativePath() {
+ return indexedFile.getModuleRelativePath();
+ }
+
+ public String getProjectRelativePath() {
+ return indexedFile.getProjectRelativePath();
+ }
+
+ @Override
+ public String absolutePath() {
+ return indexedFile.absolutePath();
+ }
+
+ @Override
+ public File file() {
+ return indexedFile.file();
+ }
+
+ @Override
+ public Path path() {
+ return indexedFile.path();
+ }
+
+ @CheckForNull
+ @Override
+ public String language() {
+ return indexedFile.language();
+ }
+
+ @Override
+ public Type type() {
+ return indexedFile.type();
+ }
+
+ /**
+ * Component key (without branch).
+ */
+ @Override
+ public String key() {
+ return indexedFile.key();
+ }
+
+ @Override
+ public int hashCode() {
+ return indexedFile.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return indexedFile.toString();
+ }
+
+ /**
+ * {@link #setStatus(Status)}
+ */
+ @Override
+ public Status status() {
+ checkMetadata();
+ return status;
+ }
+
+ @Override
+ public int lines() {
+ checkMetadata();
+ return metadata.lines();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ checkMetadata();
+ return metadata.isEmpty();
+ }
+
+ @Override
+ public Charset charset() {
+ checkMetadata();
+ return charset;
+ }
+
+ public int lastValidOffset() {
+ checkMetadata();
+ return metadata.lastValidOffset();
+ }
+
+ /**
+ * Digest hash of the file.
+ */
+ public String hash() {
+ checkMetadata();
+ return metadata.hash();
+ }
+
+ public int nonBlankLines() {
+ checkMetadata();
+ return metadata.nonBlankLines();
+ }
+
+ public int[] originalLineStartOffsets() {
+ checkMetadata();
+ checkState(metadata.originalLineStartOffsets() != null, "InputFile is not properly initialized.");
+ checkState(metadata.originalLineStartOffsets().length == metadata.lines(),
+ "InputFile is not properly initialized. 'originalLineStartOffsets' property length should be equal to 'lines'");
+ return metadata.originalLineStartOffsets();
+ }
+
+ public int[] originalLineEndOffsets() {
+ checkMetadata();
+ checkState(metadata.originalLineEndOffsets() != null, "InputFile is not properly initialized.");
+ checkState(metadata.originalLineEndOffsets().length == metadata.lines(),
+ "InputFile is not properly initialized. 'originalLineEndOffsets' property length should be equal to 'lines'");
+ return metadata.originalLineEndOffsets();
+ }
+
+ @Override
+ public TextPointer newPointer(int line, int lineOffset) {
+ checkMetadata();
+ DefaultTextPointer textPointer = new DefaultTextPointer(line, lineOffset);
+ checkValid(textPointer, "pointer");
+ return textPointer;
+ }
+
+ @Override
+ public TextRange newRange(TextPointer start, TextPointer end) {
+ checkMetadata();
+ checkValid(start, "start pointer");
+ checkValid(end, "end pointer");
+ return newRangeValidPointers(start, end, false);
+ }
+
+ @Override
+ public TextRange newRange(int startLine, int startLineOffset, int endLine, int endLineOffset) {
+ checkMetadata();
+ TextPointer start = newPointer(startLine, startLineOffset);
+ TextPointer end = newPointer(endLine, endLineOffset);
+ return newRangeValidPointers(start, end, false);
+ }
+
+ @Override
+ public TextRange selectLine(int line) {
+ checkMetadata();
+ TextPointer startPointer = newPointer(line, 0);
+ TextPointer endPointer = newPointer(line, lineLength(line));
+ return newRangeValidPointers(startPointer, endPointer, true);
+ }
+
+ public void validate(TextRange range) {
+ checkMetadata();
+ checkValid(range.start(), "start pointer");
+ checkValid(range.end(), "end pointer");
+ }
+
+ /**
+ * Create Range from global offsets. Used for backward compatibility with older API.
+ */
+ public TextRange newRange(int startOffset, int endOffset) {
+ checkMetadata();
+ return newRangeValidPointers(newPointer(startOffset), newPointer(endOffset), false);
+ }
+
+ public TextPointer newPointer(int globalOffset) {
+ checkMetadata();
+ checkArgument(globalOffset >= 0, "%s is not a valid offset for a file", globalOffset);
+ checkArgument(globalOffset <= lastValidOffset(), "%s is not a valid offset for file %s. Max offset is %s", globalOffset, this, lastValidOffset());
+ int line = findLine(globalOffset);
+ int startLineOffset = originalLineStartOffsets()[line - 1];
+ // In case the global offset is between \r and \n, move the pointer to a valid location
+ return new DefaultTextPointer(line, Math.min(globalOffset, originalLineEndOffsets()[line - 1]) - startLineOffset);
+ }
+
+ public DefaultInputFile setStatus(Status status) {
+ this.status = status;
+ return this;
+ }
+
+ public DefaultInputFile setCharset(Charset charset) {
+ this.charset = charset;
+ return this;
+ }
+
+ private void checkValid(TextPointer pointer, String owner) {
+ checkArgument(pointer.line() >= 1, "%s is not a valid line for a file", pointer.line());
+ checkArgument(pointer.line() <= this.metadata.lines(), "%s is not a valid line for %s. File %s has %s line(s)", pointer.line(), owner, this, metadata.lines());
+ checkArgument(pointer.lineOffset() >= 0, "%s is not a valid line offset for a file", pointer.lineOffset());
+ int lineLength = lineLength(pointer.line());
+ checkArgument(pointer.lineOffset() <= lineLength,
+ "%s is not a valid line offset for %s. File %s has %s character(s) at line %s", pointer.lineOffset(), owner, this, lineLength, pointer.line());
+ }
+
+ private int lineLength(int line) {
+ return originalLineEndOffsets()[line - 1] - originalLineStartOffsets()[line - 1];
+ }
+
+ private static TextRange newRangeValidPointers(TextPointer start, TextPointer end, boolean acceptEmptyRange) {
+ checkArgument(acceptEmptyRange ? (start.compareTo(end) <= 0) : (start.compareTo(end) < 0),
+ "Start pointer %s should be before end pointer %s", start, end);
+ return new DefaultTextRange(start, end);
+ }
+
+ private int findLine(int globalOffset) {
+ return Math.abs(Arrays.binarySearch(originalLineStartOffsets(), globalOffset) + 1);
+ }
+
+ public DefaultInputFile setMetadata(Metadata metadata) {
+ this.metadata = metadata;
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+
+ if (this.getClass() != obj.getClass()) {
+ return false;
+ }
+
+ DefaultInputFile that = (DefaultInputFile) obj;
+ return this.getProjectRelativePath().equals(that.getProjectRelativePath());
+ }
+
+ @Override
+ public boolean isFile() {
+ return true;
+ }
+
+ @Override
+ public String filename() {
+ return indexedFile.filename();
+ }
+
+ @Override
+ public URI uri() {
+ return indexedFile.uri();
+ }
+
+ public void noSonarAt(Set<Integer> noSonarLines) {
+ if (this.noSonarLines == null) {
+ this.noSonarLines = new BitSet(lines());
+ }
+ noSonarLines.forEach(l -> this.noSonarLines.set(l - 1));
+ }
+
+ public boolean hasNoSonarAt(int line) {
+ if (this.noSonarLines == null) {
+ return false;
+ }
+ return this.noSonarLines.get(line - 1);
+ }
+
+ public boolean isIgnoreAllIssues() {
+ return ignoreAllIssues;
+ }
+
+ public void setIgnoreAllIssues(boolean ignoreAllIssues) {
+ this.ignoreAllIssues = ignoreAllIssues;
+ }
+
+ public void addIgnoreIssuesOnLineRanges(Collection<int[]> lineRanges) {
+ if (this.ignoreIssuesOnlineRanges == null) {
+ this.ignoreIssuesOnlineRanges = new ArrayList<>();
+ }
+ this.ignoreIssuesOnlineRanges.addAll(lineRanges);
+ }
+
+ public boolean isIgnoreAllIssuesOnLine(@Nullable Integer line) {
+ if (line == null || ignoreIssuesOnlineRanges == null) {
+ return false;
+ }
+ return ignoreIssuesOnlineRanges.stream().anyMatch(r -> r[0] <= line && line <= r[1]);
+ }
+
+ public void setExecutableLines(Set<Integer> executableLines) {
+ checkState(this.executableLines == null, "Executable lines have already been saved for file: {}", this.toString());
+ this.executableLines = new BitSet(lines());
+ executableLines.forEach(l -> this.executableLines.set(l - 1));
+ }
+
+ public Optional<Set<Integer>> getExecutableLines() {
+ if (this.executableLines == null) {
+ return Optional.empty();
+ }
+ return Optional.of(this.executableLines.stream().map(i -> i + 1).boxed().collect(Collectors.toSet()));
+ }
+}
import javax.annotation.Nullable;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
-import org.sonar.api.batch.fs.internal.DefaultIndexedFile;
-import org.sonar.api.batch.fs.internal.DefaultInputDir;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.fs.internal.Metadata;
import org.sonar.api.batch.fs.internal.SensorStrategy;
import org.sonar.api.utils.PathUtils;
return setMetadata(new FileMetadata().readMetadata(new StringReader(content)));
}
- public org.sonar.api.batch.fs.internal.DefaultInputFile build() {
+ public DefaultInputFile build() {
Path absolutePath = moduleBaseDir.resolve(relativePath);
if (projectBaseDir == null) {
projectBaseDir = moduleBaseDir;
}
String projectRelativePath = projectBaseDir.relativize(absolutePath).toString();
- org.sonar.api.batch.fs.internal.DefaultIndexedFile indexedFile = new DefaultIndexedFile(absolutePath, projectKey, projectRelativePath, relativePath, type, language, id, new SensorStrategy());
- org.sonar.api.batch.fs.internal.DefaultInputFile inputFile = new org.sonar.api.batch.fs.internal.DefaultInputFile(indexedFile,
+ DefaultIndexedFile indexedFile = new DefaultIndexedFile(absolutePath, projectKey, projectRelativePath, relativePath, type, language, id, new SensorStrategy());
+ DefaultInputFile inputFile = new DefaultInputFile(indexedFile,
f -> f.setMetadata(new Metadata(lines, nonBlankLines, hash, originalLineStartOffsets, originalLineEndOffsets, lastValidOffset)),
contents);
inputFile.setStatus(status);
return inputFile;
}
- public static org.sonar.api.batch.fs.internal.DefaultInputModule newDefaultInputModule(String moduleKey, File baseDir) {
+ public static DefaultInputModule newDefaultInputModule(String moduleKey, File baseDir) {
ProjectDefinition definition = ProjectDefinition.create()
.setKey(moduleKey)
.setBaseDir(baseDir)
return newDefaultInputModule(definition);
}
- public static org.sonar.api.batch.fs.internal.DefaultInputModule newDefaultInputModule(ProjectDefinition projectDefinition) {
- return new org.sonar.api.batch.fs.internal.DefaultInputModule(projectDefinition, TestInputFileBuilder.nextBatchId());
+ public static DefaultInputModule newDefaultInputModule(ProjectDefinition projectDefinition) {
+ return new DefaultInputModule(projectDefinition, TestInputFileBuilder.nextBatchId());
}
- public static DefaultInputModule newDefaultInputModule(org.sonar.api.batch.fs.internal.AbstractProjectOrModule parent, String key) throws IOException {
+ public static DefaultInputModule newDefaultInputModule(AbstractProjectOrModule parent, String key) throws IOException {
Path basedir = parent.getBaseDir().resolve(key);
Files.createDirectory(basedir);
return newDefaultInputModule(key, basedir.toFile());
}
- public static org.sonar.api.batch.fs.internal.DefaultInputProject newDefaultInputProject(String projectKey, File baseDir) {
+ public static DefaultInputProject newDefaultInputProject(String projectKey, File baseDir) {
ProjectDefinition definition = ProjectDefinition.create()
.setKey(projectKey)
.setBaseDir(baseDir)
return newDefaultInputProject(definition);
}
- public static org.sonar.api.batch.fs.internal.DefaultInputProject newDefaultInputProject(ProjectDefinition projectDefinition) {
- return new org.sonar.api.batch.fs.internal.DefaultInputProject(projectDefinition, TestInputFileBuilder.nextBatchId());
+ public static DefaultInputProject newDefaultInputProject(ProjectDefinition projectDefinition) {
+ return new DefaultInputProject(projectDefinition, TestInputFileBuilder.nextBatchId());
}
public static DefaultInputProject newDefaultInputProject(String key, Path baseDir) throws IOException {
return newDefaultInputProject(key, baseDir.toFile());
}
- public static org.sonar.api.batch.fs.internal.DefaultInputDir newDefaultInputDir(org.sonar.api.batch.fs.internal.AbstractProjectOrModule module, String relativePath) throws IOException {
+ public static DefaultInputDir newDefaultInputDir(AbstractProjectOrModule module, String relativePath) throws IOException {
Path basedir = module.getBaseDir().resolve(relativePath);
Files.createDirectory(basedir);
return new DefaultInputDir(module.key(), relativePath)
import java.util.Optional;
import javax.annotation.Nullable;
import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputDir;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
-import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.scanner.sensor.DefaultStorable;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.issue.Issue.Flow;
import org.sonar.api.batch.sensor.issue.IssueLocation;
import org.sonar.api.batch.sensor.issue.NewIssueLocation;
import org.sonar.api.utils.PathUtils;
+import org.sonar.scanner.fs.DefaultInputDir;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.DefaultInputProject;
import static java.util.Collections.unmodifiableList;
import static java.util.stream.Collectors.toList;
import org.apache.commons.lang.builder.ToStringStyle;
import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
-import org.sonar.api.batch.fs.internal.DefaultTextPointer;
-import org.sonar.api.batch.fs.internal.DefaultTextRange;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.scan.issue.filter.FilterableIssue;
import org.sonar.scanner.ProjectInfo;
+import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.scanner.fs.DefaultTextPointer;
+import org.sonar.scanner.fs.DefaultTextRange;
import org.sonar.scanner.protocol.output.ScannerReport.Issue;
@ThreadSafe
package org.sonar.scanner.issue;
import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.batch.sensor.issue.IssueLocation;
import org.sonar.api.batch.sensor.issue.NewIssue;
import org.sonar.api.rule.RuleKey;
+import org.sonar.scanner.fs.DefaultInputProject;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nullable;
import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.issue.IssueLocation;
import org.sonar.api.batch.sensor.issue.NewIssueLocation;
+import org.sonar.scanner.fs.DefaultInputFile;
import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang.StringUtils.abbreviate;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.issue;
+
+import java.util.Set;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.issue.NoSonarFilter;
+import org.sonar.scanner.fs.DefaultInputFile;
+
+public class DefaultNoSonarFilter extends NoSonarFilter {
+ public NoSonarFilter noSonarInFile(InputFile inputFile, Set<Integer> noSonarLines) {
+ ((DefaultInputFile) inputFile).noSonarAt(noSonarLines);
+ return this;
+ }
+}
package org.sonar.scanner.issue;
import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.scan.issue.filter.FilterableIssue;
import org.sonar.api.scan.issue.filter.IssueFilter;
import org.sonar.api.scan.issue.filter.IssueFilterChain;
import org.sonar.scanner.ProjectInfo;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.protocol.output.ScannerReport;
/**
import javax.annotation.concurrent.ThreadSafe;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.fs.internal.DefaultInputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.rule.ActiveRule;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.sensor.issue.ExternalIssue;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.batch.sensor.issue.Issue.Flow;
+import org.sonar.scanner.fs.DefaultInputComponent;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.protocol.Constants.Severity;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReport.IssueLocation;
import java.util.List;
import javax.annotation.concurrent.ThreadSafe;
import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.api.scan.issue.filter.FilterableIssue;
import org.sonar.api.scan.issue.filter.IssueFilter;
import org.sonar.api.scan.issue.filter.IssueFilterChain;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.issue.DefaultFilterableIssue;
import org.sonar.scanner.issue.ignore.pattern.IssueInclusionPatternInitializer;
import org.sonar.scanner.issue.ignore.pattern.IssuePattern;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.scan.issue.filter.FilterableIssue;
import org.sonar.api.scan.issue.filter.IssueFilter;
import org.sonar.api.scan.issue.filter.IssueFilterChain;
import org.sonar.api.utils.WildcardPattern;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.issue.DefaultFilterableIssue;
public class IgnoreIssuesFilter implements IssueFilter {
import java.util.List;
import javax.annotation.CheckForNull;
import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.charhandler.CharHandler;
import org.sonar.scanner.issue.ignore.IgnoreIssuesFilter;
import org.sonar.scanner.issue.ignore.pattern.BlockIssuePattern;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.charhandler.CharHandler;
import org.sonar.scanner.issue.ignore.pattern.LineRange;
import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader.DoubleRegexpMatcher;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.TextPointer;
import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.fs.internal.DefaultInputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.highlighting.TypeOfText;
import org.sonar.api.scanner.fs.InputProject;
import org.sonar.core.util.CloseableIterator;
+import org.sonar.scanner.fs.DefaultInputComponent;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReport.Component;
import org.sonar.scanner.protocol.output.ScannerReport.Symbol;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.scm.ScmProvider;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFile.Status;
-import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.scanner.fs.AbstractProjectOrModule;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType;
import org.sonar.scanner.protocol.output.ScannerReport.Component.FileStatus;
private final InputComponentStore inputComponentStore;
private final DefaultInputProject project;
-
public ComponentsPublisher(DefaultInputProject project, InputComponentStore inputComponentStore) {
this.project = project;
this.inputComponentStore = inputComponentStore;
}
private static void writeProjectLink(ScannerReport.Component.Builder componentBuilder, Map<String, String> properties, ComponentLink.Builder linkBuilder, String linkProp,
- ComponentLinkType linkType) {
+ ComponentLinkType linkType) {
String link = properties.get(linkProp);
if (StringUtils.isNotBlank(link)) {
linkBuilder.setType(linkType);
import java.util.Map.Entry;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.batch.scm.ScmProvider;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.scanner.bootstrap.ScannerPlugin;
import org.sonar.scanner.bootstrap.ScannerPluginRepository;
import org.sonar.scanner.cpd.CpdSettings;
+import org.sonar.scanner.fs.AbstractProjectOrModule;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.InputModuleHierarchy;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReport.Metadata.BranchType;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
import okhttp3.HttpUrl;
import org.apache.commons.io.FileUtils;
import org.picocontainer.Startable;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.platform.Server;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.TempFolder;
import org.sonar.api.utils.log.Loggers;
import org.sonar.scanner.bootstrap.GlobalAnalysisMode;
import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.fs.InputModuleHierarchy;
import org.sonar.scanner.protocol.output.ScannerReportReader;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
import org.sonar.scanner.scan.ScanProperties;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
-
import org.apache.commons.io.IOUtils;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
import org.sonar.scanner.scan.filesystem.InputComponentStore;
import java.util.stream.StreamSupport;
import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.scanner.sensor.DefaultMeasure;
import org.sonar.api.test.MutableTestPlan;
import org.sonar.api.test.TestCase;
import org.sonar.api.test.TestCase.Status;
import org.sonar.scanner.deprecated.test.TestPlanBuilder;
+import org.sonar.scanner.fs.DefaultInputComponent;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
import org.sonar.scanner.scan.filesystem.InputComponentStore;
+import org.sonar.scanner.sensor.DefaultMeasure;
import static org.sonar.api.measures.CoreMetrics.SKIPPED_TESTS;
import static org.sonar.api.measures.CoreMetrics.TESTS;
import javax.annotation.CheckForNull;
import javax.annotation.concurrent.Immutable;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputFile;
@Immutable
public abstract class ProjectRepositories {
import java.util.Map;
import javax.annotation.CheckForNull;
import javax.annotation.concurrent.Immutable;
-import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.scan.filesystem.PathResolver;
+import org.sonar.scanner.fs.AbstractProjectOrModule;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.InputModuleHierarchy;
@Immutable
public class DefaultInputModuleHierarchy implements InputModuleHierarchy {
import java.util.Map;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.scan.filesystem.ScannerComponentIdGenerator;
public class InputModuleHierarchyProvider extends ProviderAdapter {
}
private static Map<DefaultInputModule, DefaultInputModule> createChildren(DefaultInputModule parent, ScannerComponentIdGenerator scannerComponentIdGenerator,
- Map<DefaultInputModule, DefaultInputModule> parents) {
+ Map<DefaultInputModule, DefaultInputModule> parents) {
for (ProjectDefinition def : parent.definition().getSubProjects()) {
DefaultInputModule child = createModule(def, scannerComponentIdGenerator.getAsInt());
parents.put(child, parent);
import java.util.Locale;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.bootstrap.ProjectReactor;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.scan.filesystem.ScannerComponentIdGenerator;
public class InputProjectProvider extends ProviderAdapter {
- private static final Logger LOG = Loggers.get(DefaultInputModule.class);
+ private static final Logger LOG = Loggers.get(InputProjectProvider.class);
private DefaultInputProject project = null;
import java.util.Map;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.scanner.bootstrap.GlobalConfiguration;
import org.sonar.scanner.bootstrap.GlobalServerSettings;
+import org.sonar.scanner.fs.DefaultInputModule;
public class ModuleConfigurationProvider extends ProviderAdapter {
package org.sonar.scanner.scan;
import org.picocontainer.Startable;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.InputModuleHierarchy;
import org.sonar.scanner.scan.filesystem.InputComponentStore;
/**
*/
package org.sonar.scanner.scan;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.scan.filesystem.FileExclusions;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.scanner.bootstrap.ExtensionInstaller;
import org.sonar.scanner.deprecated.perspectives.ScannerPerspectives;
+import org.sonar.scanner.fs.DefaultInputModule;
import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem;
import org.sonar.scanner.scan.filesystem.ModuleInputComponentStore;
import org.sonar.scanner.sensor.ModuleSensorContext;
import java.util.LinkedHashMap;
import java.util.Map;
import org.picocontainer.injectors.ProviderAdapter;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.scanner.bootstrap.GlobalConfiguration;
import org.sonar.scanner.bootstrap.GlobalServerSettings;
+import org.sonar.scanner.fs.DefaultInputProject;
public class ProjectConfigurationProvider extends ProviderAdapter {
import java.nio.file.Files;
import java.nio.file.Path;
import org.picocontainer.Startable;
-import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
+import org.sonar.scanner.fs.AbstractProjectOrModule;
public class ProjectLock implements Startable {
private final DirectoryLock lock;
import javax.annotation.Nullable;
import org.sonar.api.SonarEdition;
import org.sonar.api.SonarRuntime;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.batch.fs.internal.SensorStrategy;
import org.sonar.api.batch.rule.CheckFactory;
-import org.sonar.api.issue.NoSonarFilter;
import org.sonar.api.resources.Languages;
import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
import org.sonar.scanner.deprecated.test.TestPlanBuilder;
import org.sonar.scanner.deprecated.test.TestableBuilder;
+import org.sonar.scanner.fs.DefaultInputModule;
import org.sonar.scanner.fs.FileMetadata;
+import org.sonar.scanner.fs.InputModuleHierarchy;
+import org.sonar.scanner.issue.DefaultNoSonarFilter;
import org.sonar.scanner.issue.IssueFilters;
import org.sonar.scanner.issue.IssuePublisher;
import org.sonar.scanner.issue.ignore.EnforceIssuesFilter;
QProfileVerifier.class,
// issues
- NoSonarFilter.class,
+ DefaultNoSonarFilter.class,
IssueFilters.class,
IssuePublisher.class,
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.config.Configuration;
import org.sonar.api.utils.MessageException;
+import org.sonar.scanner.fs.DefaultInputProject;
import static org.sonar.core.config.ScannerProperties.BRANCH_NAME;
import static org.sonar.core.config.ScannerProperties.ORGANIZATION;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.core.util.FileUtils;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.InputModuleHierarchy;
/**
* Clean and create working directories of each module.
import java.util.stream.Stream;
import javax.annotation.concurrent.Immutable;
import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.utils.WildcardPattern;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.fs.DefaultInputFile;
import static java.util.stream.Collectors.toList;
package org.sonar.scanner.scan.filesystem;
import com.google.common.annotations.VisibleForTesting;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.scanner.fs.DefaultFileSystem;
+import org.sonar.scanner.fs.DefaultInputModule;
public class DefaultModuleFileSystem extends DefaultFileSystem {
package org.sonar.scanner.scan.filesystem;
import com.google.common.annotations.VisibleForTesting;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.scanner.fs.DefaultFileSystem;
+import org.sonar.scanner.fs.DefaultInputProject;
public class DefaultProjectFileSystem extends DefaultFileSystem {
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFile.Type;
import org.sonar.api.batch.fs.InputFileFilter;
-import org.sonar.api.batch.fs.internal.DefaultIndexedFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.fs.internal.SensorStrategy;
import org.sonar.api.batch.scm.IgnoreCommand;
import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.fs.DefaultIndexedFile;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader;
import org.sonar.scanner.scan.ScanProperties;
import org.sonar.scanner.util.ProgressReport;
import javax.annotation.CheckForNull;
import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.scanner.fs.DefaultFileSystem;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputModule;
import org.sonar.scanner.fs.predicates.FileExtensionPredicate;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import java.io.InputStream;
import java.nio.charset.Charset;
import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.Metadata;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.FileMetadata;
import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader;
package org.sonar.scanner.scan.filesystem;
import javax.annotation.concurrent.Immutable;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.scan.ModuleConfiguration;
@Immutable
package org.sonar.scanner.scan.filesystem;
import javax.annotation.concurrent.Immutable;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.scan.ProjectConfiguration;
@Immutable
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.batch.scm.IgnoreCommand;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.scanner.bootstrap.GlobalConfiguration;
import org.sonar.scanner.bootstrap.GlobalServerSettings;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.InputModuleHierarchy;
import org.sonar.scanner.scan.ModuleConfiguration;
import org.sonar.scanner.scan.ModuleConfigurationProvider;
import org.sonar.scanner.scan.ProjectServerSettings;
private static void logPaths(String label, Path baseDir, List<Path> paths) {
if (!paths.isEmpty()) {
StringBuilder sb = new StringBuilder(label);
- for (Iterator<Path> it = paths.iterator(); it.hasNext();) {
+ for (Iterator<Path> it = paths.iterator(); it.hasNext(); ) {
Path file = it.next();
Optional<String> relativePathToBaseDir = PathResolver.relativize(baseDir, file);
if (!relativePathToBaseDir.isPresent()) {
import javax.annotation.concurrent.Immutable;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.repository.FileData;
import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
import org.sonar.scanner.scm.ScmChangedFiles;
import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.scm.BlameCommand.BlameOutput;
import org.sonar.api.batch.scm.BlameLine;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReport.Changesets.Builder;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
import java.util.Collection;
import javax.annotation.CheckForNull;
import org.picocontainer.injectors.ProviderAdapter;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.scm.ScmProvider;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.scanner.util.ScannerUtils;
import org.sonar.api.Property;
import org.sonar.api.PropertyType;
import org.sonar.api.batch.AnalysisMode;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.batch.scm.ScmProvider;
import org.sonar.api.config.Configuration;
import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.config.ScannerProperties;
+import org.sonar.scanner.fs.InputModuleHierarchy;
import static org.sonar.api.CoreProperties.SCM_PROVIDER_KEY;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFile.Status;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.scm.ScmProvider;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReport.Changesets.Builder;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
package org.sonar.scanner.scm;
import java.util.Optional;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.batch.scm.ScmProvider;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.scanner.bootstrap.RawScannerProperties;
import org.sonar.scanner.ci.CiConfiguration;
+import org.sonar.scanner.fs.InputModuleHierarchy;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.sonar.scanner.scan.ScanProperties.SCM_REVISION;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.scanner.sensor;
-
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputDir;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
-import org.sonar.api.batch.sensor.internal.DefaultStorable;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.issue.Issue.Flow;
-import org.sonar.api.batch.sensor.issue.IssueLocation;
-import org.sonar.api.batch.sensor.issue.NewIssueLocation;
-import org.sonar.api.utils.PathUtils;
-
-import static java.util.Collections.unmodifiableList;
-import static java.util.stream.Collectors.toList;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public abstract class AbstractDefaultIssue<T extends AbstractDefaultIssue> extends DefaultStorable {
- protected IssueLocation primaryLocation;
- protected List<List<IssueLocation>> flows = new ArrayList<>();
- protected DefaultInputProject project;
-
- protected AbstractDefaultIssue(DefaultInputProject project) {
- this(project, null);
- }
-
- public AbstractDefaultIssue(DefaultInputProject project, @Nullable SensorStorage storage) {
- super(storage);
- this.project = project;
- }
-
- public IssueLocation primaryLocation() {
- return primaryLocation;
- }
-
- public List<Flow> flows() {
- return this.flows.stream()
- .<Flow>map(l -> () -> unmodifiableList(new ArrayList<>(l)))
- .collect(toList());
- }
-
- public NewIssueLocation newLocation() {
- return new DefaultIssueLocation();
- }
-
- public T at(NewIssueLocation primaryLocation) {
- checkArgument(primaryLocation != null, "Cannot use a location that is null");
- checkState(this.primaryLocation == null, "at() already called");
- this.primaryLocation = rewriteLocation((DefaultIssueLocation) primaryLocation);
- checkArgument(this.primaryLocation.inputComponent() != null, "Cannot use a location with no input component");
- return (T) this;
- }
-
- public T addLocation(NewIssueLocation secondaryLocation) {
- flows.add(Collections.singletonList(rewriteLocation((DefaultIssueLocation) secondaryLocation)));
- return (T) this;
- }
-
- public T addFlow(Iterable<NewIssueLocation> locations) {
- List<IssueLocation> flowAsList = new ArrayList<>();
- for (NewIssueLocation issueLocation : locations) {
- flowAsList.add(rewriteLocation((DefaultIssueLocation) issueLocation));
- }
- flows.add(flowAsList);
- return (T) this;
- }
-
- private DefaultIssueLocation rewriteLocation(DefaultIssueLocation location) {
- InputComponent component = location.inputComponent();
- Optional<Path> dirOrModulePath = Optional.empty();
-
- if (component instanceof DefaultInputDir) {
- DefaultInputDir dirComponent = (DefaultInputDir) component;
- dirOrModulePath = Optional.of(project.getBaseDir().relativize(dirComponent.path()));
- } else if (component instanceof DefaultInputModule && !Objects.equals(project.key(), component.key())) {
- DefaultInputModule moduleComponent = (DefaultInputModule) component;
- dirOrModulePath = Optional.of(project.getBaseDir().relativize(moduleComponent.getBaseDir()));
- }
-
- if (dirOrModulePath.isPresent()) {
- String path = PathUtils.sanitize(dirOrModulePath.get().toString());
- DefaultIssueLocation fixedLocation = new DefaultIssueLocation();
- fixedLocation.on(project);
- StringBuilder fullMessage = new StringBuilder();
- if (path != null && !path.isEmpty()) {
- fullMessage.append("[").append(path).append("] ");
- }
- fullMessage.append(location.message());
- fixedLocation.message(fullMessage.toString());
- return fixedLocation;
- } else {
- return location;
- }
- }
-}
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.batch.rule.Severity;
-import org.sonar.api.batch.sensor.internal.DefaultStorable;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.rule.AdHocRule;
import org.sonar.api.batch.sensor.rule.NewAdHocRule;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.sensor;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextPointer;
+import org.sonar.api.batch.sensor.error.AnalysisError;
+import org.sonar.api.batch.sensor.error.NewAnalysisError;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultAnalysisError extends DefaultStorable implements NewAnalysisError, AnalysisError {
+ private InputFile inputFile;
+ private String message;
+ private TextPointer location;
+
+ public DefaultAnalysisError() {
+ super(null);
+ }
+
+ public DefaultAnalysisError(SensorStorage storage) {
+ super(storage);
+ }
+
+ @Override
+ public InputFile inputFile() {
+ return inputFile;
+ }
+
+ @Override
+ public String message() {
+ return message;
+ }
+
+ @Override
+ public TextPointer location() {
+ return location;
+ }
+
+ @Override
+ public NewAnalysisError onFile(InputFile inputFile) {
+ checkArgument(inputFile != null, "Cannot use a inputFile that is null");
+ checkState(this.inputFile == null, "onFile() already called");
+ this.inputFile = inputFile;
+ return this;
+ }
+
+ @Override
+ public NewAnalysisError message(String message) {
+ this.message = message;
+ return this;
+ }
+
+ @Override
+ public NewAnalysisError at(TextPointer location) {
+ checkState(this.location == null, "at() already called");
+ this.location = location;
+ return this;
+ }
+
+ @Override
+ protected void doSave() {
+ requireNonNull(this.inputFile, "inputFile is mandatory on AnalysisError");
+ storage.store(this);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.sensor;
+
+import java.util.Collections;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.sensor.coverage.CoverageType;
+import org.sonar.api.batch.sensor.coverage.NewCoverage;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.scanner.fs.DefaultInputFile;
+
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultCoverage extends DefaultStorable implements NewCoverage {
+
+ private InputFile inputFile;
+ private CoverageType type;
+ private int totalCoveredLines = 0;
+ private int totalConditions = 0;
+ private int totalCoveredConditions = 0;
+ private SortedMap<Integer, Integer> hitsByLine = new TreeMap<>();
+ private SortedMap<Integer, Integer> conditionsByLine = new TreeMap<>();
+ private SortedMap<Integer, Integer> coveredConditionsByLine = new TreeMap<>();
+
+ public DefaultCoverage() {
+ super();
+ }
+
+ public DefaultCoverage(@Nullable SensorStorage storage) {
+ super(storage);
+ }
+
+ @Override
+ public DefaultCoverage onFile(InputFile inputFile) {
+ this.inputFile = inputFile;
+ return this;
+ }
+
+ public InputFile inputFile() {
+ return inputFile;
+ }
+
+ @Override
+ public NewCoverage ofType(CoverageType type) {
+ this.type = requireNonNull(type, "type can't be null");
+ return this;
+ }
+
+ public CoverageType type() {
+ return type;
+ }
+
+ @Override
+ public NewCoverage lineHits(int line, int hits) {
+ validateFile();
+ if (isExcluded()) {
+ return this;
+ }
+ validateLine(line);
+
+ if (!hitsByLine.containsKey(line)) {
+ hitsByLine.put(line, hits);
+ if (hits > 0) {
+ totalCoveredLines += 1;
+ }
+ }
+ return this;
+ }
+
+ private void validateLine(int line) {
+ checkState(line <= inputFile.lines(), "Line %s is out of range in the file %s (lines: %s)", line, inputFile, inputFile.lines());
+ checkState(line > 0, "Line number must be strictly positive: %s", line);
+ }
+
+ private void validateFile() {
+ requireNonNull(inputFile, "Call onFile() first");
+ }
+
+ @Override
+ public NewCoverage conditions(int line, int conditions, int coveredConditions) {
+ validateFile();
+ if (isExcluded()) {
+ return this;
+ }
+ validateLine(line);
+
+ if (conditions > 0 && !conditionsByLine.containsKey(line)) {
+ totalConditions += conditions;
+ totalCoveredConditions += coveredConditions;
+ conditionsByLine.put(line, conditions);
+ coveredConditionsByLine.put(line, coveredConditions);
+ }
+ return this;
+ }
+
+ public int coveredLines() {
+ return totalCoveredLines;
+ }
+
+ public int linesToCover() {
+ return hitsByLine.size();
+ }
+
+ public int conditions() {
+ return totalConditions;
+ }
+
+ public int coveredConditions() {
+ return totalCoveredConditions;
+ }
+
+ public SortedMap<Integer, Integer> hitsByLine() {
+ return Collections.unmodifiableSortedMap(hitsByLine);
+ }
+
+ public SortedMap<Integer, Integer> conditionsByLine() {
+ return Collections.unmodifiableSortedMap(conditionsByLine);
+ }
+
+ public SortedMap<Integer, Integer> coveredConditionsByLine() {
+ return Collections.unmodifiableSortedMap(coveredConditionsByLine);
+ }
+
+ @Override
+ public void doSave() {
+ validateFile();
+ if (!isExcluded()) {
+ storage.store(this);
+ }
+ }
+
+ private boolean isExcluded() {
+ return ((DefaultInputFile) inputFile).isExcludedForCoverage();
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.sensor;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
+import org.sonar.api.batch.sensor.cpd.internal.TokensLine;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.fs.DefaultInputFile;
+
+import static java.util.Collections.unmodifiableList;
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultCpdTokens extends DefaultStorable implements NewCpdTokens {
+ private static final Logger LOG = Loggers.get(DefaultCpdTokens.class);
+ private final List<TokensLine> result = new ArrayList<>();
+ private DefaultInputFile inputFile;
+ private int startLine = Integer.MIN_VALUE;
+ private int startIndex = 0;
+ private int currentIndex = 0;
+ private StringBuilder sb = new StringBuilder();
+ private TextRange lastRange;
+ private boolean loggedTestCpdWarning = false;
+
+ public DefaultCpdTokens(SensorStorage storage) {
+ super(storage);
+ }
+
+ @Override
+ public DefaultCpdTokens onFile(InputFile inputFile) {
+ this.inputFile = (DefaultInputFile) requireNonNull(inputFile, "file can't be null");
+ return this;
+ }
+
+ public InputFile inputFile() {
+ return inputFile;
+ }
+
+ @Override
+ public NewCpdTokens addToken(int startLine, int startLineOffset, int endLine, int endLineOffset, String image) {
+ checkInputFileNotNull();
+ TextRange newRange;
+ try {
+ newRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Unable to register token in file " + inputFile, e);
+ }
+ return addToken(newRange, image);
+ }
+
+ @Override
+ public DefaultCpdTokens addToken(TextRange range, String image) {
+ requireNonNull(range, "Range should not be null");
+ requireNonNull(image, "Image should not be null");
+ checkInputFileNotNull();
+ if (isExcludedForDuplication()) {
+ return this;
+ }
+ checkState(lastRange == null || lastRange.end().compareTo(range.start()) <= 0,
+ "Tokens of file %s should be provided in order.\nPrevious token: %s\nLast token: %s", inputFile, lastRange, range);
+
+ int line = range.start().line();
+ if (line != startLine) {
+ addNewTokensLine(result, startIndex, currentIndex, startLine, sb);
+ startIndex = currentIndex + 1;
+ startLine = line;
+ }
+ currentIndex++;
+ sb.append(image);
+ lastRange = range;
+
+ return this;
+ }
+
+ private boolean isExcludedForDuplication() {
+ if (inputFile.isExcludedForDuplication()) {
+ return true;
+ }
+ if (inputFile.type() == InputFile.Type.TEST) {
+ if (!loggedTestCpdWarning) {
+ LOG.warn("Duplication reported for '{}' will be ignored because it's a test file.", inputFile);
+ loggedTestCpdWarning = true;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public List<TokensLine> getTokenLines() {
+ return unmodifiableList(new ArrayList<>(result));
+ }
+
+ private static void addNewTokensLine(List<TokensLine> result, int startUnit, int endUnit, int startLine, StringBuilder sb) {
+ if (sb.length() != 0) {
+ result.add(new TokensLine(startUnit, endUnit, startLine, sb.toString()));
+ sb.setLength(0);
+ }
+ }
+
+ @Override
+ protected void doSave() {
+ checkState(inputFile != null, "Call onFile() first");
+ if (isExcludedForDuplication()) {
+ return;
+ }
+ addNewTokensLine(result, startIndex, currentIndex, startLine, sb);
+ storage.store(this);
+ }
+
+ private void checkInputFileNotNull() {
+ checkState(inputFile != null, "Call onFile() first");
+ }
+}
package org.sonar.scanner.sensor;
import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.issue.ExternalIssue;
import org.sonar.api.batch.sensor.issue.NewExternalIssue;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.RuleType;
+import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.scanner.issue.AbstractDefaultIssue;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import java.util.List;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
import org.sonar.api.batch.sensor.highlighting.TypeOfText;
-import org.sonar.api.batch.sensor.internal.DefaultStorable;
import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.scanner.fs.DefaultInputFile;
import static java.util.Objects.requireNonNull;
import static org.sonar.api.utils.Preconditions.checkState;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.scanner.sensor;
-
-import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
-import org.sonar.api.batch.rule.Severity;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.IssueLocation;
-import org.sonar.api.batch.sensor.issue.NewIssue;
-import org.sonar.api.rule.RuleKey;
-
-import static java.lang.String.format;
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultIssue extends AbstractDefaultIssue<DefaultIssue> implements Issue, NewIssue {
- private RuleKey ruleKey;
- private Double gap;
- private Severity overriddenSeverity;
-
- public DefaultIssue(DefaultInputProject project) {
- this(project, null);
- }
-
- public DefaultIssue(DefaultInputProject project, @Nullable SensorStorage storage) {
- super(project, storage);
- }
-
- public DefaultIssue forRule(RuleKey ruleKey) {
- this.ruleKey = ruleKey;
- return this;
- }
-
- public RuleKey ruleKey() {
- return this.ruleKey;
- }
-
- @Override
- public DefaultIssue gap(@Nullable Double gap) {
- checkArgument(gap == null || gap >= 0, format("Gap must be greater than or equal 0 (got %s)", gap));
- this.gap = gap;
- return this;
- }
-
- @Override
- public DefaultIssue overrideSeverity(@Nullable Severity severity) {
- this.overriddenSeverity = severity;
- return this;
- }
-
- @Override
- public Severity overriddenSeverity() {
- return this.overriddenSeverity;
- }
-
- @Override
- public Double gap() {
- return this.gap;
- }
-
- @Override
- public IssueLocation primaryLocation() {
- return primaryLocation;
- }
-
- @Override
- public void doSave() {
- requireNonNull(this.ruleKey, "ruleKey is mandatory on issue");
- checkState(primaryLocation != null, "Primary location is mandatory on every issue");
- storage.store(this);
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.scanner.sensor;
-
-import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.issue.IssueLocation;
-import org.sonar.api.batch.sensor.issue.NewIssueLocation;
-
-import static java.util.Objects.requireNonNull;
-import static org.apache.commons.lang.StringUtils.abbreviate;
-import static org.apache.commons.lang.StringUtils.trim;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultIssueLocation implements NewIssueLocation, IssueLocation {
-
- private InputComponent component;
- private TextRange textRange;
- private String message;
-
- @Override
- public DefaultIssueLocation on(InputComponent component) {
- checkArgument(component != null, "Component can't be null");
- checkState(this.component == null, "on() already called");
- this.component = component;
- return this;
- }
-
- @Override
- public DefaultIssueLocation at(TextRange location) {
- checkState(this.component != null, "at() should be called after on()");
- checkState(this.component.isFile(), "at() should be called only for an InputFile.");
- DefaultInputFile file = (DefaultInputFile) this.component;
- file.validate(location);
- this.textRange = location;
- return this;
- }
-
- @Override
- public DefaultIssueLocation message(String message) {
- requireNonNull(message, "Message can't be null");
- if (message.contains("\u0000")) {
- throw new IllegalArgumentException(unsupportedCharacterError(message, component));
- }
- this.message = abbreviate(trim(message), MESSAGE_MAX_SIZE);
- return this;
- }
-
- private static String unsupportedCharacterError(String message, @Nullable InputComponent component) {
- String error = "Character \\u0000 is not supported in issue message '" + message + "'";
- if (component != null) {
- error += ", on component: " + component.toString();
- }
- return error;
- }
-
- @Override
- public InputComponent inputComponent() {
- return this.component;
- }
-
- @Override
- public TextRange textRange() {
- return textRange;
- }
-
- @Override
- public String message() {
- return this.message;
- }
-
-}
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.measure.Metric;
-import org.sonar.api.batch.sensor.internal.DefaultStorable;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.measure.Measure;
import org.sonar.api.batch.sensor.measure.NewMeasure;
import org.sonar.api.batch.fs.InputDir;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.fs.internal.DefaultInputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.measure.Metric;
import org.sonar.api.batch.measure.MetricFinder;
-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.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.AnalysisError;
import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.batch.sensor.measure.Measure;
import org.sonar.api.batch.sensor.rule.AdHocRule;
-import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
+import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
import org.sonar.api.config.Configuration;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.utils.KeyValueFormat;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.internal.pmd.PmdBlockChunker;
import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
+import org.sonar.scanner.fs.DefaultInputComponent;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputModule;
import org.sonar.scanner.issue.IssuePublisher;
import org.sonar.scanner.protocol.Constants;
import org.sonar.scanner.protocol.output.FileStructure;
}
@Override
- public void store(DefaultSymbolTable symbolTable) {
+ public void store(NewSymbolTable newSymbolTable) {
+ DefaultSymbolTable symbolTable = (DefaultSymbolTable) newSymbolTable;
ScannerReportWriter writer = reportPublisher.getWriter();
DefaultInputFile inputFile = (DefaultInputFile) symbolTable.inputFile();
if (shouldSkipStorage(inputFile)) {
}
@Override
- public void store(DefaultCoverage defaultCoverage) {
+ public void store(NewCoverage coverage) {
+ DefaultCoverage defaultCoverage = (DefaultCoverage) coverage;
DefaultInputFile inputFile = (DefaultInputFile) defaultCoverage.inputFile();
inputFile.setPublished(true);
}
}
- private static void validatePositiveLine(Map<Integer, Integer> m, String filePath) {
- for (int l : m.keySet()) {
- if (l <= 0) {
- throw new IllegalStateException(String.format("Measure with line %d for file '%s' must be > 0", l, filePath));
- }
- }
- }
-
@Override
- public void store(DefaultCpdTokens defaultCpdTokens) {
+ public void store(NewCpdTokens cpdTokens) {
+ DefaultCpdTokens defaultCpdTokens = (DefaultCpdTokens) cpdTokens;
DefaultInputFile inputFile = (DefaultInputFile) defaultCpdTokens.inputFile();
inputFile.setPublished(true);
PmdBlockChunker blockChunker = new PmdBlockChunker(getCpdBlockSize(inputFile.language()));
}
@Override
- public void store(DefaultSignificantCode significantCode) {
+ public void store(NewSignificantCode newSignificantCode) {
+ DefaultSignificantCode significantCode = (DefaultSignificantCode) newSignificantCode;
ScannerReportWriter writer = reportPublisher.getWriter();
DefaultInputFile inputFile = (DefaultInputFile) significantCode.inputFile();
if (shouldSkipStorage(inputFile)) {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.sensor;
+
+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.SensorStorage;
+import org.sonar.api.utils.Preconditions;
+
+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;
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.sensor;
+
+import javax.annotation.Nullable;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public abstract class DefaultStorable {
+
+ protected final transient SensorStorage storage;
+ private transient boolean saved = false;
+
+ public DefaultStorable() {
+ this.storage = null;
+ }
+
+ public DefaultStorable(@Nullable SensorStorage storage) {
+ this.storage = storage;
+ }
+
+ public final void save() {
+ requireNonNull(this.storage, "No persister on this object");
+ checkState(!saved, "This object was already saved");
+ doSave();
+ this.saved = true;
+ }
+
+ protected abstract void doSave();
+
+ @Override
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.sensor;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.symbol.NewSymbol;
+import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
+import org.sonar.scanner.fs.DefaultInputFile;
+
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultSymbolTable extends DefaultStorable implements NewSymbolTable {
+
+ private final Map<TextRange, Set<TextRange>> referencesBySymbol;
+ private DefaultInputFile inputFile;
+
+ public DefaultSymbolTable(SensorStorage storage) {
+ super(storage);
+ referencesBySymbol = new LinkedHashMap<>();
+ }
+
+ public Map<TextRange, Set<TextRange>> getReferencesBySymbol() {
+ return referencesBySymbol;
+ }
+
+ @Override
+ public DefaultSymbolTable onFile(InputFile inputFile) {
+ requireNonNull(inputFile, "file can't be null");
+ this.inputFile = (DefaultInputFile) inputFile;
+ return this;
+ }
+
+ public InputFile inputFile() {
+ return inputFile;
+ }
+
+ @Override
+ public NewSymbol newSymbol(int startLine, int startLineOffset, int endLine, int endLineOffset) {
+ checkInputFileNotNull();
+ TextRange declarationRange;
+ try {
+ declarationRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Unable to create symbol on file " + inputFile, e);
+ }
+ return newSymbol(declarationRange);
+ }
+
+ @Override
+ public NewSymbol newSymbol(int startOffset, int endOffset) {
+ checkInputFileNotNull();
+ TextRange declarationRange;
+ try {
+ declarationRange = inputFile.newRange(startOffset, endOffset);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Unable to create symbol on file " + inputFile, e);
+ }
+ return newSymbol(declarationRange);
+ }
+
+ @Override
+ public NewSymbol newSymbol(TextRange range) {
+ checkInputFileNotNull();
+ TreeSet<TextRange> references = new TreeSet<>((o1, o2) -> o1.start().compareTo(o2.start()));
+ referencesBySymbol.put(range, references);
+ return new DefaultSymbol(inputFile, range, references);
+ }
+
+ private static class DefaultSymbol implements NewSymbol {
+
+ private final Collection<TextRange> references;
+ private final DefaultInputFile inputFile;
+ private final TextRange declaration;
+
+ public DefaultSymbol(DefaultInputFile inputFile, TextRange declaration, Collection<TextRange> references) {
+ this.inputFile = inputFile;
+ this.declaration = declaration;
+ this.references = references;
+ }
+
+ @Override
+ public NewSymbol newReference(int startOffset, int endOffset) {
+ TextRange referenceRange;
+ try {
+ referenceRange = inputFile.newRange(startOffset, endOffset);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Unable to create symbol reference on file " + inputFile, e);
+ }
+ return newReference(referenceRange);
+ }
+
+ @Override
+ public NewSymbol newReference(int startLine, int startLineOffset, int endLine, int endLineOffset) {
+ TextRange referenceRange;
+ try {
+ referenceRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Unable to create symbol reference on file " + inputFile, e);
+ }
+ return newReference(referenceRange);
+ }
+
+ @Override
+ public NewSymbol newReference(TextRange range) {
+ requireNonNull(range, "Provided range is null");
+ checkArgument(!declaration.overlap(range), "Overlapping symbol declaration and reference for symbol at %s", declaration);
+ references.add(range);
+ return this;
+ }
+
+ }
+
+ @Override
+ protected void doSave() {
+ checkInputFileNotNull();
+ storage.store(this);
+ }
+
+ private void checkInputFileNotNull() {
+ checkState(inputFile != null, "Call onFile() first");
+ }
+}
import java.util.HashMap;
import java.util.List;
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.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.AnalysisError;
import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.batch.sensor.measure.Measure;
import org.sonar.api.batch.sensor.rule.AdHocRule;
-import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
+import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
import static org.sonar.api.utils.Preconditions.checkArgument;
}
@Override
- public void store(DefaultCoverage defaultCoverage) {
+ public void store(NewCoverage coverage) {
+ DefaultCoverage defaultCoverage = (DefaultCoverage) coverage;
String fileKey = defaultCoverage.inputFile().key();
coverageByComponent.computeIfAbsent(fileKey, x -> new ArrayList<>()).add(defaultCoverage);
}
@Override
- public void store(DefaultCpdTokens defaultCpdTokens) {
+ public void store(NewCpdTokens cpdTokens) {
+ DefaultCpdTokens defaultCpdTokens = (DefaultCpdTokens) cpdTokens;
String fileKey = defaultCpdTokens.inputFile().key();
// Emulate duplicate storage check
if (cpdTokensByComponent.containsKey(fileKey)) {
}
@Override
- public void store(DefaultSymbolTable symbolTable) {
+ public void store(NewSymbolTable newSymbolTable) {
+ DefaultSymbolTable symbolTable = (DefaultSymbolTable) newSymbolTable;
String fileKey = symbolTable.inputFile().key();
// Emulate duplicate storage check
if (symbolsPerComponent.containsKey(fileKey)) {
}
@Override
- public void store(DefaultSignificantCode significantCode) {
+ public void store(NewSignificantCode newSignificantCode) {
+ DefaultSignificantCode significantCode = (DefaultSignificantCode) newSignificantCode;
String fileKey = significantCode.inputFile().key();
// Emulate duplicate storage check
if (significantCodePerComponent.containsKey(fileKey)) {
import org.sonar.api.SonarRuntime;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.config.Configuration;
import org.sonar.api.config.Settings;
+import org.sonar.scanner.fs.DefaultInputProject;
@ThreadSafe
public class ModuleSensorContext extends ProjectSensorContext {
private final InputModule module;
public ModuleSensorContext(DefaultInputProject project, InputModule module, Configuration config, Settings mutableSettings, FileSystem fs, ActiveRules activeRules,
- SensorStorage sensorStorage, SonarRuntime sonarRuntime) {
+ SensorStorage sensorStorage, SonarRuntime sonarRuntime) {
super(project, config, mutableSettings, fs, activeRules, sensorStorage, sonarRuntime);
this.module = module;
}
import java.util.Collection;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.batch.fs.internal.SensorStrategy;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.util.logs.Profiler;
import org.sonar.scanner.bootstrap.ScannerPluginRepository;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.InputModuleHierarchy;
public class ModuleSensorsExecutor {
private static final Logger LOG = Loggers.get(ModuleSensorsExecutor.class);
private final boolean isRoot;
public ModuleSensorsExecutor(ModuleSensorExtensionDictionnary selector, DefaultInputModule module, InputModuleHierarchy hierarchy,
- SensorStrategy strategy, ScannerPluginRepository pluginRepo) {
+ SensorStrategy strategy, ScannerPluginRepository pluginRepo) {
this.selector = selector;
this.strategy = strategy;
this.pluginRepo = pluginRepo;
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.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.rule.ActiveRules;
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;
-import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens;
import org.sonar.api.batch.sensor.error.NewAnalysisError;
import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.measure.NewMeasure;
import org.sonar.api.batch.sensor.rule.NewAdHocRule;
import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
-import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
import org.sonar.api.config.Configuration;
import org.sonar.api.config.Settings;
import org.sonar.api.scanner.fs.InputProject;
import org.sonar.api.utils.Version;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.scanner.issue.DefaultIssue;
import org.sonar.scanner.sensor.noop.NoOpNewAnalysisError;
@ThreadSafe
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputModule;
import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
-import org.sonar.api.batch.fs.internal.DefaultTextPointer;
import org.sonar.api.batch.rule.ActiveRules;
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;
-import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens;
import org.sonar.api.batch.sensor.cpd.internal.TokensLine;
import org.sonar.api.batch.sensor.error.AnalysisError;
import org.sonar.api.batch.sensor.error.NewAnalysisError;
-import org.sonar.api.batch.sensor.error.internal.DefaultAnalysisError;
import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
import org.sonar.api.batch.sensor.highlighting.TypeOfText;
import org.sonar.api.batch.sensor.issue.ExternalIssue;
import org.sonar.api.batch.sensor.rule.AdHocRule;
import org.sonar.api.batch.sensor.rule.NewAdHocRule;
import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
-import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
import org.sonar.api.config.Configuration;
import org.sonar.api.config.Settings;
import org.sonar.api.config.internal.ConfigurationBridge;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.Version;
import org.sonar.scanner.fs.DefaultFileSystem;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.scanner.fs.DefaultTextPointer;
+import org.sonar.scanner.issue.DefaultIssue;
import org.sonar.scanner.rule.ActiveRulesBuilder;
import static java.util.Collections.unmodifiableMap;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.SensorDescriptor;
import org.sonar.api.batch.sensor.coverage.NewCoverage;
import org.sonar.api.scanner.sensor.ProjectSensor;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.report.ReportPublisher;
@Phase(name = Phase.Name.POST)
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.ArgumentCaptor;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.api.batch.measure.MetricFinder;
import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.scanner.sensor.DefaultMeasure;
import org.sonar.api.measures.CoreMetrics;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.scanner.sensor.DefaultMeasure;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
fileLineMeasures.setIntValue(HITS_METRIC_KEY, 1, 2);
}
-
}
package org.sonar.scanner.analysis;
import java.io.File;
-import java.io.IOException;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.utils.TempFolder;
+import org.sonar.scanner.fs.DefaultInputProject;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
}
@Test
- public void createTempFolder() throws IOException {
+ public void createTempFolder() {
File defaultDir = new File(temp.getRoot(), AnalysisTempFolderProvider.TMP_NAME);
TempFolder tempFolder = tempFolderProvider.provide(project);
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.mockito.ArgumentMatchers;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
-import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.core.util.CloseableIterator;
import org.sonar.duplications.index.CloneGroup;
import org.sonar.duplications.index.ClonePart;
import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.protocol.output.ScannerReport.Duplicate;
import org.sonar.scanner.protocol.output.ScannerReport.Duplication;
import org.sonar.scanner.protocol.output.ScannerReportReader;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.config.Configuration;
+import org.sonar.scanner.fs.DefaultInputProject;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.duplications.block.Block;
import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.sensor.SensorContextTester;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.issue.ExternalIssue;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.sensor.SensorContextTester;
import static java.nio.charset.StandardCharsets.UTF_8;
ReportParser.TextRange input = new ReportParser.TextRange();
input.startLine = 1;
input.startColumn = 4;
- input.endLine= 2;
- input.endColumn= 3;
+ input.endLine = 2;
+ input.endColumn = 3;
runOn(newIssue(input));
ReportParser.TextRange input = new ReportParser.TextRange();
input.startLine = 1;
input.startColumn = null;
- input.endLine= 2;
- input.endColumn= null;
+ input.endLine = 2;
+ input.endColumn = null;
runOn(newIssue(input));
ReportParser.TextRange input = new ReportParser.TextRange();
input.startLine = 1;
input.startColumn = 3;
- input.endLine= 2;
- input.endColumn= null;
+ input.endLine = 2;
+ input.endColumn = null;
runOn(newIssue(input));
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.fs;
+
+import java.io.File;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DefaultInputDirTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Test
+ public void test() throws Exception {
+ File baseDir = temp.newFolder();
+ DefaultInputDir inputDir = new DefaultInputDir("ABCDE", "src")
+ .setModuleBaseDir(baseDir.toPath());
+
+ assertThat(inputDir.key()).isEqualTo("ABCDE:src");
+ assertThat(inputDir.file().getAbsolutePath()).isEqualTo(new File(baseDir, "src").getAbsolutePath());
+ assertThat(inputDir.relativePath()).isEqualTo("src");
+ assertThat(new File(inputDir.relativePath())).isRelative();
+ assertThat(inputDir.absolutePath()).endsWith("src");
+ assertThat(new File(inputDir.absolutePath())).isAbsolute();
+ }
+
+ @Test
+ public void testEqualsAndHashCode() throws Exception {
+ DefaultInputDir inputDir1 = new DefaultInputDir("ABCDE", "src");
+
+ DefaultInputDir inputDir2 = new DefaultInputDir("ABCDE", "src");
+
+ assertThat(inputDir1.equals(inputDir1)).isTrue();
+ assertThat(inputDir1.equals(inputDir2)).isTrue();
+ assertThat(inputDir1.equals("foo")).isFalse();
+
+ assertThat(inputDir1.hashCode()).isEqualTo(63545559);
+
+ assertThat(inputDir1.toString()).contains("[moduleKey=ABCDE, relative=src, basedir=null");
+
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.fs;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.stream.Collectors;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.fs.internal.Metadata;
+import org.sonar.api.batch.fs.internal.SensorStrategy;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+
+public class DefaultInputFileTest {
+
+ private static final String PROJECT_RELATIVE_PATH = "module1/src/Foo.php";
+ private static final String MODULE_RELATIVE_PATH = "src/Foo.php";
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ private DefaultIndexedFile indexedFile;
+
+ private Path baseDir;
+ private SensorStrategy sensorStrategy;
+
+ @Before
+ public void prepare() throws IOException {
+ baseDir = temp.newFolder().toPath();
+ sensorStrategy = new SensorStrategy();
+ indexedFile = new DefaultIndexedFile(baseDir.resolve(PROJECT_RELATIVE_PATH), "ABCDE", PROJECT_RELATIVE_PATH, MODULE_RELATIVE_PATH, InputFile.Type.TEST, "php", 0,
+ sensorStrategy);
+ }
+
+ @Test
+ public void test() throws Exception {
+
+ Metadata metadata = new Metadata(42, 42, "", new int[0], new int[0], 10);
+ DefaultInputFile inputFile = new DefaultInputFile(indexedFile, (f) -> f.setMetadata(metadata))
+ .setStatus(InputFile.Status.ADDED)
+ .setCharset(StandardCharsets.ISO_8859_1);
+
+ assertThat(inputFile.absolutePath()).endsWith("Foo.php");
+ assertThat(inputFile.filename()).isEqualTo("Foo.php");
+ assertThat(inputFile.uri()).hasPath(baseDir.resolve(PROJECT_RELATIVE_PATH).toUri().getPath());
+ assertThat(new File(inputFile.absolutePath())).isAbsolute();
+ assertThat(inputFile.language()).isEqualTo("php");
+ assertThat(inputFile.status()).isEqualTo(InputFile.Status.ADDED);
+ assertThat(inputFile.type()).isEqualTo(InputFile.Type.TEST);
+ assertThat(inputFile.lines()).isEqualTo(42);
+ assertThat(inputFile.charset()).isEqualTo(StandardCharsets.ISO_8859_1);
+
+ assertThat(inputFile.getModuleRelativePath()).isEqualTo(MODULE_RELATIVE_PATH);
+ assertThat(inputFile.getProjectRelativePath()).isEqualTo(PROJECT_RELATIVE_PATH);
+
+ sensorStrategy.setGlobal(false);
+ assertThat(inputFile.relativePath()).isEqualTo(MODULE_RELATIVE_PATH);
+ assertThat(new File(inputFile.relativePath())).isRelative();
+ sensorStrategy.setGlobal(true);
+ assertThat(inputFile.relativePath()).isEqualTo(PROJECT_RELATIVE_PATH);
+ assertThat(new File(inputFile.relativePath())).isRelative();
+ }
+
+ @Test
+ public void test_content() throws IOException {
+ Path testFile = baseDir.resolve(PROJECT_RELATIVE_PATH);
+ Files.createDirectories(testFile.getParent());
+ String content = "test é string";
+ Files.write(testFile, content.getBytes(StandardCharsets.ISO_8859_1));
+
+ assertThat(Files.readAllLines(testFile, StandardCharsets.ISO_8859_1).get(0)).hasSize(content.length());
+
+ Metadata metadata = new Metadata(42, 30, "", new int[0], new int[0], 10);
+
+ DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> f.setMetadata(metadata))
+ .setStatus(InputFile.Status.ADDED)
+ .setCharset(StandardCharsets.ISO_8859_1);
+
+ assertThat(inputFile.contents()).isEqualTo(content);
+ try (InputStream inputStream = inputFile.inputStream()) {
+ String result = new BufferedReader(new InputStreamReader(inputStream, inputFile.charset())).lines().collect(Collectors.joining());
+ assertThat(result).isEqualTo(content);
+ }
+
+ }
+
+ @Test
+ public void test_content_exclude_bom() throws IOException {
+ Path testFile = baseDir.resolve(PROJECT_RELATIVE_PATH);
+ Files.createDirectories(testFile.getParent());
+ try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(testFile.toFile()), StandardCharsets.UTF_8))) {
+ out.write('\ufeff');
+ }
+ String content = "test é string €";
+ Files.write(testFile, content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
+
+ assertThat(Files.readAllLines(testFile, StandardCharsets.UTF_8).get(0)).hasSize(content.length() + 1);
+
+ Metadata metadata = new Metadata(42, 30, "", new int[0], new int[0], 10);
+
+ DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> f.setMetadata(metadata))
+ .setStatus(InputFile.Status.ADDED)
+ .setCharset(StandardCharsets.UTF_8);
+
+ assertThat(inputFile.contents()).isEqualTo(content);
+ try (InputStream inputStream = inputFile.inputStream()) {
+ String result = new BufferedReader(new InputStreamReader(inputStream, inputFile.charset())).lines().collect(Collectors.joining());
+ assertThat(result).isEqualTo(content);
+ }
+
+ }
+
+ @Test
+ public void test_equals_and_hashcode() throws Exception {
+ DefaultInputFile f1 = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class));
+ DefaultInputFile f1a = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class));
+ DefaultInputFile f2 = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Bar.php", null), (f) -> mock(Metadata.class));
+
+ assertThat(f1).isEqualTo(f1);
+ assertThat(f1).isEqualTo(f1a);
+ assertThat(f1).isNotEqualTo(f2);
+ assertThat(f1.equals("foo")).isFalse();
+ assertThat(f1.equals(null)).isFalse();
+
+ assertThat(f1.hashCode()).isEqualTo(f1.hashCode());
+ assertThat(f1.hashCode()).isEqualTo(f1a.hashCode());
+ }
+
+ @Test
+ public void test_toString() throws Exception {
+ DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class));
+ assertThat(file.toString()).isEqualTo(MODULE_RELATIVE_PATH);
+ }
+
+ @Test
+ public void checkValidPointer() {
+ Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {9, 15}, 16);
+ DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
+ assertThat(file.newPointer(1, 0).line()).isEqualTo(1);
+ assertThat(file.newPointer(1, 0).lineOffset()).isEqualTo(0);
+ // Don't fail
+ file.newPointer(1, 9);
+ file.newPointer(2, 0);
+ file.newPointer(2, 5);
+
+ try {
+ file.newPointer(0, 1);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("0 is not a valid line for a file");
+ }
+ try {
+ file.newPointer(3, 1);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("3 is not a valid line for pointer. File src/Foo.php has 2 line(s)");
+ }
+ try {
+ file.newPointer(1, -1);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("-1 is not a valid line offset for a file");
+ }
+ try {
+ file.newPointer(1, 10);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("10 is not a valid line offset for pointer. File src/Foo.php has 9 character(s) at line 1");
+ }
+ }
+
+ @Test
+ public void checkValidPointerUsingGlobalOffset() {
+ Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {8, 15}, 16);
+ DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
+ assertThat(file.newPointer(0).line()).isEqualTo(1);
+ assertThat(file.newPointer(0).lineOffset()).isEqualTo(0);
+
+ assertThat(file.newPointer(9).line()).isEqualTo(1);
+ // Ignore eol characters
+ assertThat(file.newPointer(9).lineOffset()).isEqualTo(8);
+
+ assertThat(file.newPointer(10).line()).isEqualTo(2);
+ assertThat(file.newPointer(10).lineOffset()).isEqualTo(0);
+
+ assertThat(file.newPointer(15).line()).isEqualTo(2);
+ assertThat(file.newPointer(15).lineOffset()).isEqualTo(5);
+
+ assertThat(file.newPointer(16).line()).isEqualTo(2);
+ // Ignore eol characters
+ assertThat(file.newPointer(16).lineOffset()).isEqualTo(5);
+
+ try {
+ file.newPointer(-1);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("-1 is not a valid offset for a file");
+ }
+
+ try {
+ file.newPointer(17);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("17 is not a valid offset for file src/Foo.php. Max offset is 16");
+ }
+ }
+
+ @Test
+ public void checkValidRange() {
+ Metadata metadata = new FileMetadata().readMetadata(new StringReader("bla bla a\nabcde"));
+ DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
+
+ assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(2, 1)).start().line()).isEqualTo(1);
+ // Don't fail
+ file.newRange(file.newPointer(1, 0), file.newPointer(1, 1));
+ file.newRange(file.newPointer(1, 0), file.newPointer(1, 9));
+ file.newRange(file.newPointer(1, 0), file.newPointer(2, 0));
+ assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(2, 5))).isEqualTo(file.newRange(0, 15));
+
+ try {
+ file.newRange(file.newPointer(1, 0), file.newPointer(1, 0));
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Start pointer [line=1, lineOffset=0] should be before end pointer [line=1, lineOffset=0]");
+ }
+ try {
+ file.newRange(file.newPointer(1, 0), file.newPointer(1, 10));
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("10 is not a valid line offset for pointer. File src/Foo.php has 9 character(s) at line 1");
+ }
+ }
+
+ @Test
+ public void selectLine() {
+ Metadata metadata = new FileMetadata().readMetadata(new StringReader("bla bla a\nabcde\n\nabc"));
+ DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
+
+ assertThat(file.selectLine(1).start().line()).isEqualTo(1);
+ assertThat(file.selectLine(1).start().lineOffset()).isEqualTo(0);
+ assertThat(file.selectLine(1).end().line()).isEqualTo(1);
+ assertThat(file.selectLine(1).end().lineOffset()).isEqualTo(9);
+
+ // Don't fail when selecting empty line
+ assertThat(file.selectLine(3).start().line()).isEqualTo(3);
+ assertThat(file.selectLine(3).start().lineOffset()).isEqualTo(0);
+ assertThat(file.selectLine(3).end().line()).isEqualTo(3);
+ assertThat(file.selectLine(3).end().lineOffset()).isEqualTo(0);
+
+ try {
+ file.selectLine(5);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("5 is not a valid line for pointer. File src/Foo.php has 4 line(s)");
+ }
+ }
+
+ @Test
+ public void checkValidRangeUsingGlobalOffset() {
+ Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {9, 15}, 16);
+ DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
+ TextRange newRange = file.newRange(10, 13);
+ assertThat(newRange.start().line()).isEqualTo(2);
+ assertThat(newRange.start().lineOffset()).isEqualTo(0);
+ assertThat(newRange.end().line()).isEqualTo(2);
+ assertThat(newRange.end().lineOffset()).isEqualTo(3);
+ }
+
+ @Test
+ public void testRangeOverlap() {
+ Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {9, 15}, 16);
+ DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
+ // Don't fail
+ assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)))).isTrue();
+ assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 2)))).isTrue();
+ assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 1), file.newPointer(1, 2)))).isFalse();
+ assertThat(file.newRange(file.newPointer(1, 2), file.newPointer(1, 3)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 2)))).isFalse();
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.fs;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DefaultInputModuleTest {
+
+ private static final String FILE_1 = "file1";
+ private static final String TEST_1 = "test1";
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Test
+ public void check_getters() throws IOException {
+ ProjectDefinition def = ProjectDefinition.create();
+ def.setKey("moduleKey");
+ File baseDir = temp.newFolder();
+ Path src = baseDir.toPath().resolve(FILE_1);
+ Files.createFile(src);
+ Path test = baseDir.toPath().resolve(TEST_1);
+ Files.createFile(test);
+ def.setBaseDir(baseDir);
+ File workDir = temp.newFolder();
+ def.setWorkDir(workDir);
+ def.setSources(FILE_1);
+ def.setTests(TEST_1);
+ DefaultInputModule module = new DefaultInputModule(def);
+
+ assertThat(module.key()).isEqualTo("moduleKey");
+ assertThat(module.definition()).isEqualTo(def);
+ assertThat(module.getBranch()).isNull();
+ assertThat(module.getBaseDir()).isEqualTo(baseDir.toPath());
+ assertThat(module.getKeyWithBranch()).isEqualTo("moduleKey");
+ assertThat(module.getWorkDir()).isEqualTo(workDir.toPath());
+ assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
+ assertThat(module.getSourceDirsOrFiles().get()).containsExactlyInAnyOrder(src);
+ assertThat(module.getTestDirsOrFiles().get()).containsExactlyInAnyOrder(test);
+ assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
+
+ assertThat(module.isFile()).isFalse();
+ }
+
+ @Test
+ public void no_sources() throws IOException {
+ ProjectDefinition def = ProjectDefinition.create();
+ def.setKey("moduleKey");
+ File baseDir = temp.newFolder();
+ Path src = baseDir.toPath().resolve(FILE_1);
+ Files.createFile(src);
+ Path test = baseDir.toPath().resolve(TEST_1);
+ Files.createFile(test);
+ def.setBaseDir(baseDir);
+ File workDir = temp.newFolder();
+ def.setWorkDir(workDir);
+ DefaultInputModule module = new DefaultInputModule(def);
+
+ assertThat(module.key()).isEqualTo("moduleKey");
+ assertThat(module.definition()).isEqualTo(def);
+ assertThat(module.getBranch()).isNull();
+ assertThat(module.getBaseDir()).isEqualTo(baseDir.toPath());
+ assertThat(module.getKeyWithBranch()).isEqualTo("moduleKey");
+ assertThat(module.getWorkDir()).isEqualTo(workDir.toPath());
+ assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
+ assertThat(module.getSourceDirsOrFiles()).isNotPresent();
+ assertThat(module.getTestDirsOrFiles()).isNotPresent();
+ assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
+
+ assertThat(module.isFile()).isFalse();
+ }
+
+ @Test
+ public void working_directory_should_be_hidden() throws IOException {
+ ProjectDefinition def = ProjectDefinition.create();
+ File workDir = temp.newFolder(".sonar");
+ def.setWorkDir(workDir);
+ File baseDir = temp.newFolder();
+ def.setBaseDir(baseDir);
+ DefaultInputModule module = new DefaultInputModule(def);
+ assertThat(workDir.isHidden()).isTrue();
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.fs;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DefaultInputProjectTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Test
+ public void testGetters() throws IOException {
+ ProjectDefinition def = ProjectDefinition.create();
+ def.setKey("projectKey");
+ def.setName("projectName");
+ File baseDir = temp.newFolder();
+ def.setBaseDir(baseDir);
+ def.setDescription("desc");
+ File workDir = temp.newFolder();
+ def.setWorkDir(workDir);
+ def.setSources("file1");
+ def.setTests("test1");
+ AbstractProjectOrModule project = new DefaultInputProject(def);
+
+ assertThat(project.key()).isEqualTo("projectKey");
+ assertThat(project.getName()).isEqualTo("projectName");
+ assertThat(project.getOriginalName()).isEqualTo("projectName");
+ assertThat(project.definition()).isEqualTo(def);
+ assertThat(project.getBranch()).isNull();
+ assertThat(project.getBaseDir()).isEqualTo(baseDir.toPath());
+ assertThat(project.getKeyWithBranch()).isEqualTo("projectKey");
+ assertThat(project.getDescription()).isEqualTo("desc");
+ assertThat(project.getWorkDir()).isEqualTo(workDir.toPath());
+ assertThat(project.getEncoding()).isEqualTo(Charset.defaultCharset());
+
+ assertThat(project.properties()).hasSize(5);
+
+ assertThat(project.isFile()).isFalse();
+ }
+
+ @Test
+ public void testEncoding() throws IOException {
+ ProjectDefinition def = ProjectDefinition.create();
+ def.setKey("projectKey");
+ def.setName("projectName");
+ File baseDir = temp.newFolder();
+ def.setBaseDir(baseDir);
+ def.setProjectVersion("version");
+ def.setDescription("desc");
+ File workDir = temp.newFolder();
+ def.setWorkDir(workDir);
+ def.setSources("file1");
+ def.setProperty("sonar.sourceEncoding", "UTF-16");
+ AbstractProjectOrModule project = new DefaultInputProject(def);
+
+ assertThat(project.getEncoding()).isEqualTo(StandardCharsets.UTF_16);
+ }
+
+}
import java.io.FileInputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
-
import javax.annotation.Nullable;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.Metadata;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
File tempFile = temp.newFile();
FileUtils.write(tempFile, " foo\nb ar\r\nbaz \t", StandardCharsets.UTF_8, true);
- org.sonar.api.batch.fs.internal.DefaultInputFile f = new TestInputFileBuilder("foo", tempFile.getName())
+ DefaultInputFile f = new TestInputFileBuilder("foo", tempFile.getName())
.setModuleBaseDir(tempFile.getParentFile().toPath())
.setCharset(StandardCharsets.UTF_8)
.build();
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.fs;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import org.apache.commons.io.IOUtils;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.InputFile.Status;
+import org.sonar.api.batch.fs.InputFile.Type;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class TestInputFileBuilderTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Test
+ public void setContent() throws IOException {
+ DefaultInputFile file = TestInputFileBuilder.create("module", "invalidPath")
+ .setContents("my content")
+ .setCharset(StandardCharsets.UTF_8)
+ .build();
+ assertThat(file.contents()).isEqualTo("my content");
+ assertThat(IOUtils.toString(file.inputStream())).isEqualTo("my content");
+ }
+
+ @Test
+ public void testGetters() {
+ DefaultInputFile file = TestInputFileBuilder.create("module", new File("baseDir"), new File("baseDir", "path"))
+ .setStatus(Status.SAME)
+ .setType(Type.MAIN)
+ .build();
+
+ assertThat(file.type()).isEqualTo(Type.MAIN);
+ assertThat(file.status()).isEqualTo(Status.SAME);
+ assertThat(file.isPublished()).isTrue();
+ assertThat(file.type()).isEqualTo(Type.MAIN);
+ assertThat(file.relativePath()).isEqualTo("path");
+ assertThat(file.absolutePath()).isEqualTo("baseDir/path");
+
+ }
+
+ @Test
+ public void testCreateInputModule() throws IOException {
+ File baseDir = temp.newFolder();
+ AbstractProjectOrModule module = TestInputFileBuilder.newDefaultInputModule("key", baseDir);
+ assertThat(module.key()).isEqualTo("key");
+ assertThat(module.getBaseDir()).isEqualTo(baseDir.toPath());
+ }
+}
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.utils.MessageException;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.sensor.SensorContextTester;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.test.MutableTestCase;
import org.sonar.api.test.MutableTestPlan;
import org.sonar.api.utils.MessageException;
import org.sonar.scanner.deprecated.test.TestPlanBuilder;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.sensor.SensorContextTester;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.scanner.ProjectInfo;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.protocol.Constants.Severity;
import org.sonar.scanner.protocol.output.ScannerReport.Issue;
import org.sonar.scanner.protocol.output.ScannerReport.TextRange;
import org.mockito.runners.MockitoJUnitRunner;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.rule.ActiveRulesBuilder;
-import org.sonar.scanner.rule.NewActiveRule;
-import org.sonar.scanner.rule.RulesBuilder;
-import org.sonar.scanner.sensor.DefaultExternalIssue;
-import org.sonar.scanner.sensor.DefaultIssue;
-import org.sonar.scanner.sensor.DefaultIssueLocation;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
import org.sonar.api.rules.RuleType;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.report.ReportPublisher;
+import org.sonar.scanner.rule.ActiveRulesBuilder;
+import org.sonar.scanner.rule.NewActiveRule;
+import org.sonar.scanner.rule.RulesBuilder;
+import org.sonar.scanner.sensor.DefaultExternalIssue;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import org.junit.Before;
import org.junit.Test;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.scan.issue.filter.IssueFilterChain;
import org.sonar.api.utils.WildcardPattern;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.issue.DefaultFilterableIssue;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.rules.ExpectedException;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.api.notifications.AnalysisWarnings;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.issue.ignore.IgnoreIssuesFilter;
import org.sonar.scanner.issue.ignore.pattern.IssueExclusionPatternInitializer;
import org.sonar.scanner.issue.ignore.pattern.IssuePattern;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.FileMetadata;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.issue.ignore.pattern.IssueExclusionPatternInitializer;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.FileMetadata;
import org.sonar.scanner.mediumtest.AnalysisResult;
import org.sonar.scanner.mediumtest.ScannerMediumTester;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.SonarEdition;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.utils.MessageException;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.mediumtest.AnalysisResult;
import org.sonar.scanner.mediumtest.ScannerMediumTester;
import org.sonar.xoo.XooPlugin;
import org.sonar.api.CoreProperties;
import org.sonar.api.SonarEdition;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.PathUtils;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.mediumtest.AnalysisResult;
import org.sonar.scanner.mediumtest.ScannerMediumTester;
import org.sonar.xoo.XooPlugin;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.scan.ModuleConfiguration;
import org.sonar.scanner.scan.filesystem.ModuleCoverageAndDuplicationExclusions;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.batch.fs.internal.SensorStrategy;
-import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.scanner.sensor.ModuleSensorExtensionDictionnary;
import org.sonar.scanner.bootstrap.ScannerPluginRepository;
-import org.sonar.scanner.sensor.ModuleSensorsExecutor;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.InputModuleHierarchy;
+import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.scanner.sensor.ModuleSensorExtensionDictionnary;
import org.sonar.scanner.sensor.ModuleSensorWrapper;
+import org.sonar.scanner.sensor.ModuleSensorsExecutor;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.scan.ProjectConfiguration;
import org.sonar.scanner.scan.filesystem.ProjectCoverageAndDuplicationExclusions;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.core.platform.PluginInfo;
import org.sonar.scanner.bootstrap.GlobalServerSettings;
import org.sonar.scanner.bootstrap.ScannerPluginRepository;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.InputModuleHierarchy;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
import org.sonar.scanner.scan.ProjectServerSettings;
import org.sonar.scanner.scan.filesystem.InputComponentStore;
" - sonar.projectKey=foo");
}
+ @Test
+ public void shouldNotDumpSQPropsInSystemProps() throws Exception {
+ logTester.setLevel(LoggerLevel.DEBUG);
+ ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder());
+ Properties props = new Properties();
+ props.setProperty(COM_FOO, "bar");
+ props.setProperty(SONAR_SKIP, "true");
+ when(system2.properties()).thenReturn(props);
+ DefaultInputModule rootModule = new DefaultInputModule(ProjectDefinition.create()
+ .setBaseDir(temp.newFolder())
+ .setWorkDir(temp.newFolder())
+ .setProperty("sonar.projectKey", "foo")
+ .setProperty(COM_FOO, "bar")
+ .setProperty(SONAR_SKIP, "true"));
+ when(store.allModules()).thenReturn(singletonList(rootModule));
+ when(hierarchy.root()).thenReturn(rootModule);
+
+ publisher.init(writer);
+
+ List<String> lines = FileUtils.readLines(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8);
+ assertThat(lines).containsExactly("Environment variables:",
+ "System properties:",
+ " - com.foo=bar",
+ "SonarQube plugins:",
+ "Global server settings:",
+ "Project server settings:",
+ "Project scanner properties:",
+ " - sonar.projectKey=foo",
+ " - sonar.skip=true");
+ }
+
+ @Test
+ public void shouldNotDumpEnvTwice() throws Exception {
+ logTester.setLevel(LoggerLevel.DEBUG);
+ ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder());
+
+ Map<String, String> env = new HashMap<>();
+ env.put(FOO, "BAR");
+ env.put(BIZ, "BAZ");
+ when(system2.envVariables()).thenReturn(env);
+ DefaultInputModule rootModule = new DefaultInputModule(ProjectDefinition.create()
+ .setBaseDir(temp.newFolder())
+ .setWorkDir(temp.newFolder())
+ .setProperty("sonar.projectKey", "foo")
+ .setProperty("env." + FOO, "BAR"));
+ when(store.allModules()).thenReturn(singletonList(rootModule));
+ when(hierarchy.root()).thenReturn(rootModule);
+ publisher.init(writer);
+
+ String content = FileUtils.readFileToString(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8);
+ assertThat(content).containsOnlyOnce(FOO);
+ assertThat(content).containsOnlyOnce(BIZ);
+ assertThat(content).containsSubsequence(BIZ, FOO);
+
+ content = FileUtils.readFileToString(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8);
+ assertThat(content).containsOnlyOnce(FOO);
+ assertThat(content).containsOnlyOnce(BIZ);
+ assertThat(content).doesNotContain("env." + FOO);
+ }
+
@Test
public void shouldNotDumpSensitiveModuleProperties() throws Exception {
ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder());
assertThat(writer.getFileStructure().analysisLog()).exists();
-
assertThat(FileUtils.readFileToString(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8)).containsSubsequence(
"sonar.aVeryLongProp=" + StringUtils.repeat("abcde", 199) + "ab...",
"sonar.projectBaseDir=" + baseDir.toString(),
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
-import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.api.batch.scm.ScmProvider;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.scanner.fs.InputModuleHierarchy;
+import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.protocol.output.ScannerReportReader;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
-import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.api.utils.DateUtils;
import org.sonar.scanner.ProjectInfo;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.protocol.output.FileStructure;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReport.Component;
import org.junit.runner.RunWith;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
-import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.api.batch.scm.ScmProvider;
import org.sonar.scanner.ProjectInfo;
import org.sonar.scanner.bootstrap.ScannerPlugin;
import org.sonar.scanner.bootstrap.ScannerPluginRepository;
import org.sonar.scanner.cpd.CpdSettings;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.InputModuleHierarchy;
+import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReportReader;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
.setRulesUpdatedAt(date.getTime())
.build()));
assertThat(metadata.getPluginsByKey()).containsOnly(entry("java", org.sonar.scanner.protocol.output.ScannerReport.Metadata.Plugin.newBuilder()
- .setKey("java")
- .setUpdatedAt(12345)
- .build()),
+ .setKey("java")
+ .setUpdatedAt(12345)
+ .build()),
entry("php", org.sonar.scanner.protocol.output.ScannerReport.Metadata.Plugin.newBuilder()
.setKey("php")
.setUpdatedAt(45678)
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.platform.Server;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.TempFolder;
import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.scanner.bootstrap.GlobalAnalysisMode;
import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.InputModuleHierarchy;
import org.sonar.scanner.scan.ScanProperties;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonarqube.ws.Ce;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.utils.MessageException;
import org.sonar.scanner.WsTestUtil;
import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonarqube.ws.Batch.WsProjectResponse;
import org.sonarqube.ws.client.HttpException;
import org.sonarqube.ws.client.WsRequest;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.scanner.fs.DefaultInputModule;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays;
import org.junit.Test;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.scanner.fs.DefaultInputModule;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.scanner.scan.filesystem.InputComponentStore;
private DefaultInputModuleHierarchy moduleHierarchy;
private InputComponentStore componentStore;
- public void createIndexer(DefaultInputProject rootProject) {
+ public void createIndexer() {
componentStore = new InputComponentStore(mock(BranchConfiguration.class));
moduleHierarchy = mock(DefaultInputModuleHierarchy.class);
indexer = new ModuleIndexer(componentStore, moduleHierarchy);
when(mod2.definition()).thenReturn(def);
when(mod3.definition()).thenReturn(def);
- createIndexer(mock(DefaultInputProject.class));
+ createIndexer();
when(moduleHierarchy.root()).thenReturn(root);
when(moduleHierarchy.children(root)).thenReturn(Arrays.asList(mod1, mod2, mod3));
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.scanner.fs.DefaultInputProject;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.utils.MessageException;
+import org.sonar.scanner.fs.DefaultInputProject;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.InputModuleHierarchy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import org.sonar.api.batch.fs.InputFile.Status;
import org.sonar.api.batch.fs.InputFile.Type;
import org.sonar.api.batch.fs.InputPath;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.api.utils.PathUtils;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.FileMetadata;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.issue.ignore.IgnoreIssuesFilter;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.fs.internal.SensorStrategy;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.fs.IndexedFile;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultIndexedFile;
+import org.sonar.scanner.fs.DefaultIndexedFile;
import org.sonar.api.config.internal.MapSettings;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputFile;
import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.repository.FileData;
import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
import org.junit.rules.ExpectedException;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.batch.scm.ScmProvider;
+import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.scanner.fs.InputModuleHierarchy;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
import org.mockito.Answers;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.AnalysisMode;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.batch.scm.ScmProvider;
import org.sonar.api.config.Configuration;
import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.log.LogTester;
import org.sonar.core.config.ScannerProperties;
+import org.sonar.scanner.fs.InputModuleHierarchy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.any;
import java.util.Optional;
import javax.annotation.Nullable;
import org.junit.Test;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.scanner.bootstrap.RawScannerProperties;
import org.sonar.scanner.ci.CiConfiguration;
+import org.sonar.scanner.fs.InputModuleHierarchy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
public void ignore_failure_if_scm_does_not_support_revisions() {
CiConfiguration ciConfiguration = mock(CiConfiguration.class);
when(ciConfiguration.getScmRevision()).thenReturn(Optional.empty());
- Map<String,String> scannerConfiguration = new HashMap<>();
+ Map<String, String> scannerConfiguration = new HashMap<>();
ScmConfiguration scmConfiguration = mock(ScmConfiguration.class, RETURNS_DEEP_STUBS);
when(scmConfiguration.provider().revisionId(any())).thenThrow(new UnsupportedOperationException("BOOM"));
InputModuleHierarchy moduleHierarchy = mock(InputModuleHierarchy.class, RETURNS_DEEP_STUBS);
private Optional<String> testGet(@Nullable String cliValue, @Nullable String ciValue, @Nullable String scmValue) {
CiConfiguration ciConfiguration = mock(CiConfiguration.class);
when(ciConfiguration.getScmRevision()).thenReturn(Optional.ofNullable(ciValue));
- Map<String,String> scannerConfiguration = new HashMap<>();
+ Map<String, String> scannerConfiguration = new HashMap<>();
scannerConfiguration.put("sonar.scm.revision", cliValue);
ScmConfiguration scmConfiguration = mock(ScmConfiguration.class, RETURNS_DEEP_STUBS);
when(scmConfiguration.provider().revisionId(any())).thenReturn(scmValue);
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.sensor;
+
+import org.junit.Before;
+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.TextPointer;
+import org.sonar.api.batch.sensor.error.NewAnalysisError;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.scanner.fs.DefaultTextPointer;
+import org.sonar.scanner.fs.TestInputFileBuilder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+public class DefaultAnalysisErrorTest {
+ private InputFile inputFile;
+ private SensorStorage storage;
+ private TextPointer textPointer;
+
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+ @Before
+ public void setUp() {
+ inputFile = new TestInputFileBuilder("module1", "src/File.java").build();
+ textPointer = new DefaultTextPointer(5, 2);
+ storage = mock(SensorStorage.class);
+ }
+
+ @Test
+ public void test_analysis_error() {
+ DefaultAnalysisError analysisError = new DefaultAnalysisError(storage);
+ analysisError.onFile(inputFile)
+ .at(textPointer)
+ .message("msg");
+
+ assertThat(analysisError.location()).isEqualTo(textPointer);
+ assertThat(analysisError.message()).isEqualTo("msg");
+ assertThat(analysisError.inputFile()).isEqualTo(inputFile);
+ }
+
+ @Test
+ public void test_save() {
+ DefaultAnalysisError analysisError = new DefaultAnalysisError(storage);
+ analysisError.onFile(inputFile).save();
+
+ verify(storage).store(analysisError);
+ verifyNoMoreInteractions(storage);
+ }
+
+ @Test
+ public void test_no_storage() {
+ exception.expect(NullPointerException.class);
+ DefaultAnalysisError analysisError = new DefaultAnalysisError();
+ analysisError.onFile(inputFile).save();
+ }
+
+ @Test
+ public void test_validation() {
+ try {
+ new DefaultAnalysisError(storage).onFile(null);
+ fail("Expected exception");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ NewAnalysisError error = new DefaultAnalysisError(storage).onFile(inputFile);
+ try {
+ error.onFile(inputFile);
+ fail("Expected exception");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ error = new DefaultAnalysisError(storage).at(textPointer);
+ try {
+ error.at(textPointer);
+ fail("Expected exception");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ try {
+ new DefaultAnalysisError(storage).save();
+ fail("Expected exception");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.sensor;
+
+import org.junit.Test;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.TestInputFileBuilder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+public class DefaultCpdTokensTest {
+ private final SensorStorage sensorStorage = mock(SensorStorage.class);
+
+ private final DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.java")
+ .setLines(2)
+ .setOriginalLineStartOffsets(new int[] {0, 50})
+ .setOriginalLineEndOffsets(new int[] {49, 100})
+ .setLastValidOffset(101)
+ .build();
+
+ @Test
+ public void save_no_tokens() {
+ DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+ .onFile(inputFile);
+
+ tokens.save();
+
+ verify(sensorStorage).store(tokens);
+
+ assertThat(tokens.inputFile()).isEqualTo(inputFile);
+ }
+
+ @Test
+ public void save_one_token() {
+ DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+ .onFile(inputFile)
+ .addToken(inputFile.newRange(1, 2, 1, 5), "foo");
+
+ tokens.save();
+
+ verify(sensorStorage).store(tokens);
+
+ assertThat(tokens.getTokenLines()).extracting("value", "startLine", "hashCode", "startUnit", "endUnit").containsExactly(tuple("foo", 1, "foo".hashCode(), 1, 1));
+ }
+
+ @Test
+ public void handle_exclusions() {
+ inputFile.setExcludedForDuplication(true);
+ DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+ .onFile(inputFile)
+ .addToken(inputFile.newRange(1, 2, 1, 5), "foo");
+
+ tokens.save();
+
+ verifyZeroInteractions(sensorStorage);
+
+ assertThat(tokens.getTokenLines()).isEmpty();
+ }
+
+ @Test
+ public void dont_save_for_test_files() {
+ DefaultInputFile testInputFile = new TestInputFileBuilder("foo", "src/Foo.java")
+ .setLines(2)
+ .setOriginalLineStartOffsets(new int[] {0, 50})
+ .setOriginalLineEndOffsets(new int[] {49, 100})
+ .setLastValidOffset(101)
+ .setType(InputFile.Type.TEST)
+ .build();
+
+ DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+ .onFile(testInputFile)
+ .addToken(testInputFile.newRange(1, 2, 1, 5), "foo");
+
+ tokens.save();
+ verifyZeroInteractions(sensorStorage);
+ assertThat(tokens.getTokenLines()).isEmpty();
+ }
+
+ @Test
+ public void save_many_tokens() {
+ DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+ .onFile(inputFile)
+ .addToken(inputFile.newRange(1, 2, 1, 5), "foo")
+ .addToken(inputFile.newRange(1, 6, 1, 10), "bar")
+ .addToken(inputFile.newRange(1, 20, 1, 25), "biz")
+ .addToken(inputFile.newRange(2, 1, 2, 10), "next");
+
+ tokens.save();
+
+ verify(sensorStorage).store(tokens);
+
+ assertThat(tokens.getTokenLines())
+ .extracting("value", "startLine", "hashCode", "startUnit", "endUnit")
+ .containsExactly(
+ tuple("foobarbiz", 1, "foobarbiz".hashCode(), 1, 3),
+ tuple("next", 2, "next".hashCode(), 4, 4));
+ }
+
+ @Test
+ public void basic_validation() {
+ SensorStorage sensorStorage = mock(SensorStorage.class);
+ DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage);
+ try {
+ tokens.save();
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Call onFile() first");
+ }
+ try {
+ tokens.addToken(inputFile.newRange(1, 2, 1, 5), "foo");
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Call onFile() first");
+ }
+ try {
+ tokens.addToken(null, "foo");
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Range should not be null");
+ }
+ try {
+ tokens.addToken(inputFile.newRange(1, 2, 1, 5), null);
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Image should not be null");
+ }
+ }
+
+ @Test
+ public void validate_tokens_order() {
+ SensorStorage sensorStorage = mock(SensorStorage.class);
+ DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+ .onFile(inputFile)
+ .addToken(inputFile.newRange(1, 6, 1, 10), "bar");
+
+ try {
+ tokens.addToken(inputFile.newRange(1, 2, 1, 5), "foo");
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Tokens of file src/Foo.java should be provided in order.\n" +
+ "Previous token: Range[from [line=1, lineOffset=6] to [line=1, lineOffset=10]]\n" +
+ "Last token: Range[from [line=1, lineOffset=2] to [line=1, lineOffset=5]]");
+ }
+ }
+
+}
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.RuleType;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.scanner.issue.DefaultIssueLocation;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import org.junit.rules.ExpectedException;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.fs.internal.DefaultTextPointer;
-import org.sonar.api.batch.fs.internal.DefaultTextRange;
import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.scanner.fs.DefaultTextPointer;
+import org.sonar.scanner.fs.DefaultTextRange;
import org.sonar.scanner.fs.TestInputFileBuilder;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.rules.ExpectedException;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.scanner.issue.DefaultIssueLocation;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.rules.ExpectedException.none;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.internal.DefaultInputDir;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.rule.RuleKey;
+import org.sonar.scanner.fs.DefaultInputDir;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.scanner.issue.DefaultIssue;
+import org.sonar.scanner.issue.DefaultIssueLocation;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.measures.CoreMetrics;
+import org.sonar.scanner.fs.AbstractProjectOrModule;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.fs.TestInputFileBuilder;
import static org.assertj.core.api.Assertions.assertThat;
import org.mockito.ArgumentCaptor;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputDir;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.batch.sensor.code.internal.DefaultSignificantCode;
import org.sonar.api.batch.sensor.highlighting.TypeOfText;
import org.sonar.api.batch.sensor.issue.ExternalIssue;
import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.core.metric.ScannerMetrics;
import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
+import org.sonar.scanner.fs.DefaultInputDir;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.scanner.issue.DefaultIssue;
+import org.sonar.scanner.issue.DefaultIssueLocation;
import org.sonar.scanner.issue.IssuePublisher;
import org.sonar.scanner.protocol.output.FileStructure;
import org.sonar.scanner.protocol.output.ScannerReport;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.sensor;
+
+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.sensor.internal.SensorStorage;
+import org.sonar.scanner.fs.TestInputFileBuilder;
+
+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));
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.scanner.sensor;
+
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+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.TextRange;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.scanner.sensor.DefaultSymbolTable;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class DefaultSymbolTableTest {
+
+ private static final InputFile INPUT_FILE = new TestInputFileBuilder("foo", "src/Foo.java")
+ .setLines(2)
+ .setOriginalLineStartOffsets(new int[] {0, 50})
+ .setOriginalLineEndOffsets(new int[] {49, 100})
+ .setLastValidOffset(101)
+ .build();
+
+ private Map<TextRange, Set<TextRange>> referencesPerSymbol;
+
+ @Rule
+ public ExpectedException throwable = ExpectedException.none();
+
+ @Before
+ public void setUpSampleSymbols() {
+
+ DefaultSymbolTable symbolTableBuilder = new DefaultSymbolTable(mock(SensorStorage.class))
+ .onFile(INPUT_FILE);
+ symbolTableBuilder
+ .newSymbol(0, 10)
+ .newReference(12, 15)
+ .newReference(2, 10, 2, 15);
+
+ symbolTableBuilder.newSymbol(1, 12, 1, 15).newReference(52, 55);
+
+ symbolTableBuilder.save();
+
+ referencesPerSymbol = symbolTableBuilder.getReferencesBySymbol();
+ }
+
+ @Test
+ public void should_register_symbols() {
+ assertThat(referencesPerSymbol).hasSize(2);
+ }
+
+}
import org.sonar.api.SonarQubeSide;
import org.sonar.api.SonarRuntime;
import org.sonar.api.batch.fs.InputModule;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.measure.MetricFinder;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.utils.Version;
import org.sonar.scanner.fs.DefaultFileSystem;
+import org.sonar.scanner.fs.DefaultInputProject;
import org.sonar.scanner.rule.ActiveRulesBuilder;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.DefaultTextPointer;
-import org.sonar.scanner.fs.DefaultFileSystem;
-import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.error.AnalysisError;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.RuleType;
+import org.sonar.scanner.fs.DefaultFileSystem;
+import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.fs.DefaultTextPointer;
+import org.sonar.scanner.fs.TestInputFileBuilder;
import org.sonar.scanner.rule.ActiveRulesBuilder;
import org.sonar.scanner.rule.NewActiveRule;