Skip to content

Commit 34cf6e1

Browse files
authored
Merge pull request #122 from SpiceCodeCLI/separate-analyze-file
Separate analyze file
2 parents 71c9d9b + 46a166b commit 34cf6e1

8 files changed

Lines changed: 118 additions & 103 deletions

File tree

spice/analyze.py

Lines changed: 27 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,9 @@
11
import os
22

3-
# this is the universal token, used by all lexers to know what to output
4-
from lexers.token import TokenType
5-
6-
# these are the individual lexers for all languages we support
7-
from lexers.ruby.rubylexer import RubyLexer
8-
from lexers.python.pythonlexer import PythonLexer
9-
from lexers.javascript.javascriptlexer import JavaScriptLexer
10-
from lexers.golang.golexer import GoLexer
11-
123
# gustavo testando alguma coisa
4+
from spice.analyzers.identation import detect_indentation
5+
136

14-
from spice.identation import detect_indentation
15-
16-
# this will read the file extension and return the correct lexer
17-
def get_lexer_for_file(file_path):
18-
_, ext = os.path.splitext(file_path)
19-
20-
if ext == ".rb":
21-
return RubyLexer
22-
elif ext == ".py":
23-
return PythonLexer
24-
elif ext == ".js":
25-
return JavaScriptLexer
26-
elif ext == ".go":
27-
return GoLexer
28-
else:
29-
raise ValueError(f"Unsupported file extension: {ext}")
30-
317

328
# this is the analyze function
339
def analyze_file(file_path: str, selected_stats=None):
@@ -56,21 +32,31 @@ def analyze_file(file_path: str, selected_stats=None):
5632

5733
# line count if requested
5834
if "line_count" in selected_stats:
35+
from spice.analyzers.count_lines import count_lines
5936
results["line_count"] = count_lines(code)
37+
38+
# comment line count if requested
39+
if "comment_line_count" in selected_stats:
40+
from spice.analyzers.count_comment_lines import count_comment_lines
41+
results["comment_line_count"] = count_comment_lines(code)
42+
43+
# @gtins botei sua funcao aqui pq ela usa o codigo raw e nao o tokenizado, ai so tirei ela ali de baixo pra nao ficar chamando o parser sem precisar
44+
# edit: ok i see whats going on, instead of appending the results to the resuls, this will itself print the results to the terminal
45+
# TODO: make analyze_code_structure return the results, then append those results to the results array
46+
if "identation_level" in selected_stats:
47+
analyze_code_structure(code)
6048

61-
# only put the code through the lexer and proceed with tokenization if we need function count or comment count (UPDATE THIS WHEN NEEDED PLEASE !!!!!!!!)
62-
if "function_count" in selected_stats or "comment_line_count" in selected_stats:
49+
# only put the code through the lexer and proceed with tokenization if we need function count (UPDATE THIS WHEN NEEDED PLEASE !!!!!!!!)
50+
if "function_count" in selected_stats:
51+
6352
# get the lexer for the code's language
53+
from spice.utils.get_lexer import get_lexer_for_file
6454
LexerClass = get_lexer_for_file(file_path)
6555

6656
# tokenize the code via lexer
6757
lexer = LexerClass(code)
6858
tokens = lexer.tokenize()
6959

70-
# process comment line count if requested
71-
if "comment_line_count" in selected_stats:
72-
results["comment_line_count"] = count_comment_lines(code)
73-
7460
# only put the code through the parser and proceed with parsing if we need function count (UPDATE THIS WHEN NEEDED PLEASE !!!!!!!!)
7561
if "function_count" in selected_stats:
7662

@@ -82,83 +68,20 @@ def analyze_file(file_path: str, selected_stats=None):
8268
ast = parser.parse()
8369

8470
# count functions
71+
from spice.analyzers.count_functions import count_functions
8572
results["function_count"] = count_functions(ast)
86-
if "identation_level" in selected_stats:
87-
analyze_code_structure(code)
8873

8974
return results
9075

9176

92-
# this will count lines straight from the raw code
93-
def count_lines(code):
94-
return code.count("\n") + 1
95-
96-
97-
# this will count functions in the AST
98-
def count_functions(ast):
99-
# import function definition from the parser's ast
100-
from parser.ast import FunctionDefinition, Program
101-
102-
if not isinstance(ast, Program):
103-
return 0
104-
105-
function_count = 0
106-
107-
# recursive search for function definitions in the AST
108-
def search_node(node):
109-
nonlocal function_count
110-
111-
if isinstance(node, FunctionDefinition):
112-
function_count += 1
113-
114-
# process child nodes if they exist
115-
if hasattr(node, 'statements') and node.statements:
116-
for statement in node.statements:
117-
search_node(statement)
118-
119-
if hasattr(node, 'body') and node.body:
120-
for body_statement in node.body:
121-
search_node(body_statement)
122-
123-
# for binary operation, check both sides
124-
if hasattr(node, 'left'):
125-
search_node(node.left)
126-
if hasattr(node, 'right'):
127-
search_node(node.right)
128-
129-
# check the value part of an assignment
130-
if hasattr(node, 'value'):
131-
search_node(node.value)
132-
133-
# check function call arguments
134-
if hasattr(node, 'arguments') and node.arguments:
135-
for arg in node.arguments:
136-
search_node(arg)
137-
138-
# start recursive search from the root Program node
139-
search_node(ast)
140-
141-
return function_count
14277

