8cdc3b2ed829e3c5737913d640a2ba19036dfb5d
[JavaForFun] /
1 /*
2  * SonarQube JavaScript Plugin
3  * Copyright (C) 2011-2016 SonarSource SA
4  * mailto:contact AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package de.example.plugins.custom.javascript.minify;
21
22 import java.io.BufferedReader;
23 import java.io.File;
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;
29
30 /**
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>).
37  */
38 class AverageLineLengthCalculator {
39
40   private File file;
41
42   private boolean isAtFirstLine = true;
43
44   private boolean isInHeaderComment = false;
45
46   private boolean isClike = false;
47
48   private Charset encoding;
49
50   public AverageLineLengthCalculator(File file, Charset encoding) {
51     this.file = file;
52     this.encoding = encoding;
53   }
54
55   public int getAverageLineLength() {
56     long nbLines = 0;
57     long nbCharacters = 0;
58
59     try (BufferedReader reader = getReader(file)) {
60       String line;
61       while ((line = reader.readLine()) != null) {
62         if (!isLineInHeaderComment(line)) {
63           nbLines++;
64           nbCharacters += line.length();
65         }
66       }
67     } catch (IOException e) {
68       handleException(e, file);
69     }
70
71     return nbLines > 0 ? (int) (nbCharacters / nbLines) : 0;
72   }
73
74   public boolean isLineInHeaderComment(String line) {
75     String trimmedLine = line.trim();
76     if (isAtFirstLine) {
77       isAtFirstLine = false;
78       return isFirstLineInHeaderComment(trimmedLine);
79     } else if (isInHeaderComment) {
80       return isSubsequentLineInHeaderComment(trimmedLine);
81     }
82     return false;
83   }
84
85   private boolean isFirstLineInHeaderComment(String line) {
86     if (line.startsWith("/*")) {
87       isClike = true;
88       isInHeaderComment = !line.endsWith("*/");
89       return true;
90     } else if (line.startsWith("//")) {
91       isClike = false;
92       isInHeaderComment = true;
93       return true;
94     }
95     return false;
96   }
97
98   private boolean isSubsequentLineInHeaderComment(String line) {
99     if (isClike) {
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;
105         return false;
106       }
107       return true;
108     } else {
109       if (line.startsWith("//")) {
110         return true;
111       } else {
112         isInHeaderComment = false;
113         return false;
114       }
115     }
116   }
117
118   private BufferedReader getReader(File file) throws IOException {
119     return new BufferedReader(new InputStreamReader(new FileInputStream(file), encoding));
120   }
121
122   private static void handleException(IOException e, File file) {
123     throw new AnalysisException("Unable to analyse file: " + file.getAbsolutePath(), e);
124   }
125
126 }