SyedTahir commited on
Commit
ff5f981
Β·
verified Β·
1 Parent(s): 2a6ede0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +193 -81
app.py CHANGED
@@ -1,24 +1,104 @@
1
  import gradio as gr
2
  import os
3
- from transformers import AutoTokenizer, AutoModelForCausalLM
4
  import torch
5
  import re
 
 
6
 
7
- # Initialize model and tokenizer
8
- MODEL_NAME = "bigcode/starcoderbase-1b"
9
- tokenizer = None
10
- model = None
11
 
12
- def load_model():
13
- global tokenizer, model
14
- if tokenizer is None:
15
- tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
16
- model = AutoModelForCausalLM.from_pretrained(
17
- MODEL_NAME,
18
- torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
19
- device_map="auto"
20
- )
21
- return tokenizer, model
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
  def analyze_code_structure(code, language):
24
  """Analyze code structure and provide metrics"""
@@ -28,23 +108,26 @@ def analyze_code_structure(code, language):
28
  comment_lines = len([l for l in lines if l.strip().startswith('#') or l.strip().startswith('//')])
29
  blank_lines = total_lines - code_lines - comment_lines
30
 
31
- # Calculate complexity (simple heuristic)
32
  complexity_keywords = ['if', 'else', 'elif', 'for', 'while', 'switch', 'case', 'catch', 'try']
33
  complexity = sum(code.lower().count(keyword) for keyword in complexity_keywords)
34
 
 
 
 
35
  return {
36
  'total_lines': total_lines,
37
  'code_lines': code_lines,
38
  'comment_lines': comment_lines,
39
  'blank_lines': blank_lines,
40
- 'complexity': complexity
 
41
  }
42
 
43
  def detect_vulnerabilities(code, language):
44
  """Detect common security vulnerabilities"""
45
  vulnerabilities = []
46
 
47
- # Common vulnerability patterns
48
  patterns = {
49
  'SQL Injection': [r'execute\s*\(.*\+.*\)', r'query\s*\(.*\+.*\)', r'SELECT.*\+.*FROM'],
50
  'Hardcoded Secrets': [r'password\s*=\s*["\'][^"\']+["\']', r'api_key\s*=\s*["\'][^"\']+["\']', r'secret\s*=\s*["\'][^"\']+["\']'],
@@ -61,89 +144,122 @@ def detect_vulnerabilities(code, language):
61
 
62
  return list(set(vulnerabilities))
63
 
64
- def generate_ai_suggestions(code, language):
65
- """Generate AI-powered code suggestions"""
66
- try:
67
- tokenizer, model = load_model()
68
-
69
- prompt = f"""# Code Review for {language}
70
- # Analyze the following code and provide suggestions for improvement:
71
-
72
- {code[:500]} # Limit input for faster processing
73
-
74
- # Suggestions:
75
- 1."""
76
-
77
- inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=512)
78
-
79
- with torch.no_grad():
80
- outputs = model.generate(
81
- **inputs,
82
- max_new_tokens=200,
83
- temperature=0.7,
84
- do_sample=True,
85
- top_p=0.95,
86
- pad_token_id=tokenizer.eos_token_id
87
- )
88
-
89
- suggestion = tokenizer.decode(outputs[0], skip_special_tokens=True)
90
- # Extract only the generated part
91
- suggestion = suggestion.split("# Suggestions:")[-1].strip()
92
-
93
- return suggestion if suggestion else "Consider adding more comments and following best practices for code readability."
94
 
95
- except Exception as e:
96
- return f"AI suggestion generation in progress... Meanwhile, consider: proper error handling, code documentation, and following {language} best practices."
 
 
 
97
 
98
  def review_code(code, language):
99
  """Main code review function"""
100
  if not code.strip():
101
  return "⚠️ Please enter some code to review.", "", ""
102
 
 
 
 
 
 
 
 
 
 
103
  # Analyze code structure
104
  metrics = analyze_code_structure(code, language)
105
 
106
  # Detect vulnerabilities
107
  vulnerabilities = detect_vulnerabilities(code, language)
108
 
109
- # Generate AI suggestions
110
- ai_suggestions = generate_ai_suggestions(code, language)
111
 