14378

144-
# this will count comment lines, since our AST/Parser doesn't include comment lines, this needs to be done in the tokenized output of the lexer
145-
# COMMENT LINE IS A LINE THAT EXCLUSIVELY HAS A COMMENT
146-
# so like: y = 5 #sets y to 5 IS NOT A COMMENT LINE!!!!!!!!
147-
def count_comment_lines(code):
148-
"""Count lines that are exclusively comments (no code on the same line)"""
149-
# split the code into lines
150-
lines = code.splitlines()
151-
comment_count = 0
152-
153-
for line in lines:
154-
# Remove leading whitespace
155-
stripped = line.strip()
156-
# Check if this line consists only of a comment
157-
if stripped and stripped.startswith('#'):
158-
comment_count += 1
159-
160-
return comment_count
16179

80+
# im not sure what to do with this part 😂
81+
# this is the identation analyzer
82+
# but it's not included in the menu?
83+
# im not going to change this since gtins knows better than me how this works
84+
# but this needs to be refactores and included directly into the analyze_file function and the analyze menu
16285
def analyze_code_structure(code):
16386
indentation_info = detect_indentation(code)
16487

@@ -167,4 +90,6 @@ def analyze_code_structure(code):
16790
for line, level in indentation_info["levels"]:
16891
# print(f"Indentation Level {level}: {line}")
16992
print(f"Detected Indentation Type: {indentation_info['indent_type']}")
170-
print(f"Detected Indentation Size: {indentation_info['indent_size']}")
93+
print(f"Detected Indentation Size: {indentation_info['indent_size']}")
94+
95+
# ----------------------------------------------------------------------------------------------------

spice/analyzers/__init__.py

Whitespace-only changes.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# this will count comment lines, since our AST/Parser doesn't include comment lines, this needs to be done in the tokenized output of the lexer
2+
# not sure about that first line, im pretty sure like about 200% sure this is analyzing the raw code and not the tokenized code but ok
3+
# COMMENT LINE IS A LINE THAT EXCLUSIVELY HAS A COMMENT
4+
# so like: y = 5 #sets y to 5 IS NOT A COMMENT LINE!!!!!!!!
5+
def count_comment_lines(code):
6+
"""Count lines that are exclusively comments (no code on the same line)"""
7+
# split the code into lines
8+
lines = code.splitlines()
9+
comment_count = 0
10+
11+
for line in lines:
12+
# Remove leading whitespace
13+
stripped = line.strip()
14+
# Check if this line consists only of a comment
15+
if stripped and stripped.startswith('#'):
16+
comment_count += 1
17+
18+
return comment_count

spice/analyzers/count_functions.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# this will count functions in the AST
2+
def count_functions(ast):
3+
# import function definition from the parser's ast
4+
from parser.ast import FunctionDefinition, Program
5+
6+
if not isinstance(ast, Program):
7+
return 0
8+
9+
function_count = 0
10+
11+
# recursive search for function definitions in the AST
12+
def search_node(node):
13+
nonlocal function_count
14+
15+
if isinstance(node, FunctionDefinition):
16+
function_count += 1
17+
18+
# process child nodes if they exist
19+
if hasattr(node, 'statements') and node.statements:
20+
for statement in node.statements:
21+
search_node(statement)
22+
23+
if hasattr(node, 'body') and node.body:
24+
for body_statement in node.body:
25+
search_node(body_statement)
26+
27+
# for binary operation, check both sides
28+
if hasattr(node, 'left'):
29+
search_node(node.left)
30+
if hasattr(node, 'right'):
31+
search_node(node.right)
32+
33+
# check the value part of an assignment
34+
if hasattr(node, 'value'):
35+
search_node(node.value)
36+
37+
# check function call arguments
38+
if hasattr(node, 'arguments') and node.arguments:
39+
for arg in node.arguments:
40+
search_node(arg)
41+
42+
# start recursive search from the root Program node
43+
search_node(ast)
44+
45+
return function_count

spice/analyzers/count_lines.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# this will count lines straight from the raw code
2+
def count_lines(code):
3+
return code.count("\n") + 1
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import os
21
import re
32

43
def detect_indentation(code):

spice/utils/__init__.py

Whitespace-only changes.

spice/utils/get_lexer.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import os
2+
3+
4+
# this will read the file extension and return the correct lexer
5+
def get_lexer_for_file(file_path):
6+
_, ext = os.path.splitext(file_path)
7+
8+
if ext == ".rb":
9+
from lexers.ruby.rubylexer import RubyLexer
10+
return RubyLexer
11+
12+
elif ext == ".py":
13+
from lexers.python.pythonlexer import PythonLexer
14+
return PythonLexer
15+
16+
elif ext == ".js":
17+
from lexers.javascript.javascriptlexer import JavaScriptLexer
18+
return JavaScriptLexer
19+
20+
elif ext == ".go":
21+
from lexers.golang.golexer import GoLexer
22+
return GoLexer
23+
24+
else:
25+
raise ValueError(f"Unsupported file extension: {ext}")

0 commit comments

Comments
 (0)