import gradio as gr import re import json from typing import Dict, List, Tuple, Optional from dataclasses import dataclass @dataclass class PineError: line_number: int error_type: str description: str suggestion: str severity: str class PineProfessionalFixer: def __init__(self): self.version_patterns = { 'v4': r'//@version\s*=\s*4', 'v5': r'//@version\s*=\s*5', 'v6': r'//@version\s*=\s*6' } # نقشه تبدیل توابع قدیمی به جدید self.function_migrations = { 'v4_to_v5': { 'study': 'indicator', 'security': 'request.security', 'tostring': 'str.tostring', 'tonumber': 'str.tonumber', 'input': 'input.int', 'hline': 'hline', 'alertcondition': 'alert' }, 'v5_to_v6': { 'syminfo.ticker': 'syminfo.tickerid', 'security': 'request.security' } } # الگوهای خطاهای رایج self.error_patterns = { 'syntax_errors': [ (r'(\w+)\s*\(\s*([^)]*)\s*\)\s*=>', r'\1(\2) =>'), # Arrow function syntax (r'(\w+)\s*\(\s*([^)]*)\s*\)\s*->', r'\1(\2) =>'), # Wrong arrow (r'var\s+(\w+)\s*=\s*([^=]+)(?!=)', r'var \1 = \2'), # var declarations (r'if\s*\(\s*([^)]+)\s*\)\s*{', r'if \1'), # if statements (r'for\s+(\w+)\s*=\s*([^;]+);([^;]+);([^{]+){', r'for \1 = \2 to \3'), # for loops ], 'indentation_errors': [ (r'^(\s{2,})(\S)', r' \2'), # Fix indentation to 4 spaces (r'^(\t+)(\S)', lambda m: ' ' * len(m.group(1)) + m.group(2)), # Convert tabs to spaces ], 'variable_errors': [ (r'(\w+)\s*:=\s*([^=]+)(?!=)', r'\1 := \2'), # Assignment operators (r'(\w+)\s*==\s*([^=]+)', r'\1 == \2'), # Comparison operators ] } def detect_version(self, code: str) -> str: """تشخیص ورژن Pine Script""" for version, pattern in self.version_patterns.items(): if re.search(pattern, code, re.IGNORECASE): return version return 'v5' # Default version def fix_syntax_errors(self, code: str) -> str: """تصحیح خطاهای نحوی""" fixed_code = code for pattern, replacement in self.error_patterns['syntax_errors']: fixed_code = re.sub(pattern, replacement, fixed_code, flags=re.MULTILINE) return fixed_code def fix_indentation(self, code: str) -> str: """تصحیح فاصله‌گذاری و تورفتگی""" lines = code.split('\n') fixed_lines = [] for line in lines: # حذف فاصله‌های اضافی در انتهای خط line = line.rstrip() # تصحیح تورفتگی if line.strip(): # محاسبه سطح تورفتگی indent_level = 0 for char in line: if char == ' ': indent_level += 1 elif char == '\t': indent_level += 4 else: break # تصحیح به مضارب 4 correct_indent = (indent_level // 4) * 4 fixed_line = ' ' * correct_indent + line.lstrip() fixed_lines.append(fixed_line) else: fixed_lines.append('') return '\n'.join(fixed_lines) def fix_variable_declarations(self, code: str) -> str: """تصحیح تعریف متغیرها""" fixed_code = code # تصحیح عملگرهای انتساب fixed_code = re.sub(r'(\w+)\s*:=\s*([^=\n]+)', r'\1 := \2', fixed_code) fixed_code = re.sub(r'(\w+)\s*=\s*([^=\n]+)', r'\1 = \2', fixed_code) return fixed_code def fix_function_calls(self, code: str, version: str) -> str: """تصحیح فراخوانی توابع بر اساس ورژن""" fixed_code = code if version == 'v4': # تبدیل از v4 به v5 for old_func, new_func in self.function_migrations['v4_to_v5'].items(): pattern = r'\b' + re.escape(old_func) + r'\b' fixed_code = re.sub(pattern, new_func, fixed_code) return fixed_code def fix_parentheses_and_brackets(self, code: str) -> str: """تصحیح پرانتزها و براکت‌ها""" fixed_code = code # تصحیح فاصله‌های اضافی در پرانتزها fixed_code = re.sub(r'\(\s+', '(', fixed_code) fixed_code = re.sub(r'\s+\)', ')', fixed_code) fixed_code = re.sub(r'\[\s+', '[', fixed_code) fixed_code = re.sub(r'\s+\]', ']', fixed_code) return fixed_code def fix_line_endings(self, code: str) -> str: """تصحیح پایان خطوط""" # تبدیل انواع مختلف line ending به Unix style fixed_code = code.replace('\r\n', '\n').replace('\r', '\n') # حذف خطوط خالی اضافی fixed_code = re.sub(r'\n{3,}', '\n\n', fixed_code) return fixed_code def validate_pine_structure(self, code: str, version: str) -> List[PineError]: """اعتبارسنجی ساختار کلی Pine Script""" errors = [] lines = code.split('\n') # بررسی وجود //@version if not re.search(r'//@version\s*=\s*[456]', code): errors.append(PineError( line_number=1, error_type="Version Missing", description="Version declaration is missing", suggestion="Add //@version=5 at the beginning", severity="Critical" )) # بررسی وجود indicator یا study has_main_declaration = False for i, line in enumerate(lines): if re.search(r'\b(indicator|study)\s*\(', line): has_main_declaration = True break if not has_main_declaration: errors.append(PineError( line_number=1, error_type="Main Declaration Missing", description="Missing indicator() or study() declaration", suggestion="Add indicator('Title') declaration", severity="Critical" )) return errors def fix_all_errors(self, code: str) -> Tuple[str, List[PineError], str]: """تصحیح همه خطاها""" if not code.strip(): return "", [], "❌ لطفاً کد Pine Script خود را وارد کنید" progress = "🔍 شروع تحلیل و تصحیح کد Pine Script...\n" # تشخیص ورژن version = self.detect_version(code) progress += f"📊 ورژن تشخیص داده شده: {version}\n" # مراحل تصحیح fixed_code = code progress += "🔧 تصحیح خطاهای نحوی...\n" fixed_code = self.fix_syntax_errors(fixed_code) progress += "📐 تصحیح فاصله‌گذاری و تورفتگی...\n" fixed_code = self.fix_indentation(fixed_code) progress += "🔤 تصحیح متغیرها...\n" fixed_code = self.fix_variable_declarations(fixed_code) progress += "⚙️ تصحیح فراخوانی توابع...\n" fixed_code = self.fix_function_calls(fixed_code, version) progress += "🔗 تصحیح پرانتزها و براکت‌ها...\n" fixed_code = self.fix_parentheses_and_brackets(fixed_code) progress += "📝 تصحیح پایان خطوط...\n" fixed_code = self.fix_line_endings(fixed_code) # اعتبارسنجی نهایی progress += "✅ اعتبارسنجی نهایی...\n" validation_errors = self.validate_pine_structure(fixed_code, version) progress += "🎯 تصحیح کامل شد!\n" return fixed_code, validation_errors, progress # ایجاد شیء فیکسر fixer = PineProfessionalFixer() def process_pine_code(input_code): """پردازش کد Pine Script""" if not input_code or not input_code.strip(): return "", "❌ لطفاً کد Pine Script خود را وارد کنید", "" try: fixed_code, errors, progress = fixer.fix_all_errors(input_code) # ایجاد گزارش خطاها error_report = "" if errors: error_report = "⚠️ خطاهای یافت شده:\n" for i, error in enumerate(errors, 1): error_report += f"{i}. خط {error.line_number}: {error.description}\n" error_report += f" پیشنهاد: {error.suggestion}\n" error_report += f" اهمیت: {error.severity}\n\n" else: error_report = "✅ هیچ خطای ساختاری یافت نشد!" # ایجاد پیام موفقیت success_message = """ 🎉 کد شما با موفقیت تصحیح شد! 📋 راهنمای استفاده: 1. کد تصحیح شده را از باکس زیر کپی کنید 2. در Pine Editor در TradingView پیست کنید 3. دکمه 'Add to Chart' را بزنید ✨ کد شما آماده استفاده است! """ return fixed_code, error_report, success_message except Exception as e: error_msg = f"❌ خطا در تصحیح کد: {str(e)}\nلطفاً کد خود را بررسی کنید و دوباره تلاش کنید." return "", error_msg, "" # تعریف رابط کاربری Gradio def create_interface(): with gr.Blocks(title="Pine Script Professional Fixer", theme=gr.themes.Soft()) as interface: gr.Markdown(""" # 🚀 Pine Script Professional Error Fixer ## ابزار حرفه‌ای تصحیح کدهای Pine Script **ویژگی‌ها:** - ✅ سازگار با ورژن‌های 4، 5 و 6 - 🔧 تصحیح خطاهای نحوی و ساختاری - 📐 بهینه‌سازی فاصله‌گذاری - ⚙️ تبدیل توابع قدیمی به جدید - 🎯 آماده برای استفاده در TradingView """) with gr.Row(): with gr.Column(scale=1): input_code = gr.Textbox( label="📝 کد Pine Script خود را اینجا وارد کنید:", placeholder="// مثال:\n//@version=5\nindicator('My Indicator')\nplot(close)", lines=15, max_lines=25 ) fix_button = gr.Button("🔧 تصحیح و بهینه‌سازی کد", variant="primary", size="lg") with gr.Column(scale=1): output_code = gr.Textbox( label="✅ کد تصحیح شده:", lines=15, max_lines=25, interactive=False ) with gr.Row(): error_report = gr.Textbox( label="📊 گزارش خطاها:", lines=5, interactive=False ) success_message = gr.Textbox( label="🎉 وضعیت:", lines=5, interactive=False ) # مثال‌های نمونه gr.Markdown(""" ## 📚 مثال‌های نمونه: **مثال ساده:** ```pine //@version=5 indicator("My RSI", shorttitle="RSI") rsi_value = ta.rsi(close, 14) plot(rsi_value, color=color.blue) hline(70, "Overbought", color=color.red) hline(30, "Oversold", color=color.green) ``` **نکات مهم:** - حتماً ورژن Pine Script را مشخص کنید - از indicator() یا study() استفاده کنید - فاصله‌گذاری صحیح را رعایت کنید """) # اتصال دکمه به تابع fix_button.click( fn=process_pine_code, inputs=[input_code], outputs=[output_code, error_report, success_message] ) return interface # اجرای برنامه if __name__ == "__main__": interface = create_interface() interface.launch( server_name="0.0.0.0", server_port=7860, share=True, show_error=True )