SyedTahir's picture
Update app.py
8bc5435 verified
Raw History Blame Contribute Delete
13.9 kB
import gradio as gr
import os
from transformers import pipeline
import torch
import re
import ast
import traceback
# Initialize a more suitable model for code analysis
code_analyzer = None
def load_analyzer():
global code_analyzer
if code_analyzer is None:
try:
# Using a text generation model that's better for code analysis
code_analyzer = pipeline(
"text-generation",
model="Salesforce/codegen-350M-mono",
device=0 if torch.cuda.is_available() else -1
)
except:
code_analyzer = "fallback"
return code_analyzer
def check_python_syntax(code):
"""Check Python syntax errors"""
errors = []
try:
ast.parse(code)
except SyntaxError as e:
errors.append({
'type': 'Syntax Error',
'line': e.lineno,
'message': e.msg,
'text': e.text.strip() if e.text else ''
})
except Exception as e:
errors.append({
'type': 'Parse Error',
'line': None,
'message': str(e),
'text': ''
})
return errors
def check_common_errors(code, language):
"""Detect common coding errors"""
errors = []
lines = code.split('\n')
if language.lower() == 'python':
# Check for missing colons
for i, line in enumerate(lines, 1):
stripped = line.strip()
if stripped and not stripped.startswith('#'):
if any(stripped.startswith(kw) for kw in ['def ', 'class ', 'if ', 'elif ', 'else', 'for ', 'while ', 'try', 'except', 'finally', 'with ']):
if not stripped.endswith(':') and not stripped.endswith('\\'):
errors.append({
'type': 'Missing Colon',
'line': i,
'message': 'Missing colon at end of statement',
'text': stripped
})
# Check for missing parentheses
for i, line in enumerate(lines, 1):
if 'def ' in line or 'for ' in line or 'while ' in line:
if '(' not in line or ')' not in line:
errors.append({
'type': 'Missing Parentheses',
'line': i,
'message': 'Missing parentheses in statement',
'text': line.strip()
})
# Check for undefined variables (simple check)
defined_vars = set()
for i, line in enumerate(lines, 1):
# Track variable assignments
if '=' in line and not line.strip().startswith('#'):
parts = line.split('=')[0].strip()
if ' ' not in parts or parts.split()[0] in ['for']:
var_name = parts.split()[-1].strip('()')
defined_vars.add(var_name)
# Check for undefined variable usage
words = re.findall(r'\b[a-zA-Z_][a-zA-Z0-9_]*\b', line)
for word in words:
if word not in ['def', 'class', 'if', 'else', 'elif', 'for', 'while', 'in', 'return', 'print', 'len', 'range', 'str', 'int', 'float', 'list', 'dict', 'set', 'tuple']:
# Check if it looks like it's being used but not defined
if word not in defined_vars and f'{word}(' not in line and f'{word} =' not in line:
if re.search(rf'\b{word}\b(?!\s*=)(?!\s*\()', line):
errors.append({
'type': 'Potential Undefined Variable',
'line': i,
'message': f"Variable '{word}' may not be defined",
'text': line.strip()
})
return errors
def analyze_code_structure(code, language):
"""Analyze code structure and provide metrics"""
lines = code.split('\n')
total_lines = len(lines)
code_lines = len([l for l in lines if l.strip() and not l.strip().startswith('#') and not l.strip().startswith('//')])
comment_lines = len([l for l in lines if l.strip().startswith('#') or l.strip().startswith('//')])
blank_lines = total_lines - code_lines - comment_lines
# Calculate complexity
complexity_keywords = ['if', 'else', 'elif', 'for', 'while', 'switch', 'case', 'catch', 'try']
complexity = sum(code.lower().count(keyword) for keyword in complexity_keywords)
# Check for functions
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))
return {
'total_lines': total_lines,
'code_lines': code_lines,
'comment_lines': comment_lines,
'blank_lines': blank_lines,
'complexity': complexity,
'functions': func_count
}
def detect_vulnerabilities(code, language):
"""Detect common security vulnerabilities"""
vulnerabilities = []
patterns = {
'SQL Injection': [r'execute\s*\(.*\+.*\)', r'query\s*\(.*\+.*\)', r'SELECT.*\+.*FROM'],
'Hardcoded Secrets': [r'password\s*=\s*["\'][^"\']+["\']', r'api_key\s*=\s*["\'][^"\']+["\']', r'secret\s*=\s*["\'][^"\']+["\']'],
'Command Injection': [r'os\.system\s*\(', r'subprocess\.call\s*\(', r'eval\s*\(', r'exec\s*\('],
'Path Traversal': [r'\.\./', r'open\s*\(.*\+.*\)'],
'XSS Vulnerability': [r'innerHTML\s*=', r'document\.write\s*\('],
}
for vuln_type, pattern_list in patterns.items():
for pattern in pattern_list:
if re.search(pattern, code, re.IGNORECASE):
vulnerabilities.append(vuln_type)
break
return list(set(vulnerabilities))
def generate_smart_suggestions(code, language, errors):
"""Generate intelligent code suggestions based on detected issues"""
suggestions = []
# Suggestions based on errors
if errors:
suggestions.append("**Critical Issues Found:**")
for error in errors[:5]: # Limit to first 5 errors
suggestions.append(f"- Line {error['line']}: {error['type']} - {error['message']}")
if error['text']:
suggestions.append(f" ```{language.lower()}\n {error['text']}\n ```")
# Code quality suggestions
metrics = analyze_code_structure(code, language)
if metrics['comment_lines'] == 0 and metrics['code_lines'] > 5:
suggestions.append("\n**Documentation:**")
suggestions.append("- Add comments to explain complex logic")
suggestions.append("- Consider adding docstrings to functions")
if metrics['complexity'] > 10:
suggestions.append("\n**Complexity:**")
suggestions.append("- High cyclomatic complexity detected. Consider breaking down complex functions")
# Language-specific suggestions
if language.lower() == 'python':
if 'print(' in code and '+' in code:
suggestions.append("\n**String Formatting:**")
suggestions.append("- Use f-strings instead of string concatenation: `f'The average is {average}'`")
if not re.search(r'if\s+__name__\s*==\s*["\']__main__["\']', code) and metrics['code_lines'] > 10:
suggestions.append("\n**Best Practices:**")
suggestions.append("- Add `if __name__ == '__main__':` guard for script execution")
return "\n".join(suggestions) if suggestions else "Code looks good! Consider adding more comments for better maintainability."
def review_code(code, language):
"""Main code review function"""
if not code.strip():
return "⚠️ Please enter some code to review.", "", ""
# Check for syntax and common errors
all_errors = []
if language.lower() == 'python':
syntax_errors = check_python_syntax(code)
all_errors.extend(syntax_errors)
common_errors = check_common_errors(code, language)
all_errors.extend(common_errors)
# Analyze code structure
metrics = analyze_code_structure(code, language)
# Detect vulnerabilities
vulnerabilities = detect_vulnerabilities(code, language)
# Generate smart suggestions
suggestions = generate_smart_suggestions(code, language, all_errors)
# Format metrics output
quality_score = 100
if metrics['comment_lines'] == 0:
quality_score -= 20
if all_errors:
quality_score -= len(all_errors) * 10
if metrics['complexity'] > 10:
quality_score -= 15
quality_score = max(0, quality_score)
metrics_output = f"""## πŸ“Š Code Metrics
- **Total Lines:** {metrics['total_lines']}
- **Code Lines:** {metrics['code_lines']}
- **Comment Lines:** {metrics['comment_lines']}
- **Blank Lines:** {metrics['blank_lines']}
- **Functions:** {metrics['functions']}
- **Cyclomatic Complexity:** {metrics['complexity']}
- **Comment Ratio:** {(metrics['comment_lines'] / max(metrics['code_lines'], 1) * 100):.1f}%
- **Quality Score:** {quality_score}/100 {'🟒' if quality_score >= 70 else '🟑' if quality_score >= 40 else 'πŸ”΄'}
"""
# Format errors and vulnerabilities
issues_output = ""
if all_errors:
issues_output += "## ❌ Errors Detected\n\n"
for i, error in enumerate(all_errors[:10], 1): # Show first 10 errors
issues_output += f"{i}. **{error['type']}** (Line {error['line']})\n"
issues_output += f" - {error['message']}\n"
if error['text']:
issues_output += f" - Code: `{error['text']}`\n"
issues_output += "\n"
if vulnerabilities:
issues_output += "## πŸ”’ Security Vulnerabilities\n\n"
for vuln in vulnerabilities:
issues_output += f"- ⚠️ **{vuln}**\n"
issues_output += "\n**Recommendation:** Review and fix these security issues before deployment.\n"
if not all_errors and not vulnerabilities:
issues_output = "## βœ… No Critical Issues Detected\n\nNo syntax errors or obvious security issues found."
# Format suggestions
suggestions_output = f"""## πŸ’‘ Suggestions for Improvement
{suggestions}
### General Best Practices:
- Write unit tests for your functions
- Use meaningful variable and function names
- Keep functions small and focused (Single Responsibility Principle)
- Handle exceptions appropriately
- Follow {language} PEP 8 style guide (for Python) or equivalent standards
"""
return metrics_output, issues_output, suggestions_output
# Custom CSS
custom_css = """
#header {
text-align: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 30px;
border-radius: 10px;
margin-bottom: 20px;
color: white;
}
#header h1 {
margin: 0;
font-size: 2.5em;
font-weight: bold;
}
#header p {
margin: 10px 0 0 0;
font-size: 1.1em;
opacity: 0.9;
}
.footer {
text-align: center;
margin-top: 30px;
padding: 20px;
background: #f8f9fa;
border-radius: 10px;
}
.footer a {
color: #667eea;
text-decoration: none;
font-weight: bold;
margin: 0 10px;
}
.footer a:hover {
text-decoration: underline;
}
"""
# Create Gradio interface
with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
gr.HTML("""
<div id="header">
<h1>πŸ” STHASI Code Review Assistant</h1>
<p>AI-Powered Code Analysis, Quality Metrics & Security Vulnerability Detection</p>
</div>
""")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### πŸ“ Input Code")
language = gr.Dropdown(
choices=["Python", "JavaScript", "Java", "C++", "C#", "Go", "Ruby", "PHP", "TypeScript", "Swift"],
value="Python",
label="Programming Language"
)
code_input = gr.Code(
label="Paste your code here",
language="python",
lines=15
)
review_btn = gr.Button("πŸš€ Review Code", variant="primary", size="lg")
gr.Markdown("""
### πŸ“Œ Features:
- **Syntax error detection**
- **Code quality metrics**
- **Security vulnerability scan**
- **Smart improvement suggestions**
- **Multi-language support**
""")
with gr.Row():
with gr.Column():
metrics_output = gr.Markdown(label="Code Metrics")
with gr.Row():
with gr.Column():
issues_output = gr.Markdown(label="Issues & Security")
with gr.Row():
with gr.Column():
suggestions_output = gr.Markdown(label="Suggestions")
gr.HTML("""
<div class="footer">
<a href="https://www.linkedin.com/in/syedtahirhussan/" target="_blank">πŸ”— LinkedIn</a>
<a href="https://github.com/SyedTahirHussan" target="_blank">πŸ’» GitHub</a>
<p style="font-size: 0.9em; margin-top: 10px; color: black;">Built with ❀️ by <a href="https://www.linkedin.com/in/syedtahirhussan/" target="_blank" style="color: black; text-decoration: underline;">Syed Tahir Hussan</a></p>
<p style="margin-top: 15px; color: #666;">Powered by Advanced Static Analysis | Gradio 5.49.1</p>
</div>
""")
review_btn.click(
fn=review_code,
inputs=[code_input, language],
outputs=[metrics_output, issues_output, suggestions_output]
)
language.change(
fn=lambda x: gr.Code(language=x.lower()),
inputs=[language],
outputs=[code_input]
)
if __name__ == "__main__":
demo.launch()