112
  # Format metrics output
 
 
 
 
 
 
 
 
 
113
  metrics_output = f"""## πŸ“Š Code Metrics
114
 
115
  - **Total Lines:** {metrics['total_lines']}
116
  - **Code Lines:** {metrics['code_lines']}
117
  - **Comment Lines:** {metrics['comment_lines']}
118
  - **Blank Lines:** {metrics['blank_lines']}
 
119
  - **Cyclomatic Complexity:** {metrics['complexity']}
120
  - **Comment Ratio:** {(metrics['comment_lines'] / max(metrics['code_lines'], 1) * 100):.1f}%
 
121
  """
122
 
123
- # Format vulnerabilities output
 
 
 
 
 
 
 
 
 
 
 
124
  if vulnerabilities:
125
- vuln_output = "## πŸ”’ Security Vulnerabilities Detected\n\n"
126
  for vuln in vulnerabilities:
127
- vuln_output += f"- ⚠️ **{vuln}**\n"
128
- vuln_output += "\n**Recommendation:** Review and fix these security issues before deployment."
129
- else:
130
- vuln_output = "## βœ… No Common Vulnerabilities Detected\n\nNo obvious security issues found. However, always perform thorough security testing."
 
131
 
132
- # Format AI suggestions
133
- suggestions_output = f"""## πŸ€– AI-Powered Suggestions
134
 
135
- {ai_suggestions}
136
 
137
  ### General Best Practices:
138
- - Ensure proper error handling
139
- - Add comprehensive documentation
140
- - Follow {language} coding standards
141
- - Write unit tests for critical functions
142
- - Use meaningful variable names
143
- - Keep functions small and focused
144
  """
145
 
146
- return metrics_output, vuln_output, suggestions_output
147
 
148
  # Custom CSS
149
  custom_css = """
@@ -190,7 +306,6 @@ custom_css = """
190
 
191
  # Create Gradio interface
192
  with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
