All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonarsource.sonarlint.core.container.analysis.filesystem.SonarLintInputFile Maven / Gradle / Ivy

/*
 * SonarLint Core - Implementation
 * Copyright (C) 2016-2021 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.sonarsource.sonarlint.core.container.analysis.filesystem;

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.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
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.utils.PathUtils;
import org.sonarsource.sonarlint.core.client.api.common.Language;
import org.sonarsource.sonarlint.core.client.api.common.analysis.ClientInputFile;
import org.sonarsource.sonarlint.core.container.analysis.filesystem.FileMetadata.Metadata;

public class SonarLintInputFile implements InputFile {

  private final ClientInputFile clientInputFile;
  private final String relativePath;
  private Language language;
  private Type type;
  private Metadata metadata;
  private final Function metadataGenerator;
  private boolean ignoreAllIssues;
  private final Set noSonarLines = new HashSet<>();
  private Collection ignoreIssuesOnlineRanges;

  public SonarLintInputFile(ClientInputFile clientInputFile, Function metadataGenerator) {
    this.clientInputFile = clientInputFile;
    this.metadataGenerator = metadataGenerator;
    this.relativePath = PathUtils.sanitize(clientInputFile.relativePath());
  }

  public void checkMetadata() {
    if (metadata == null) {
      this.metadata = metadataGenerator.apply(this);
    }
  }

  public ClientInputFile getClientInputFile() {
    return clientInputFile;
  }

  @Override
  public String relativePath() {
    return relativePath;
  }

  public SonarLintInputFile setLanguage(@Nullable Language language) {
    this.language = language;
    return this;
  }

  public SonarLintInputFile setType(Type type) {
    this.type = type;
    return this;
  }

  @CheckForNull
  @Override
  public String language() {
    return language != null ? language.getLanguageKey() : null;
  }

  @CheckForNull
  public Language getLanguage() {
    return language;
  }

  @Override
  public Type type() {
    return type;
  }

  /**
   * @deprecated avoid calling this method if possible, since it may require to create a temporary copy of the file
   */
  @Deprecated
  @Override
  public String absolutePath() {
    return PathUtils.sanitize(clientInputFile.getPath());
  }

  /**
   * @deprecated avoid calling this method if possible, since it may require to create a temporary copy of the file
   */
  @Deprecated
  @Override
  public File file() {
    return path().toFile();
  }

  /**
   * @deprecated avoid calling this method if possible, since it may require to create a temporary copy of the file
   */
  @Deprecated
  @Override
  public Path path() {
    return Paths.get(clientInputFile.getPath());
  }

  @Override
  public InputStream inputStream() throws IOException {
    return clientInputFile.inputStream();
  }

  @Override
  public String contents() throws IOException {
    return clientInputFile.contents();
  }

  @Override
  public Status status() {
    return Status.ADDED;
  }

  /**
   * Component key.
   */
  @Override
  public String key() {
    return uri().toString();
  }

  @Override
  public URI uri() {
    return clientInputFile.uri();
  }

  @Override
  public Charset charset() {
    Charset charset = clientInputFile.getCharset();
    return charset != null ? charset : Charset.defaultCharset();
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }

    if (!(o instanceof SonarLintInputFile)) {
      return false;
    }

    SonarLintInputFile that = (SonarLintInputFile) o;
    return uri().equals(that.uri());
  }

  @Override
  public int hashCode() {
    return uri().hashCode();
  }

  @Override
  public String toString() {
    return "[uri=" + uri() + "]";
  }

  @Override
  public boolean isFile() {
    return true;
  }

  @Override
  public String filename() {
    return Paths.get(relativePath).getFileName().toString();
  }

  @Override
  public int lines() {
    checkMetadata();
    return metadata.lines();
  }

  @Override
  public boolean isEmpty() {
    checkMetadata();
    return metadata.lastValidOffset() == 0;
  }

  @Override
  public TextPointer newPointer(int line, int lineOffset) {
    checkMetadata();
    return new DefaultTextPointer(line, lineOffset);
  }

  @Override
  public TextRange newRange(TextPointer start, TextPointer end) {
    checkMetadata();
    return newRangeValidPointers(start, end);
  }

  @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);
  }

  @Override
  public TextRange selectLine(int line) {
    checkMetadata();
    TextPointer startPointer = newPointer(line, 0);
    TextPointer endPointer = newPointer(line, lineLength(line));
    return newRangeValidPointers(startPointer, endPointer);
  }

  private static TextRange newRangeValidPointers(TextPointer start, TextPointer end) {
    return new DefaultTextRange(start, end);
  }

  private int lineLength(int line) {
    return lastValidGlobalOffsetForLine(line) - metadata.originalLineOffsets()[line - 1];
  }

  private int lastValidGlobalOffsetForLine(int line) {
    return line < this.metadata.lines() ? (metadata.originalLineOffsets()[line] - 1) : metadata.lastValidOffset();
  }

  public void noSonarAt(Set noSonarLines) {
    this.noSonarLines.addAll(noSonarLines);
  }

  public boolean hasNoSonarAt(int line) {
    return this.noSonarLines.contains(line);
  }

  public boolean isIgnoreAllIssues() {
    checkMetadata();
    return ignoreAllIssues;
  }

  public void setIgnoreAllIssues(boolean ignoreAllIssues) {
    this.ignoreAllIssues = ignoreAllIssues;
  }

  public void addIgnoreIssuesOnLineRanges(Collection lineRanges) {
    if (this.ignoreIssuesOnlineRanges == null) {
      this.ignoreIssuesOnlineRanges = new ArrayList<>();
    }
    this.ignoreIssuesOnlineRanges.addAll(lineRanges);
  }

  public boolean isIgnoreAllIssuesOnLine(@Nullable Integer line) {
    checkMetadata();
    if (line == null || ignoreIssuesOnlineRanges == null) {
      return false;
    }
    return ignoreIssuesOnlineRanges.stream().anyMatch(r -> r[0] <= line && line <= r[1]);
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy