2 * SonarQube JavaScript Plugin
3 * Copyright (C) 2011-2016 SonarSource SA
4 * mailto:contact AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package de.example.plugins.custom.javascript.minify;
22 import java.io.BufferedReader;
24 import java.io.FileInputStream;
25 import java.io.IOException;
26 import java.io.InputStreamReader;
27 import java.nio.charset.Charset;
28 import org.sonar.squidbridge.api.AnalysisException;
31 * An instance of this class computes the average line length of file.
32 * Before making the computation, it discards all lines which are part
33 * of the header comment.
34 * The header comment is a comment which starts on the first line of the file.
35 * It may be either a C-like comment (i.e., it starts with <code>"/*"</code>) or a C++-like comment
36 * (i.e., it starts with <code>"//"</code>).
38 class AverageLineLengthCalculator {
42 private boolean isAtFirstLine = true;
44 private boolean isInHeaderComment = false;
46 private boolean isClike = false;
48 private Charset encoding;
50 public AverageLineLengthCalculator(File file, Charset encoding) {
52 this.encoding = encoding;
55 public int getAverageLineLength() {
57 long nbCharacters = 0;
59 try (BufferedReader reader = getReader(file)) {
61 while ((line = reader.readLine()) != null) {
62 if (!isLineInHeaderComment(line)) {
64 nbCharacters += line.length();
67 } catch (IOException e) {
68 handleException(e, file);
71 return nbLines > 0 ? (int) (nbCharacters / nbLines) : 0;
74 public boolean isLineInHeaderComment(String line) {
75 String trimmedLine = line.trim();
77 isAtFirstLine = false;
78 return isFirstLineInHeaderComment(trimmedLine);
79 } else if (isInHeaderComment) {
80 return isSubsequentLineInHeaderComment(trimmedLine);
85 private boolean isFirstLineInHeaderComment(String line) {
86 if (line.startsWith("/*")) {
88 isInHeaderComment = !line.endsWith("*/");
90 } else if (line.startsWith("//")) {
92 isInHeaderComment = true;
98 private boolean isSubsequentLineInHeaderComment(String line) {
100 if (line.endsWith("*/")) {
101 isInHeaderComment = false;
102 } else if (line.contains("*/")) {
103 // case of */ followed with something, possibly a long minified line
104 isInHeaderComment = false;
109 if (line.startsWith("//")) {
112 isInHeaderComment = false;
118 private BufferedReader getReader(File file) throws IOException {
119 return new BufferedReader(new InputStreamReader(new FileInputStream(file), encoding));
122 private static void handleException(IOException e, File file) {
123 throw new AnalysisException("Unable to analyse file: " + file.getAbsolutePath(), e);