1、统计粒度
能够统计包括:代码行数、注释、空行、总行数。
2、适用的编程语言
目前只测试过Java,其它编程语言暂时未知。
3、代码简析
代码行统计需要考虑的因素包括字符串匹配、编程语言本身的字符串,后者非常重要,往往导致难以发现的bug。该程序的核心在于递归的使用和栈的构造,需要深刻理解递归的原因和栈的几种状态。
4、参考程序
程序一:http://wenku.baidu.com/view/2a3dcbe3524de518964b7dec.html
程序二:http://www.downxia.com/downinfo/11131.html
程序三:https://code.google.com/p/boomworks/wiki/SourceCounterCN 版本:3.5.33.73 - Boom 2011-6-22
5、程序源代码
1 /** 2 * LOCStatistics application 3 * @author 邝翼飞 4 * @version 1.0 5 * @date 2015/1/8 6 */ 7 8 import java.io.BufferedReader; 9 import java.io.File; 10 import java.io.FileReader; 11 import java.util.Stack; 12 13 public class LOCStatistics { 14 private long numCommentLine = 0; 15 private long numWhiteLine = 0; 16 private long numCodeLine = 0; 17 private long numTotalLine = 0; 18 private int numCompilationUnit = 0; 19 private boolean isCommenting = false; 20 21 public LOCStatistics(){} 22 23 public static void main(String[] args) { 24 String SRC_DIR = "D:\\InsightViewerTestCases\\MethodSimilarityTest"; 25 LOCStatistics loc = new LOCStatistics(); 26 if(loc.generateResult(new File(SRC_DIR))) { 27 System.out.println("numCommentLine:\t" + loc.numCommentLine); 28 System.out.println("numWhiteLine:\t" + loc.numWhiteLine); 29 System.out.println("numCodeLine:\t" + loc.numCodeLine); 30 System.out.println("numTotalLine:\t" + loc.numTotalLine); 31 System.out.println("numCompilationUnit:\t" + loc.numCompilationUnit); 32 } 33 else { 34 System.out.println("Failed to generate results!"); 35 } 36 } 37 38 public boolean generateResult(File dir) { 39 if(dir==null || !dir.exists() || !dir.isDirectory()) { 40 return false; 41 } 42 isCommenting = false; 43 File[] files = dir.listFiles(); 44 for(int i = 0; i < files.length; i++) { 45 if (files[i].isDirectory()) { 46 generateResult(files[i]); 47 } 48 else { 49 try { 50 if (files[i].getName().endsWith(".java")) { 51 numCompilationUnit++; 52 BufferedReader br = new BufferedReader(new FileReader(files[i])); 53 String line = br.readLine(); 54 while (line != null) { 55 numTotalLine++; 56 LineProperty lineProperty = extractLineProperty(line); 57 if(lineProperty.hasComment) { 58 numCommentLine++; 59 } 60 if(lineProperty.hasCode) { 61 numCodeLine++; 62 } 63 if(!lineProperty.hasComment && !lineProperty.hasCode) { 64 numWhiteLine++; 65 } 66 line = br.readLine(); 67 } 68 br.close(); 69 } 70 } 71 catch (Exception e) { 72 e.printStackTrace(); 73 return false; 74 } 75 } 76 } 77 return true; 78 } 79 80 private LineProperty extractLineProperty(String line) { 81 line = line.trim(); 82 String subLine = null; 83 LineProperty lineProperty = new LineProperty(); 84 boolean hasCode = false; 85 boolean hasComment = false; 86 if(line.length() == 0) { 87 return lineProperty; 88 } 89 else if(isCommenting == true) { 90 hasComment = true; 91 if(line.matches(".*\\*/.*")) { 92 isCommenting = false; 93 int index = line.indexOf("*/"); 94 if(line.length() == index + 2) { 95 hasCode = false; 96 } 97 else { 98 subLine = line.substring(index + 2); 99 lineProperty = extractLineProperty(subLine); 100 hasCode = lineProperty.hasCode; 101 } 102 } 103 else { 104 hasCode = false; 105 } 106 } 107 else if(line.startsWith("//")) { 108 hasComment = true; 109 } 110 else if(line.startsWith("/*") && !line.matches(".{2,}\\*/.*")){ 111 hasCode = false; 112 hasComment = true; 113 isCommenting = true; 114 } 115 else if(line.startsWith("/*") && line.matches(".{2,}\\*/.*")) { 116 if(!line.matches(".{2,}\\*/.+")) { 117 hasCode = false; 118 hasComment = true; 119 } 120 else { 121 String tmps = line.substring(2); 122 subLine = tmps.substring(tmps.indexOf("*/")+2);/*/test*/ 123 lineProperty = extractLineProperty(subLine); 124 hasCode = lineProperty.hasCode; 125 hasComment = true; 126 } 127 } 128 else { 129 hasCode = true; 130 int x, y; 131 x = line.indexOf("//"); 132 y = line.indexOf("/*"); 133 if(x==-1 && y==-1) { 134 hasComment = false; 135 } 136 else { 137 Stack<Character> stack = new Stack<Character>(); 138 int count = 0; 139 for(Character ch: line.toCharArray()) { 140 count++; 141 // 首先判断上一个字符是否是转义符 \ 若是,则抛弃该字符 142 if(!stack.isEmpty() && stack.peek()==‘\\‘) { 143 stack.pop(); 144 continue; 145 } 146 if(ch != ‘"‘){ 147 if(ch == ‘\\‘) { 148 stack.push(ch); 149 } 150 else if(!stack.isEmpty() && stack.peek()==‘"‘) { 151 continue; 152 } 153 else if(ch==‘*‘ || ch==‘/‘) { 154 if (stack.isEmpty()) { 155 stack.push(ch); 156 } 157 else { 158 if(stack.peek() == ‘/‘) { 159 break; 160 } 161 else { 162 stack.push(ch); 163 } 164 } 165 } 166 } 167 else { 168 if(stack.isEmpty()) { 169 stack.push(ch); 170 } 171 else { 172 char tmp = stack.peek(); 173 while(tmp!=‘"‘ && !stack.isEmpty()) { 174 tmp = stack.pop(); 175 } 176 if(tmp!=‘"‘ && stack.isEmpty()) { 177 stack.push(ch); 178 } 179 else { 180 while(!stack.isEmpty()) { 181 stack.pop(); 182 } 183 } 184 } 185 } 186 } 187 if(count <= line.length()) { 188 subLine = line.substring(count-2); 189 lineProperty = extractLineProperty(subLine); 190 hasComment = lineProperty.hasComment; 191 } 192 else { 193 hasComment = false; 194 } 195 } 196 } 197 lineProperty.hasCode = hasCode; 198 lineProperty.hasComment = hasComment; 199 return lineProperty; 200 } 201 202 public long getNumCommentLine() { 203 return numCommentLine; 204 } 205 206 public void setNumCommentLine(long numCommentLine) { 207 this.numCommentLine = numCommentLine; 208 } 209 210 public long getNumWhiteLine() { 211 return numWhiteLine; 212 } 213 214 public void setNumWhiteLine(long numWhiteLine) { 215 this.numWhiteLine = numWhiteLine; 216 } 217 218 public long getNumCodeLine() { 219 return numCodeLine; 220 } 221 222 public void setNumCodeLine(long numCodeLine) { 223 this.numCodeLine = numCodeLine; 224 } 225 226 public long getNumTotalLine() { 227 return numTotalLine; 228 } 229 230 public void setNumTotalLine(long numTotalLine) { 231 this.numTotalLine = numTotalLine; 232 } 233 234 public int getNumCompilationUnit() { 235 return numCompilationUnit; 236 } 237 238 public void setNumCompilationUnit(int numCompilationUnit) { 239 this.numCompilationUnit = numCompilationUnit; 240 } 241 } 242 243 class LineProperty 244 { 245 public boolean hasCode = false; 246 public boolean hasComment = false; 247 public LineProperty() { 248 this(false, false); 249 } 250 public LineProperty(boolean hasCode, boolean hasComment) { 251 this.hasCode = hasCode; 252 this.hasComment = hasComment; 253 } 254 }
6、测试用例
1 import java.util.ArrayList; 2 import java.util.List; 3 4 @SuppressWarnings("rawtypes") 5 public class MethodSimilarityTest { 6 7 public void overLoad(AA a){} 8 public void overLoad(double x){} 9 public void overLoad(List list){} 10 11 12 13 public static void main(String[] args) { 14 // new MethodSimilarityTest().overLoad((new BB()).getAA()); 15 // new MethodSimilarityTest().overLoad(1); 16 new MethodSimilarityTest().overLoad(new ArrayList()); 17 /** // sfska */ String s = "/*dls"; // fsdafl 18 /** // sfska */ 19 s = "/*dls"; 20 } 21 22 } 23 24 class AA 25 { 26 public AA getAA(){return new AA();} 27 public void c(int b){} 28 } 29 class BB extends AA 30 { 31 public BB(){this(1);this.c(1); } 32 public BB(int x){} 33 }
时间: 2024-11-11 06:55:44