001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2011 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar 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 * Sonar 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
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020 package org.sonar.squid.text;
021
022 import org.sonar.squid.measures.Metric;
023 import org.sonar.squid.recognizer.CodeRecognizer;
024
025 import java.io.Reader;
026 import java.util.ArrayList;
027 import java.util.HashSet;
028 import java.util.List;
029 import java.util.Set;
030
031 public class Source {
032
033 private List<Line> lines = new ArrayList<Line>();
034 private CodeRecognizer codeRecognizer;
035 private Set<Integer> noSonarTagLines = new HashSet<Integer>();
036
037 public Source(Reader reader, CodeRecognizer codeRecognizer, String... additionalSingleLineCommentFlag) {
038 this.codeRecognizer = codeRecognizer;
039 LinesFactory linesFactory = new LinesFactory(reader, additionalSingleLineCommentFlag);
040 lines = linesFactory.getLines();
041 processLines();
042 }
043
044 public Source(String[] stringLines, CodeRecognizer codeRecognizer) {
045 this(new StringArrayReader(stringLines), codeRecognizer);
046 }
047
048 private void processLines() {
049 for (Line line : lines) {
050 computeBlankLine(line);
051 computeHeaderCommentLine(line);
052 computeCommentLine(line);
053 computeCommentBlankLine(line);
054 computeLineOfCode(line);
055 computeNoSonarTag(line);
056 line.deleteLineContent();
057 }
058 }
059
060 private void computeNoSonarTag(Line line) {
061 if (line.isThereNoSonarTag()) {
062 noSonarTagLines.add(line.getLineIndex());
063 }
064 }
065
066 private void computeLineOfCode(Line line) {
067 if (line.isThereCode()) {
068 line.setMeasure(Metric.LINES_OF_CODE, 1);
069 }
070 }
071
072 private void computeHeaderCommentLine(Line line) {
073 if (line.isThereComment() && !line.isThereBlankComment() && line.isThereLicenseHeaderComment()) {
074 line.setMeasure(Metric.HEADER_COMMENT_LINES, 1);
075 }
076 }
077
078 private void computeCommentLine(Line line) {
079 if (line.isThereComment() && !line.isThereBlankComment()) {
080 if (line.isThereJavadoc() || line.isThereLicenseHeaderComment()) {
081 line.setMeasure(Metric.COMMENT_LINES, 1);
082 return;
083 }
084
085 boolean isCommentedOutCode = codeRecognizer.isLineOfCode(line.getComment());
086 if (!isCommentedOutCode) {
087 line.setMeasure(Metric.COMMENT_LINES, 1);
088 } else {
089 line.setMeasure(Metric.COMMENTED_OUT_CODE_LINES, 1);
090 }
091 }
092 }
093
094 private void computeBlankLine(Line line) {
095 if (line.isBlank()) {
096 line.setMeasure(Metric.BLANK_LINES, 1);
097 }
098 }
099
100 private void computeCommentBlankLine(Line line) {
101 if (line.isThereBlankComment()) {
102 line.setMeasure(Metric.COMMENT_BLANK_LINES, 1);
103 }
104 }
105
106 public int getMeasure(Metric metric) {
107 return getMeasure(metric, 1, lines.size());
108 }
109
110 public int getMeasure(Metric metric, int fromLine, int toLine) {
111 if (toLine > lines.size()) {
112 throw new IllegalStateException("There are only " + lines.size() + " lines in the file and you're trying to reach line " + toLine);
113 }
114 if (fromLine < 1) {
115 throw new IllegalStateException("Line index starts from 1 and not from " + fromLine);
116 }
117
118 int measure = 0;
119 for (int index = fromLine; index < toLine + 1; index++) {
120 measure += lines.get(index - 1).getInt(metric);
121 }
122 return measure;
123 }
124
125 public Set<Integer> getNoSonarTagLines() {
126 return noSonarTagLines;
127 }
128 }