001/*
002 * SonarQube
003 * Copyright (C) 2009-2017 SonarSource SA
004 * mailto:info AT sonarsource DOT com
005 *
006 * This program is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019 */
020package org.sonar.api.batch.fs;
021
022import java.io.File;
023import java.io.IOException;
024import java.io.InputStream;
025import java.nio.charset.Charset;
026import java.nio.file.Files;
027import java.nio.file.Path;
028import javax.annotation.CheckForNull;
029import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
030
031/**
032 * This layer over {@link java.io.File} adds information for code analyzers.
033 * For unit testing purpose, use {@link TestInputFileBuilder} and initialize
034 * the needed fields:
035 * 
036 * <pre>
037 *   new TestInputFileBuilder("moduleKey", "relative/path/from/module/baseDir.java")
038 *     .setModuleBaseDir(path)
039 *     .build();
040 * </pre>
041 *
042 * @since 4.2
043 */
044public interface InputFile extends IndexedFile {
045
046  enum Type {
047    MAIN, TEST
048  }
049
050  /** 
051   * Status regarding previous analysis
052   */
053  enum Status {
054    SAME, CHANGED, ADDED
055  }
056
057  /**
058   * Path relative to module base directory. Path is unique and identifies file
059   * within given <code>{@link FileSystem}</code>. File separator is the forward
060   * slash ('/'), even on Microsoft Windows.
061   * <br>
062   * Returns <code>src/main/java/com/Foo.java</code> if module base dir is
063   * <code>/path/to/module</code> and if file is
064   * <code>/path/to/module/src/main/java/com/Foo.java</code>.
065   * <br>
066   * Relative path is not null and is normalized ('foo/../foo' is replaced by 'foo').
067   */
068  @Override
069  String relativePath();
070
071  /**
072   * Normalized absolute path. File separator is forward slash ('/'), even on Microsoft Windows.
073   * <br>
074   * This is not canonical path. Symbolic links are not resolved. For example if /project/src links
075   * to /tmp/src and basedir is /project, then this method returns /project/src/index.php. Use
076   * {@code file().getCanonicalPath()} to resolve symbolic link.
077   */
078  @Override
079  String absolutePath();
080
081  /**
082   * The underlying absolute {@link java.io.File}. It should not be used to read the file in the filesystem.
083   * @see #contents()
084   * @see #inputStream()
085   */
086  @Override
087  File file();
088
089  /**
090   * The underlying absolute {@link Path}.
091   * It should not be used to read the file in the filesystem.
092   * @see #contents()
093   * @see #inputStream()
094   * @since 5.1
095   */
096  @Override
097  Path path();
098
099  /**
100   * Language, for example "java" or "php". Can be null if indexation of all files is enabled and no language claims to support the file.
101   */
102  @CheckForNull
103  @Override
104  String language();
105
106  /**
107   * Does it contain main or test code ?
108   */
109  @Override
110  Type type();
111
112  /**
113   * Creates a stream of the file's contents. Depending on the runtime context, the source might be a file in a physical or virtual filesystem.
114   * Typically, it won't be buffered. <b>The stream must be closed by the caller</b>.
115   * Note that there is a default implementation.
116   * @since 6.2
117   */
118  @Override
119  default InputStream inputStream() throws IOException {
120    return Files.newInputStream(path());
121  }
122
123  /**
124   * Fetches the entire contents of the file, decoding with the {@link #charset}.
125   * Note that there is a default implementation.
126   * @since 6.2
127   */
128  default String contents() throws IOException {
129    return new String(Files.readAllBytes(path()), charset());
130  }
131
132  /**
133   * Status regarding previous analysis
134   */
135  Status status();
136
137  /**
138   * Number of physical lines. This method supports all end-of-line characters. Formula is (number of line break + 1). 
139   * <p>
140   * Returns 1 if the file is empty.
141   * <br> 
142   * Returns 2 for <tt>foo\nbar</tt>. 
143   * <br>
144   * Returns 3 for <tt>foo\nbar\n</tt>.
145   */
146  int lines();
147
148  /**
149   * Check if the file content is empty (ignore potential BOM).
150   * @since 5.2
151   */
152  boolean isEmpty();
153
154  /**
155   * Returns a {@link TextPointer} in the given file.
156   * @param line Line of the pointer. Start at 1.
157   * @param lineOffset Offset in the line. Start at 0.
158   * @throws IllegalArgumentException if line or offset is not valid for the given file.
159   * @since 5.2
160   */
161  TextPointer newPointer(int line, int lineOffset);
162
163  /**
164   * Returns a {@link TextRange} in the given file.
165   * @param start start pointer
166   * @param end end pointer
167   * @throws IllegalArgumentException if start or stop pointers are not valid for the given file.
168   * @since 5.2
169   */
170  TextRange newRange(TextPointer start, TextPointer end);
171
172  /**
173   * Returns a {@link TextRange} in the given file.
174   * <ul>
175   * <li><code>newRange(1, 0, 1, 1)</code> selects the first character at line 1</li>
176   * <li><code>newRange(1, 0, 1, 10)</code> selects the 10 first characters at line 1</li>
177   * </ul>
178   * @throws IllegalArgumentException if start or stop positions are not valid for the given file.
179   * @since 5.2
180   */
181  TextRange newRange(int startLine, int startLineOffset, int endLine, int endLineOffset);
182
183  /**
184   * Returns a {@link TextRange} in the given file that select the full line.
185   * @param line Start at 1.
186   * @throws IllegalArgumentException if line is not valid for the given file.
187   * @since 5.2
188   */
189  TextRange selectLine(int line);
190
191  /**
192   * Charset to be used to decode this specific file.
193   * @since 6.0
194   */
195  Charset charset();
196}