193
- # Header
194
  gr.HTML("""
195
  <div id="header">
196
  <h1>πŸ” STHASI Code Review Assistant</h1>
@@ -216,10 +331,11 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
216
 
217
  gr.Markdown("""
218
  ### πŸ“Œ Features:
219
- - Code quality metrics
220
- - Security vulnerability detection
221
- - AI-powered suggestions
222
- - Multi-language support
 
223
  """)
224
 
225
  with gr.Row():
@@ -228,36 +344,32 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
228
 
229
  with gr.Row():
230
  with gr.Column():
231
- vuln_output = gr.Markdown(label="Security Analysis")
232
 
233
  with gr.Row():
234
  with gr.Column():
235
- suggestions_output = gr.Markdown(label="AI Suggestions")
236
 
237
- # Footer
238
  gr.HTML("""
239
  <div class="footer">
240
  <p><strong>Connect with me:</strong></p>
241
  <a href="https://www.linkedin.com/in/syedtahirhussan/" target="_blank">πŸ”— LinkedIn</a>
242
  <a href="https://github.com/SyedTahirHussan" target="_blank">πŸ’» GitHub</a>
243
- <p style="margin-top: 15px; color: #666;">Powered by StarCoder AI Model | Gradio 5.49.1</p>
244
  </div>
245
  """)
246
 
247
- # Event handler
248
  review_btn.click(
249
  fn=review_code,
250
  inputs=[code_input, language],
251
- outputs=[metrics_output, vuln_output, suggestions_output]
252
  )
253
 
254
- # Update code editor language when dropdown changes
255
  language.change(
256
  fn=lambda x: gr.Code(language=x.lower()),
257
  inputs=[language],
258
  outputs=[code_input]
259
  )
260
 
261
- # Launch the app
262
  if __name__ == "__main__":
263
  demo.launch()
 
1
  import gradio as gr
2
  import os
3
+ from transformers import pipeline
4
  import torch
5
  import re
6
+ import ast
7
+ import traceback
8
 
9
+ # Initialize a more suitable model for code analysis
10
+ code_analyzer = None
 
 
11
 
12
+ def load_analyzer():
13
+ global code_analyzer
14
+ if code_analyzer is None:
15
+ try:
16
+ # Using a text generation model that's better for code analysis
17
+ code_analyzer = pipeline(
18
+ "text-generation",
19
+ model="Salesforce/codegen-350M-mono",
20
+ device=0 if torch.cuda.is_available() else -1
21
+ )
22
+ except:
23
+ code_analyzer = "fallback"
24
+ return code_analyzer
25
+
26
+ def check_python_syntax(code):
27
+ """Check Python syntax errors"""
28
+ errors = []
29
+ try:
30
+ ast.parse(code)
31
+ except SyntaxError as e:
32
+ errors.append({
33
+ 'type': 'Syntax Error',
34
+ 'line': e.lineno,
35
+ 'message': e.msg,
36
+ 'text': e.text.strip() if e.text else ''
37
+ })
38
+ except Exception as e:
39
+ errors.append({
40
+ 'type': 'Parse Error',
41
+ 'line': None,
42
+ 'message': str(e),
43
+ 'text': ''
44
+ })
45
+ return errors
46
+
47
+ def check_common_errors(code, language):
48
+ """Detect common coding errors"""
49
+ errors = []
50
+ lines = code.split('\n')
51
+
52
+ if language.lower() == 'python':
53
+ # Check for missing colons
54
+ for i, line in enumerate(lines, 1):
55
+ stripped = line.strip()
56
+ if stripped and not stripped.startswith('#'):
57
+ if any(stripped.startswith(kw) for kw in ['def ', 'class ', 'if ', 'elif ', 'else', 'for ', 'while ', 'try', 'except', 'finally', 'with ']):
58
+ if not stripped.endswith(':') and not stripped.endswith('\\'):
59
+ errors.append({
60
+ 'type': 'Missing Colon',
61
+ 'line': i,
62
+ 'message': 'Missing colon at end of statement',
63
+ 'text': stripped
64
+ })
65
+
66
+ # Check for missing parentheses
67
+ for i, line in enumerate(lines, 1):
68
+ if 'def ' in line or 'for ' in line or 'while ' in line:
69
+ if '(' not in line or ')' not in line:
70
+ errors.append({
71
+ 'type': 'Missing Parentheses',
72
+ 'line': i,
73
+ 'message': 'Missing parentheses in statement',
74
+ 'text': line.strip()
75
+ })
76
+
77
+ # Check for undefined variables (simple check)
78
+ defined_vars = set()
79
+ for i, line in enumerate(lines, 1):
80
+ # Track variable assignments
81
+ if '=' in line and not line.strip().startswith('#'):
82
+ parts = line.split('=')[0].strip()
83
+ if ' ' not in parts or parts.split()[0] in ['for']:
84
+ var_name = parts.split()[-1].strip('()')
85
+ defined_vars.add(var_name)
86
+
87
+ # Check for undefined variable usage
88
+ words = re.findall(r'\b[a-zA-Z_][a-zA-Z0-9_]*\b', line)
89
+ for word in words:
90
+ if word not in ['def', 'class', 'if', 'else', 'elif', 'for', 'while', 'in', 'return', 'print', 'len', 'range', 'str', 'int', 'float', 'list', 'dict', 'set', 'tuple']:
91
+ # Check if it looks like it's being used but not defined
92
+ if word not in defined_vars and f'{word}(' not in line and f'{word} =' not in line:
93
+ if re.search(rf'\b{word}\b(?!\s*=)(?!\s*\()', line):
94
+ errors.append({
95
+ 'type': 'Potential Undefined Variable',
96
+ 'line': i,
97
+ 'message': f"Variable '{word}' may not be defined",
98
+ 'text': line.strip()
99
+ })
100
+
101
+ return errors
102
 
103
  def analyze_code_structure(code, language):
104
  """Analyze code structure and provide metrics"""
 
108
  comment_lines = len([l for l in lines if l.strip().startswith('#') or l.strip().startswith('//')])
109
  blank_lines = total_lines - code_lines - comment_lines
110
 
111
+ # Calculate complexity
112
  complexity_keywords = ['if', 'else', 'elif', 'for', 'while', 'switch', 'case', 'catch', 'try']
113
  complexity = sum(code.lower().count(keyword) for keyword in complexity_keywords)
114
 
115
+ # Check for functions
116
+ func_count = len(re.findall(r'\bdef\s+\w+\s*\(', code)) if language.lower() == 'python' else len(re.findall(r'\bfunction\s+\w+\s*\(', code))
117
+
118
  return {
119
  'total_lines': total_lines,
120
  'code_lines': code_lines,
121
  'comment_lines': comment_lines,
122
  'blank_lines': blank_lines,
123
+ 'complexity': complexity,
124
+ 'functions': func_count
125
  }
126
 
127
  def detect_vulnerabilities(code, language):
128
  """Detect common security vulnerabilities"""
129
  vulnerabilities = []
130
 
 
131
  patterns = {
132
  'SQL Injection': [r'execute\s*\(.*\+.*\)', r'query\s*\(.*\+.*\)', r'SELECT.*\+.*FROM'],
133
  'Hardcoded Secrets': [r'password\s*=\s*["\'][^"\']+["\']', r'api_key\s*=\s*["\'][^"\']+["\']', r'secret\s*=\s*["\'][^"\']+["\']'],
 
144
 
145
  return list(set(vulnerabilities))
146
 
147
+ def generate_smart_suggestions(code, language, errors):
148
+ """Generate intelligent code suggestions based on detected issues"""
149
+ suggestions = []
150
+
151
+ # Suggestions based on errors
152
+ if errors:
153
+ suggestions.append("**Critical Issues Found:**")
154
+ for error in errors[:5]: # Limit to first 5 errors
155
+ suggestions.append(f"- Line {error['line']}: {error['type']} - {error['message']}")
156
+ if error['text']:
157
+ suggestions.append(f" ```{language.lower()}\n {error['text']}\n ```")
158
+
159
+ # Code quality suggestions
160
+ metrics = analyze_code_structure(code, language)
161
+
162
+ if metrics['comment_lines'] == 0 and metrics['code_lines'] > 5:
163
+ suggestions.append("\n**Documentation:**")
164
+ suggestions.append("- Add comments to explain complex logic")
165
+ suggestions.append("- Consider adding docstrings to functions")
166
+
167
+ if metrics['complexity'] > 10:
168
+ suggestions.append("\n**Complexity:**")
169
+ suggestions.append("- High cyclomatic complexity detected. Consider breaking down complex functions")
170
+
171
+ # Language-specific suggestions
172
+ if language.lower() == 'python':
173
+ if 'print(' in code and '+' in code:
174
+ suggestions.append("\n**String Formatting:**")
175
+ suggestions.append("- Use f-strings instead of string concatenation: `f'The average is {average}'`")
 
176
 
177
+ if not re.search(r'if\s+__name__\s*==\s*["\']__main__["\']', code) and metrics['code_lines'] > 10:
178
+ suggestions.append("\n**Best Practices:**")
179
+ suggestions.append("- Add `if __name__ == '__main__':` guard for script execution")
180
+
181
+ return "\n".join(suggestions) if suggestions else "Code looks good! Consider adding more comments for better maintainability."
182
 
183
  def review_code(code, language):
184
  """Main code review function"""
185
  if not code.strip():
186
  return "⚠️ Please enter some code to review.", "", ""
187
 
188
+ # Check for syntax and common errors
189
+ all_errors = []
190
+ if language.lower() == 'python':
191
+ syntax_errors = check_python_syntax(code)
192
+ all_errors.extend(syntax_errors)
193
+
194
+ common_errors = check_common_errors(code, language)
195
+ all_errors.extend(common_errors)
196
+
197
  # Analyze code structure
198
  metrics = analyze_code_structure(code, language)
199
 
200
  # Detect vulnerabilities
201
  vulnerabilities = detect_vulnerabilities(code, language)
202
 
203
+ # Generate smart suggestions
204
+ suggestions = generate_smart_suggestions(code, language, all_errors)
205
 
206
  # Format metrics output
207
+ quality_score = 100
208
+ if metrics['comment_lines'] == 0:
209
+ quality_score -= 20
210
+ if all_errors:
211
+ quality_score -= len(all_errors) * 10
212
+ if metrics['complexity'] > 10:
213
+ quality_score -= 15
214
+ quality_score = max(0, quality_score)
215
+
216
  metrics_output = f"""## πŸ“Š Code Metrics
217
 
218
  - **Total Lines:** {metrics['total_lines']}
219
  - **Code Lines:** {metrics['code_lines']}
220
  - **Comment Lines:** {metrics['comment_lines']}
221
  - **Blank Lines:** {metrics['blank_lines']}
222
+ - **Functions:** {metrics['functions']}
223
  - **Cyclomatic Complexity:** {metrics['complexity']}
224
  - **Comment Ratio:** {(metrics['comment_lines'] / max(metrics['code_lines'], 1) * 100):.1f}%
225
+ - **Quality Score:** {quality_score}/100 {'🟒' if quality_score >= 70 else '🟑' if quality_score >= 40 else 'πŸ”΄'}
226
  """
227
 
228
+ # Format errors and vulnerabilities
229
+ issues_output = ""
230
+
231
+ if all_errors:
232
+ issues_output += "## ❌ Errors Detected\n\n"
233
+ for i, error in enumerate(all_errors[:10], 1): # Show first 10 errors
234
+ issues_output += f"{i}. **{error['type']}** (Line {error['line']})\n"
235
+ issues_output += f" - {error['message']}\n"
236
+ if error['text']:
237
+ issues_output += f" - Code: `{error['text']}`\n"
238
+ issues_output += "\n"
239
+
240
  if vulnerabilities:
241
+ issues_output += "## πŸ”’ Security Vulnerabilities\n\n"
242
  for vuln in vulnerabilities:
243
+ issues_output += f"- ⚠️ **{vuln}**\n"
244
+ issues_output += "\n**Recommendation:** Review and fix these security issues before deployment.\n"
245
+
246
+ if not all_errors and not vulnerabilities:
247
+ issues_output = "## βœ… No Critical Issues Detected\n\nNo syntax errors or obvious security issues found."
248
 
249
+ # Format suggestions
250
+ suggestions_output = f"""## πŸ’‘ Suggestions for Improvement
251
 
252
+ {suggestions}
253
 
254
  ### General Best Practices:
255
+ - Write unit tests for your functions
256
+ - Use meaningful variable and function names
257
+ - Keep functions small and focused (Single Responsibility Principle)
258
+ - Handle exceptions appropriately
259
+ - Follow {language} PEP 8 style guide (for Python) or equivalent standards
 
260
  """
261
 
262
+ return metrics_output, issues_output, suggestions_output
263
 
264
  # Custom CSS
265
  custom_css = """
 
306
 
307
  # Create Gradio interface
308
  with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
 
309
  gr.HTML("""
310
  <div id="header">
311
  <h1>πŸ” STHASI Code Review Assistant</h1>
 
331
 
332
  gr.Markdown("""
333
  ### πŸ“Œ Features:
334
+ - **Syntax error detection**
335
+ - **Code quality metrics**
336
+ - **Security vulnerability scan**
337
+ - **Smart improvement suggestions**
338
+ - **Multi-language support**
339
  """)
340
 
341
  with gr.Row():
 
344
 
345
  with gr.Row():
346
  with gr.Column():
347
+ issues_output = gr.Markdown(label="Issues & Security")
348
 
349
  with gr.Row():
350
  with gr.Column():
351
+ suggestions_output = gr.Markdown(label="Suggestions")
352
 
 
353
  gr.HTML("""
354
  <div class="footer">
355
  <p><strong>Connect with me:</strong></p>
356
  <a href="https://www.linkedin.com/in/syedtahirhussan/" target="_blank">πŸ”— LinkedIn</a>
357
  <a href="https://github.com/SyedTahirHussan" target="_blank">πŸ’» GitHub</a>
358
+ <p style="margin-top: 15px; color: #666;">Powered by Advanced Static Analysis | Gradio 5.49.1</p>
359
  </div>
360
  """)
361
 
 
362
  review_btn.click(
363
  fn=review_code,
364
  inputs=[code_input, language],
365
+ outputs=[metrics_output, issues_output, suggestions_output]
366
  )
367
 
 
368
  language.change(
369
  fn=lambda x: gr.Code(language=x.lower()),
370
  inputs=[language],
371
  outputs=[code_input]
372
  )
373
 
 
374
  if __name__ == "__main__":
375
  demo.launch()