1
+
//! An example of using syntect for code analysis.
2
+
//! Basically a fancy lines of code count program that works
3
+
//! for all languages Sublime Text supports and also counts things
4
+
//! like number of functions and number of types defined.
5
+
//!
6
+
//! Another thing it does that other line count programs can't always
7
+
//! do is properly count comments in embedded syntaxes. For example
8
+
//! JS, CSS and Ruby comments embedded in ERB files.
1
9
extern crate syntect;
2
10
extern crate walkdir;
3
11
use syntect::parsing::{SyntaxSet, ParseState, ScopeStackOp, ScopeStack};
@@ -13,6 +21,7 @@ use std::str::FromStr;
13
21
#[derive(Debug)]
14
22
struct Selectors {
15
23
comment: ScopeSelector,
24
+
doc_comment: ScopeSelectors,
16
25
function: ScopeSelector,
17
26
types: ScopeSelectors,
18
27
}
@@ -21,6 +30,7 @@ impl Default for Selectors {
21
30
fn default() -> Selectors {
22
31
Selectors {
23
32
comment: ScopeSelector::from_str("comment - comment.block.attribute").unwrap(),
33
+
doc_comment: ScopeSelectors::from_str("comment.line.documentation, comment.block.documentation").unwrap(),
24
34
function: ScopeSelector::from_str("entity.name.function").unwrap(),
25
35
types: ScopeSelectors::from_str("entity.name.class, entity.name.struct, entity.name.enum, entity.name.type").unwrap(),
26
36
}
@@ -38,7 +48,9 @@ struct Stats {
38
48
code_lines: usize,
39
49
comment_lines: usize,
40
50
comment_chars: usize,
41
-
comment_tokens: usize,
51
+
comment_words: usize,
52
+
doc_comment_lines: usize,
53
+
doc_comment_words: usize,
42
54
}
43
55
44
56
fn print_stats(stats: &Stats) {
@@ -55,7 +67,9 @@ fn print_stats(stats: &Stats) {
55
67
println!("Comment lines (comment but no code): {:>6}", stats.comment_lines);
56
68
println!("Blank lines (lines-blank-comment): {:>6}", stats.lines-stats.code_lines-stats.comment_lines);
57
69
println!("");
58
-
println!("Number of comment tokens: {:>6}", stats.comment_tokens);
70
+
println!("Lines with a documentation comment: {:>6}", stats.doc_comment_lines);
71
+
println!("Total words written in doc comments: {:>6}", stats.doc_comment_words);
72
+
println!("Total words written in all comments: {:>6}", stats.comment_words);
59
73
println!("Characters of comment: {:>6}", stats.comment_chars);
60
74
}
61
75
@@ -71,15 +85,21 @@ fn count_line(ops: &[(usize, ScopeStackOp)], line: &str, stats: &mut Stats) {
71
85
72
86
let mut stack = ScopeStack::new();
73
87
let mut line_has_comment = false;
88
+
let mut line_has_doc_comment = false;
74
89
let mut line_has_code = false;
75
90
for (s, op) in ScopeRegionIterator::new(&ops, line) {
76
91
stack.apply(op);
77
92
if s.is_empty() { // in this case we don't care about blank tokens
78
93
continue;
79
94
}
80
95
if stats.selectors.comment.does_match(stack.as_slice()).is_some() {
96
+
let words = s.split_whitespace().filter(|w| w.chars().all(|c| c.is_alphanumeric() || c == '.' || c == '\'')).count();
97
+
if stats.selectors.doc_comment.does_match(stack.as_slice()).is_some() {
98
+
line_has_doc_comment = true;
99
+
stats.doc_comment_words += words;
100
+
}
81
101
stats.comment_chars += s.len();
82
-
stats.comment_tokens += 1;
102
+
stats.comment_words += words;
83
103
line_has_comment = true;
84
104
} else if !s.chars().all(|c| c.is_whitespace()) {
85
105
line_has_code = true;
@@ -94,6 +114,9 @@ fn count_line(ops: &[(usize, ScopeStackOp)], line: &str, stats: &mut Stats) {
94
114
if line_has_comment && !line_has_code {
95
115
stats.comment_lines += 1;
96
116
}
117
+
if line_has_doc_comment {
118
+
stats.doc_comment_lines += 1;
119
+
}
97
120
if line_has_code {
98
121
stats.code_lines += 1;
99
122
}
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4