Spaces:
Running
Running
File size: 6,466 Bytes
7a21841 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
import os
import re
import sys
from graphviz import Digraph
import esprima
def detect_file_dependencies(root_dir):
"""
Menelusuri semua file dalam root_dir dan mendeteksi dependency sederhana.
Jika sebuah file (HTML) menautkan file lain (JS/CSS) melalui tag <script> atau <link>,
maka dependency tersebut dicatat.
"""
dep_graph = {}
for subdir, _, files in os.walk(root_dir):
for file in files:
ext = os.path.splitext(file)[1].lower()
if ext in ['.html', '.js', '.css']:
filepath = os.path.join(subdir, file)
try:
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
except Exception as e:
print(f"Error reading {filepath}: {e}")
continue
dependencies = []
if ext == '.html':
scripts = re.findall(r'<script\s+[^>]*src=["\'](.*?)["\']', content, re.IGNORECASE)
links = re.findall(r'<link\s+[^>]*href=["\'](.*?)["\']', content, re.IGNORECASE)
dependencies.extend(scripts)
dependencies.extend(links)
dep_graph[filepath] = dependencies
return dep_graph
def build_file_dependency_flowchart(dep_graph, output_file='results/project_file_dependencies'):
"""
Membuat diagram flowchart dependency antar file menggunakan Graphviz.
Jika string dependency (misalnya, 'script.js') ditemukan dalam nama file lain, dibuat edge.
"""
dot = Digraph(comment='Project File Dependencies')
for file in dep_graph:
dot.node(file, os.path.basename(file))
for file, deps in dep_graph.items():
for dep in deps:
for candidate in dep_graph:
if dep in os.path.basename(candidate):
dot.edge(file, candidate)
dot.render(output_file, view=True)
print(f"Diagram dependency file disimpan sebagai {output_file}.pdf")
def generate_full_js_flowchart(js_file):
"""
Menghasilkan flowchart yang mencoba mengidentifikasi seluruh _syntax_ yang mempengaruhi
alur kontrol pada file JavaScript dengan mengurai AST menggunakan esprima.
Node-node yang dihasilkan mencakup FunctionDeclaration, IfStatement, loop, SwitchStatement,
ReturnStatement, CallExpression, dan jenis node lainnya.
"""
try:
with open(js_file, 'r', encoding='utf-8') as f:
code = f.read()
except Exception as e:
print(f"Error reading {js_file}: {e}")
return None
try:
ast = esprima.parseScript(code, tolerant=True)
except Exception as e:
print(f"Error parsing {js_file}: {e}")
return None
flowchart = Digraph(comment=f'Full JS Flowchart: {os.path.basename(js_file)}')
node_counter = 0
def new_node(label):
nonlocal node_counter
node_id = f"node{node_counter}"
node_counter += 1
flowchart.node(node_id, label)
return node_id
def traverse_full(node, parent_node=None):
if isinstance(node, dict):
node_type = node.get('type')
current_node = None
if node_type == 'FunctionDeclaration':
func_name = node.get('id', {}).get('name', 'anonymous')
current_node = new_node(f'Function: {func_name}')
elif node_type == 'IfStatement':
current_node = new_node('If Statement')
elif node_type in ['ForStatement', 'WhileStatement', 'DoWhileStatement']:
current_node = new_node(node_type)
elif node_type == 'SwitchStatement':
current_node = new_node('Switch Statement')
elif node_type == 'ReturnStatement':
current_node = new_node('Return')
elif node_type == 'CallExpression':
callee = node.get('callee')
if callee and callee.get('type') == 'Identifier':
current_node = new_node(f'Call: {callee.get("name")}')
else:
current_node = new_node(node_type)
if parent_node and current_node:
flowchart.edge(parent_node, current_node)
new_parent = current_node if current_node else parent_node
for key, value in node.items():
if key in ['loc', 'range', 'raw']:
continue
traverse_full(value, parent_node=new_parent)
elif isinstance(node, list):
for item in node:
traverse_full(item, parent_node=parent_node)
traverse_full(ast.toDict(), parent_node=None)
return flowchart
def build_all_full_js_flowcharts(root_dir, output_folder='results/full_js_flowcharts'):
"""
Menelusuri seluruh file dalam root_dir, dan untuk setiap file JS menghasilkan flowchart
lengkap dari seluruh syntax yang mempengaruhi alur. Flowchart disimpan di output_folder.
"""
if not os.path.exists(output_folder):
os.makedirs(output_folder)
for subdir, _, files in os.walk(root_dir):
for file in files:
ext = os.path.splitext(file)[1].lower()
if ext == '.js':
js_file = os.path.join(subdir, file)
print(f"Memproses {js_file} untuk flowchart lengkap...")
flowchart = generate_full_js_flowchart(js_file)
if flowchart:
base_name = os.path.splitext(os.path.basename(js_file))[0]
output_name = os.path.join(output_folder, base_name + '_full_flowchart')
flowchart.render(output_name, view=False)
print(f"Flowchart lengkap untuk {js_file} disimpan sebagai {output_name}.pdf")
if __name__ == '__main__':
root_directory = '/content/drive/MyDrive/Developer/Project/Competition/Alhazen Coding Quest 20 Days Ramadhan Challenge/FINAL PROJECT'
dependency_graph = detect_file_dependencies(root_directory)
print("Dependency Graph Antar File:")
for file, deps in dependency_graph.items():
print(f"{file}: {deps}")
build_file_dependency_flowchart(dependency_graph)
build_all_full_js_flowcharts(root_directory)
sys.stdout.flush()
input("Tekan Enter untuk keluar...") |