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